tree-ssa-sccvn.c (visit_reference_op_call): Value number virtual definition to virtua...
authorRichard Biener <rguenther@suse.de>
Fri, 23 Sep 2016 12:39:05 +0000 (12:39 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 23 Sep 2016 12:39:05 +0000 (12:39 +0000)
2016-09-23  Richard Biener  <rguenther@suse.de>

* tree-ssa-sccvn.c (visit_reference_op_call): Value number
virtual definition to virtual use if the call devirtualizes
to a const or pure function.
(visit_use): Also visit calls we can devirtualize to a
const or pure function.

* gcc.dg/tree-ssa/ssa-fre-56.c: New testcase.

From-SVN: r240431

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index 2c4cf43..914624d 100644 (file)
@@ -1,5 +1,13 @@
 2016-09-23  Richard Biener  <rguenther@suse.de>
 
+       * tree-ssa-sccvn.c (visit_reference_op_call): Value number
+       virtual definition to virtual use if the call devirtualizes
+       to a const or pure function.
+       (visit_use): Also visit calls we can devirtualize to a
+       const or pure function.
+
+2016-09-23  Richard Biener  <rguenther@suse.de>
+
        PR tree-optimization/77697
        * tree-ssa-forwprop.c (defcodefor_name): Remove bogus code,
        signal error if we have sth ternary or unhandled.
index 8305520..7a87fea 100644 (file)
@@ -1,3 +1,7 @@
+2016-09-23  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/ssa-fre-56.c: New testcase.
+
 2016-09-23  Matthew Wahab  <matthew.wahab@arm.com>
 
        * gcc.target/advsimd-intrinsics/advsimd-intrinsics.exp: Enable
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c
new file mode 100644 (file)
index 0000000..49c6fa1
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+int x = 1;
+int __attribute__((noinline,noclone)) fn ()
+{
+  return x;
+}
+int (*f)();
+int main ()
+{
+  int res;
+  f = fn;
+  x = 0;
+  res = f ();
+  res += x;
+  if (res != 0)
+    __builtin_abort ();
+  return 0;
+}
+
+/* We should be able to optimize the load from x in main and thus the
+   addition.  */
+
+/* { dg-final { scan-tree-dump-times "= x;" 1 "fre1" } } */
+/* { dg-final { scan-tree-dump-times " \\\+ " 0 "fre1" } } */
index 21cc54e..7f44ec8 100644 (file)
@@ -3484,8 +3484,24 @@ visit_reference_op_call (tree lhs, gcall *stmt)
     {
       vn_reference_t vr2;
       vn_reference_s **slot;
+      tree vdef_val = vdef;
       if (vdef)
-       changed |= set_ssa_val_to (vdef, vdef);
+       {
+         /* If we value numbered an indirect functions function to
+            one not clobbering memory value number its VDEF to its
+            VUSE.  */
+         tree fn = gimple_call_fn (stmt);
+         if (fn && TREE_CODE (fn) == SSA_NAME)
+           {
+             fn = SSA_VAL (fn);
+             if (TREE_CODE (fn) == ADDR_EXPR
+                 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+                 && (flags_from_decl_or_type (TREE_OPERAND (fn, 0))
+                     & (ECF_CONST | ECF_PURE)))
+               vdef_val = vuse_ssa_val (gimple_vuse (stmt));
+           }
+         changed |= set_ssa_val_to (vdef, vdef_val);
+       }
       if (lhs)
        changed |= set_ssa_val_to (lhs, lhs);
       vr2 = current_info->references_pool->allocate ();
@@ -3498,7 +3514,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
       vr2->set = vr1.set;
       vr2->hashcode = vr1.hashcode;
       vr2->result = lhs;
-      vr2->result_vdef = vdef;
+      vr2->result_vdef = vdef_val;
       slot = current_info->references->find_slot_with_hash (vr2, vr2->hashcode,
                                                            INSERT);
       gcc_assert (!*slot);
@@ -3912,11 +3928,22 @@ visit_use (tree use)
            }
        }
 
+      /* Pick up flags from a devirtualization target.  */
+      tree fn = gimple_call_fn (stmt);
+      int extra_fnflags = 0;
+      if (fn && TREE_CODE (fn) == SSA_NAME)
+       {
+         fn = SSA_VAL (fn);
+         if (TREE_CODE (fn) == ADDR_EXPR
+             && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+           extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
+       }
       if (!gimple_call_internal_p (call_stmt)
          && (/* Calls to the same function with the same vuse
                 and the same operands do not necessarily return the same
                 value, unless they're pure or const.  */
-             gimple_call_flags (call_stmt) & (ECF_PURE | ECF_CONST)
+             ((gimple_call_flags (call_stmt) | extra_fnflags)
+              & (ECF_PURE | ECF_CONST))
              /* If calls have a vdef, subsequent calls won't have
                 the same incoming vuse.  So, if 2 calls with vdef have the
                 same vuse, we know they're not subsequent.