summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-07-17 11:10:23 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2017-07-17 11:10:23 +0200
commite8dd1313132e5aaa4c66b0bd2135919707dc45b6 (patch)
treeab28fd58473d7498affb0856f0fba16c2c508561
parent764eec6cf591fcfe9bd0fe7760ecb657cfa6abc0 (diff)
re PR tree-optimization/81365 (GCC miscompiles swap)
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81365.C39
-rw-r--r--gcc/tree-ssa-phiprop.c27
4 files changed, 76 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 92f7c7f2e9b..2f29824f915 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 67ffc3ef502..141d035cf6d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..fde5e503df9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr81365.C
@@ -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 ();
+}
diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c
index 8f8c1336c02..7dcb9ee49a4 100644
--- a/gcc/tree-ssa-phiprop.c
+++ b/gcc/tree-ssa-phiprop.c
@@ -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. */