re PR tree-optimization/81365 (GCC miscompiles swap)
authorJakub Jelinek <jakub@redhat.com>
Mon, 17 Jul 2017 09:10:23 +0000 (11:10 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 17 Jul 2017 09:10:23 +0000 (11:10 +0200)
PR tree-optimization/81365
* tree-ssa-phiprop.c (propagate_with_phi): When considering hoisting
aggregate moves onto bb predecessor edges, make sure there are no
loads that could alias the lhs in between the start of bb and the
loads from *phi.

* g++.dg/torture/pr81365.C: New test.

From-SVN: r250261

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr81365.C [new file with mode: 0644]
gcc/tree-ssa-phiprop.c

index 92f7c7f2e9b0db4974dfd64bc4210a71d901181e..2f29824f91577e2d415ea2fdef34ccc8c344d8ee 100644 (file)
@@ -1,3 +1,11 @@
+2017-07-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/81365
+       * tree-ssa-phiprop.c (propagate_with_phi): When considering hoisting
+       aggregate moves onto bb predecessor edges, make sure there are no
+       loads that could alias the lhs in between the start of bb and the
+       loads from *phi.
+
 2017-07-17  Georg-Johann Lay  <avr@gjlay.de>
 
        PR 80929
index 67ffc3ef50221d09461041bb6801b6309c09b028..141d035cf6dbcc30ab12b732f66106cf64fa8917 100644 (file)
@@ -1,5 +1,8 @@
 2017-07-17  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/81365
+       * g++.dg/torture/pr81365.C: New test.
+
        PR tree-optimization/81396
        * gcc.dg/tree-ssa/pr81396.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/torture/pr81365.C b/gcc/testsuite/g++.dg/torture/pr81365.C
new file mode 100644 (file)
index 0000000..fde5e50
--- /dev/null
@@ -0,0 +1,39 @@
+// PR tree-optimization/81365
+// { dg-do run }
+
+struct A { unsigned a; };
+
+struct B {
+  B (const A *x)
+  {
+    __builtin_memcpy (b, x, 3 * sizeof (A));
+    __builtin_memcpy (c, x + 3, sizeof (A));
+    __builtin_memset (c + 1, 0, sizeof (A));
+  }
+  bool
+  foo (unsigned x)
+  {
+    A *it = c;
+    if (it->a == x || (++it)->a == x)
+      {
+       A t(b[0]);
+       b[0] = *it;
+       *it = t;
+       return true;
+      }
+    return false;
+  }
+  A b[3];
+  A c[2];
+};
+
+int
+main ()
+{
+  A x[] = { 4, 8, 12, 18 };
+  B y(x);
+  if (!y.foo (18))
+    __builtin_abort ();
+  if (!y.foo (4))
+    __builtin_abort ();
+}
index 8f8c1336c02ed302a367953a324f4d5c77c138a1..7dcb9ee49a43716eb3eaa354ec20b8e8f0e719c5 100644 (file)
@@ -327,7 +327,7 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
       if (!dominated_by_p (CDI_POST_DOMINATORS,
                           bb, gimple_bb (use_stmt)))
        continue;
-         
+
       /* Check whether this is a load of *ptr.  */
       if (!(is_gimple_assign (use_stmt)
            && gimple_assign_rhs_code (use_stmt) == MEM_REF
@@ -356,6 +356,9 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
          insert aggregate copies on the edges instead.  */
       if (!is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
        {
+         if (!gimple_vdef (use_stmt))
+           goto next;
+
          /* As we replicate the lhs on each incoming edge all
             used SSA names have to be available there.  */
          if (! for_each_index (gimple_assign_lhs_ptr (use_stmt),
@@ -363,6 +366,28 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
                                get_immediate_dominator (CDI_DOMINATORS,
                                                         gimple_bb (phi))))
            goto next;
+
+         gimple *vuse_stmt;
+         imm_use_iterator vui;
+         use_operand_p vuse_p;
+         /* In order to move the aggregate copies earlier, make sure
+            there are no statements that could read from memory
+            aliasing the lhs in between the start of bb and use_stmt.
+            As we require use_stmt to have a VDEF above, loads after
+            use_stmt will use a different virtual SSA_NAME.  */
+         FOR_EACH_IMM_USE_FAST (vuse_p, vui, vuse)
+           {
+             vuse_stmt = USE_STMT (vuse_p);
+             if (vuse_stmt == use_stmt)
+               continue;
+             if (!dominated_by_p (CDI_DOMINATORS,
+                                  gimple_bb (vuse_stmt), bb))
+               continue;
+             if (ref_maybe_used_by_stmt_p (vuse_stmt,
+                                           gimple_assign_lhs (use_stmt)))
+               goto next;
+           }
+
          phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
 
          /* Remove old stmt.  The phi is taken care of by DCE.  */