tree-optimization/106912 - clear const attribute from fntype
authorRichard Biener <rguenther@suse.de>
Thu, 16 Mar 2023 12:51:19 +0000 (13:51 +0100)
committerRichard Biener <rguenther@suse.de>
Fri, 24 Mar 2023 12:52:38 +0000 (13:52 +0100)
The following makes sure that after clearing pure/const from
instrumented function declarations we are adjusting call statements
fntype as well to handle indirect calls and because gimple_call_flags
looks at both decl and fntype.

Like the pure/const flag clearing on decls we refrain from touching
calls to known functions that do not have a body in the current TU.

PR tree-optimization/106912
* tree-profile.cc (tree_profiling): Update stmts only when
profiling or testing coverage.  Make sure to update calls
fntype, stripping 'const' there.

* gcc.dg/profile-generate-4.c: New testcase.

gcc/testsuite/gcc.dg/profile-generate-4.c [new file with mode: 0644]
gcc/tree-profile.cc

diff --git a/gcc/testsuite/gcc.dg/profile-generate-4.c b/gcc/testsuite/gcc.dg/profile-generate-4.c
new file mode 100644 (file)
index 0000000..c2b999f
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR106912 */
+/* { dg-require-profiling "-fprofile-generate" } */
+/* { dg-options "-O2 -fprofile-generate -ftree-vectorize" } */
+
+__attribute__ ((__simd__))
+__attribute__ ((__nothrow__ , __leaf__ , __const__, __noinline__))
+double foo (double x);
+
+void bar(double *f, int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    f[i] = foo(f[i]);
+}
+
+double foo(double x)
+{
+  return x * x / 3.0;
+}
index ea9d7a2..6f9a43e 100644 (file)
@@ -835,16 +835,36 @@ tree_profiling (void)
 
       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 
-      FOR_EACH_BB_FN (bb, cfun)
-       {
-         gimple_stmt_iterator gsi;
-         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-           {
-             gimple *stmt = gsi_stmt (gsi);
-             if (is_gimple_call (stmt))
-               update_stmt (stmt);
-           }
-       }
+      if (profile_arc_flag || flag_test_coverage)
+       FOR_EACH_BB_FN (bb, cfun)
+         {
+           gimple_stmt_iterator gsi;
+           for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+             {
+               gcall *call = dyn_cast <gcall *> (gsi_stmt (gsi));
+               if (!call)
+                 continue;
+
+               /* We do not clear pure/const on decls without body.  */
+               tree fndecl = gimple_call_fndecl (call);
+               if (fndecl && !gimple_has_body_p (fndecl))
+                 continue;
+
+               /* Drop the const attribute from the call type (the pure
+                  attribute is not available on types).  */
+               tree fntype = gimple_call_fntype (call);
+               if (fntype && TYPE_READONLY (fntype))
+                 {
+                   int quals = TYPE_QUALS (fntype) & ~TYPE_QUAL_CONST;
+                   fntype = build_qualified_type (fntype, quals);
+                   gimple_call_set_fntype (call, fntype);
+                 }
+
+               /* Update virtual operands of calls to no longer const/pure
+                  functions.  */
+               update_stmt (call);
+             }
+         }
 
       /* re-merge split blocks.  */
       cleanup_tree_cfg ();