This fixes an old missed optimization in alias disambiguation during
SCCVN.  We can skip a clobbering stmt if that is a store with exactly
the same value as a preceeding redundancy.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2017-11-23  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/23094
        * tree-ssa-sccvn.c (vuse_ssa_val): Handle VN_TOP when we
        come here from walking over backedges in the first iteration.
        (vn_reference_lookup_3): Skip clobbers that store the same value.

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

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 255054)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -345,7 +345,12 @@ vuse_ssa_val (tree x)
 
   do
     {
-      x = SSA_VAL (x);
+      tree tem = SSA_VAL (x);
+      /* stmt walking can walk over a backedge and reach code we didn't
+        value-number yet.  */
+      if (tem == VN_TOP)
+       return x;
+      x = tem;
     }
   while (SSA_NAME_IN_FREE_LIST (x));
 
@@ -1868,6 +1873,39 @@ vn_reference_lookup_3 (ao_ref *ref, tree
          ao_ref_init (&lhs_ref, lhs);
          lhs_ref_ok = true;
        }
+
+      /* If we reach a clobbering statement try to skip it and see if
+         we find a VN result with exactly the same value as the
+        possible clobber.  In this case we can ignore the clobber
+        and return the found value.
+        Note that we don't need to worry about partial overlapping
+        accesses as we then can use TBAA to disambiguate against the
+        clobbering statement when looking up a load (thus the
+        VN_WALKREWRITE guard).  */
+      if (vn_walk_kind == VN_WALKREWRITE
+         && is_gimple_reg_type (TREE_TYPE (lhs))
+         && types_compatible_p (TREE_TYPE (lhs), vr->type))
+       {
+         tree *saved_last_vuse_ptr = last_vuse_ptr;
+         /* Do not update last_vuse_ptr in vn_reference_lookup_2.  */
+         last_vuse_ptr = NULL;
+         tree saved_vuse = vr->vuse;
+         hashval_t saved_hashcode = vr->hashcode;
+         void *res = vn_reference_lookup_2 (ref,
+                                            gimple_vuse (def_stmt), 0, vr);
+         /* Need to restore vr->vuse and vr->hashcode.  */
+         vr->vuse = saved_vuse;
+         vr->hashcode = saved_hashcode;
+         last_vuse_ptr = saved_last_vuse_ptr;
+         if (res && res != (void *)-1)
+           {
+             vn_reference_t vnresult = (vn_reference_t) res;
+             if (vnresult->result
+                 && operand_equal_p (vnresult->result,
+                                     gimple_assign_rhs1 (def_stmt), 0))
+               return res;
+           }
+       }
     }
   else if (gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL)
           && gimple_call_num_args (def_stmt) <= 4)
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c  (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c  (working copy)
@@ -0,0 +1,43 @@
+/* { dg-do link } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+void link_error (void);
+
+void test1 (int *p, int *q)
+{
+  *p = 1;
+  *q = 1;
+  if (*p != 1)
+    link_error ();
+}
+
+void test2 (int *p, int *q, int t)
+{
+  *p = t;
+  *q = t;
+  if (*p != t)
+    link_error ();
+}
+
+void test3 (int *q, int *p)
+{
+  int tem = *p;
+  *q = tem;
+  if (*p != tem)
+    link_error ();
+}
+
+char a[4];
+struct A { char a[4]; };
+void test4 (struct A *p)
+{
+  a[0] = p->a[0];
+  a[0] = p->a[0];
+  a[0] = p->a[0];
+}
+
+int main() { return 0; }
+
+/* { dg-final { scan-tree-dump-times "Replaced \\\*p" 3 "fre1" } } */
+/* { dg-final { scan-tree-dump-times "Replaced p_.\\(D\\)->" 2 "fre1" } } */
+/* { dg-final { scan-tree-dump-times "Deleted redundant store a\\\[0\\\]" 2 
"fre1" } } */

Reply via email to