aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2010-06-28 15:14:31 +0000
committerMichael Matz <matz@gcc.gnu.org>2010-06-28 15:14:31 +0000
commitfe2ef088e065f9e15311b221db3fcbf864dfb250 (patch)
tree9de962d5f754d58a1f456143f4c86710db0e4087
parentf0cc75e07893d05abcfe0287dc2c1071680e0c6f (diff)
downloadgcc-fe2ef088e065f9e15311b221db3fcbf864dfb250.zip
gcc-fe2ef088e065f9e15311b221db3fcbf864dfb250.tar.gz
gcc-fe2ef088e065f9e15311b221db3fcbf864dfb250.tar.bz2
re PR middle-end/44592 (wrong code at -O3)
PR middle-end/44592 * gimple-fold.c (gimplify_and_update_call_from_tree): Maintain proper VDEF chain for intermediate stores in the sequence. testsuite/ PR middle-end/44592 * gfortran.dg/pr44592.f90: New test. From-SVN: r161496
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/gimple-fold.c54
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/pr44592.f9020
4 files changed, 81 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aa93333..fd8b6d9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-06-28 Michael Matz <matz@suse.de>
+
+ PR middle-end/44592
+ * gimple-fold.c (gimplify_and_update_call_from_tree): Maintain
+ proper VDEF chain for intermediate stores in the sequence.
+
2010-06-28 Jan Hubicka <jh@suse.cz>
PR tree-optimization/44357
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index a37b4a3..8fb604d 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1053,7 +1053,9 @@ fold_gimple_cond (gimple stmt)
is replaced. If the call is expected to produces a result, then it
is replaced by an assignment of the new RHS to the result variable.
If the result is to be ignored, then the call is replaced by a
- GIMPLE_NOP. */
+ GIMPLE_NOP. A proper VDEF chain is retained by making the first
+ VUSE and the last VDEF of the whole sequence be the same as the replaced
+ statement and using new SSA names for stores in between. */
void
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
@@ -1065,12 +1067,15 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
gimple last = NULL;
+ gimple laststore = NULL;
+ tree reaching_vuse;
stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (stmt));
lhs = gimple_call_lhs (stmt);
+ reaching_vuse = gimple_vuse (stmt);
push_gimplify_context (&gctx);
@@ -1095,13 +1100,47 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
new_stmt = gsi_stmt (i);
find_new_referenced_vars (new_stmt);
mark_symbols_for_renaming (new_stmt);
+ /* If the new statement has a VUSE, update it with exact SSA name we
+ know will reach this one. */
+ if (gimple_vuse (new_stmt))
+ {
+ /* If we've also seen a previous store create a new VDEF for
+ the latter one, and make that the new reaching VUSE. */
+ if (laststore)
+ {
+ reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
+ gimple_set_vdef (laststore, reaching_vuse);
+ update_stmt (laststore);
+ laststore = NULL;
+ }
+ gimple_set_vuse (new_stmt, reaching_vuse);
+ gimple_set_modified (new_stmt, true);
+ }
+ if (gimple_assign_single_p (new_stmt)
+ && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
+ {
+ laststore = new_stmt;
+ }
last = new_stmt;
}
if (lhs == NULL_TREE)
{
- unlink_stmt_vdef (stmt);
- release_defs (stmt);
+ /* If we replace a call without LHS that has a VDEF and our new
+ sequence ends with a store we must make that store have the same
+ vdef in order not to break the sequencing. This can happen
+ for instance when folding memcpy calls into assignments. */
+ if (gimple_vdef (stmt) && laststore)
+ {
+ gimple_set_vdef (laststore, gimple_vdef (stmt));
+ move_ssa_defining_stmt_for_defs (laststore, stmt);
+ update_stmt (laststore);
+ }
+ else
+ {
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
+ }
new_stmt = last;
}
else
@@ -1111,8 +1150,15 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
+ if (laststore)
+ {
+ reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
+ gimple_set_vdef (laststore, reaching_vuse);
+ update_stmt (laststore);
+ laststore = NULL;
+ }
new_stmt = gimple_build_assign (lhs, tmp);
- gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+ gimple_set_vuse (new_stmt, reaching_vuse);
gimple_set_vdef (new_stmt, gimple_vdef (stmt));
move_ssa_defining_stmt_for_defs (new_stmt, stmt);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59b0bf9..7bdfc348 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-06-28 Michael Matz <matz@suse.de>
+
+ PR middle-end/44592
+ * gfortran.dg/pr44592.f90: New test.
+
2010-06-28 Jan Hubicka <jh@suse.cz>
PR tree-optimization/44357
diff --git a/gcc/testsuite/gfortran.dg/pr44592.f90 b/gcc/testsuite/gfortran.dg/pr44592.f90
new file mode 100644
index 0000000..8b043ba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr44592.f90
@@ -0,0 +1,20 @@
+! { dg-do run }
+! { dg-options "-O3" }
+! From forall_12.f90
+! Fails with loop reversal at -O3
+!
+ character(len=1) :: b(4) = (/"1","2","3","4"/), c(4)
+ c = b
+ i = 1
+ ! This statement must be here for the abort below
+ b(1:3)(i:i) = b(2:4)(i:i)
+
+ b = c
+ b(4:2:-1)(i:i) = b(3:1:-1)(i:i)
+
+ ! This fails. If the condition is printed, the result is F F F F
+ if (any (b .ne. (/"1","1","2","3"/))) i = 2
+ print *, b
+ print *, b .ne. (/"1","1","2","3"/)
+ if (i == 2) call abort
+end