diff mbox series

Fix PR88029, change how gimple_call_flags works

Message ID alpine.LSU.2.20.1811151146210.1827@zhemvz.fhfr.qr
State New
Headers show
Series Fix PR88029, change how gimple_call_flags works | expand

Commit Message

Richard Biener Nov. 15, 2018, 10:50 a.m. UTC
The following makes sure we preserve a 'const' attribute that
was in effect on an indirect call even after turning it into
a direct call of a non-const (pure for the testcase) function.
This mimics how we handle nothrow/noreturn.

By unioning ECF_ flags from fntype and decl we get the best
of both worlds (for optimization as well as IL consistency).
This seemed easier (and better) than introducing pure/const
flags on the gimple stmt (as opposed to nothrow which can
come in via -fno-exceptions on a function as well).

I skimmed over flags_from_decl_or_type users to see which
might need updating to simply use gimple_call_flags but
only found bitrotting TM code (which I updated).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2018-11-15  Richard Biener  <rguenther@suse.de>

	PR middle-end/
	* gimple.c (gimple_call_flags): Union flags from decl, type
	and call fntype.
	* trans-mem.c (is_tm_pure_call): Simplify.

	* gcc.dg/tree-ssa/pr88029.c: New testcase.
diff mbox series

Patch

diff --git a/gcc/gimple.c b/gcc/gimple.c
index 41d9f677c4f..23ccbae6bcb 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1446,15 +1446,17 @@  gimple_call_same_target_p (const gimple *c1, const gimple *c2)
 int
 gimple_call_flags (const gimple *stmt)
 {
-  int flags;
-  tree decl = gimple_call_fndecl (stmt);
+  int flags = 0;
 
-  if (decl)
-    flags = flags_from_decl_or_type (decl);
-  else if (gimple_call_internal_p (stmt))
+  if (gimple_call_internal_p (stmt))
     flags = internal_fn_flags (gimple_call_internal_fn (stmt));
   else
-    flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
+    {
+      tree decl = gimple_call_fndecl (stmt);
+      if (decl)
+	flags = flags_from_decl_or_type (decl);
+      flags |= flags_from_decl_or_type (gimple_call_fntype (stmt));
+    }
 
   if (stmt->subcode & GF_CALL_NOTHROW)
     flags |= ECF_NOTHROW;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88029.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88029.c
new file mode 100644
index 00000000000..c169dd543cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88029.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -w -fdump-tree-fre1-vops" } */
+
+double foo (double) __attribute__ ((pure));
+double (*fp) (double) __attribute__ ((const));
+double f(double a)
+{
+  fp = foo;
+  /* Verify when propagating foo to the call we preserve its constness.  */
+  return fp (a);
+}
+
+/* { dg-final { scan-tree-dump "foo \\(a" "fre1" } } */
+/* { dg-final { scan-tree-dump-times "VUSE" 1 "fre1" } } */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 938f4e28b90..bb7146bc153 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -265,20 +265,7 @@  is_tm_safe (const_tree x)
 static bool
 is_tm_pure_call (gimple *call)
 {
-  if (gimple_call_internal_p (call))
-    return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0;
-
-  tree fn = gimple_call_fn (call);
-
-  if (TREE_CODE (fn) == ADDR_EXPR)
-    {
-      fn = TREE_OPERAND (fn, 0);
-      gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
-    }
-  else
-    fn = TREE_TYPE (fn);
-
-  return is_tm_pure (fn);
+  return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0;
 }
 
 /* Return true if X has been marked TM_CALLABLE.  */