This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[rfa] Fix PR44592: wrong code
- From: Michael Matz <matz at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 25 Jun 2010 18:03:08 +0200 (CEST)
- Subject: [rfa] Fix PR44592: wrong code
Hello,
For callers of gimplify_and_update_call_from_tree() that possibly traverse
the VOP chains we have to make the new sequence as a whole have the same
effects as the original statements (from a VOP perspective), i.e.
attaching the old VOPs to the new sequence. There was a latent ommission
uncovered by my more general use of the above function. It involved
transforming a call without LHS but VOPs (e.g. memcpy) into stores.
Hence, we track the last store of the new sequence, and possibly attach
the VOPs of the original statement to that one.
Fixed the testcase, regstrapping on x86_64-linux in progress. Okay for
trunk and 4.5 after some time?
Ciao,
Michael.
--
PR middle-end/44592
* gimple-fold.c (gimplify_and_update_call_from_tree): Track last
store in sequence, attach original VOPs to it.
testsuite/
PR middle-end/44592
* gfortran.dg/pr44592.f90: New test.
Index: gimple-fold.c
===================================================================
--- gimple-fold.c (revision 161389)
+++ gimple-fold.c (working copy)
@@ -1065,6 +1065,7 @@ gimplify_and_update_call_from_tree (gimp
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
gimple last = NULL;
+ gimple laststore = NULL;
stmt = gsi_stmt (*si_p);
@@ -1096,12 +1097,28 @@ gimplify_and_update_call_from_tree (gimp
find_new_referenced_vars (new_stmt);
mark_symbols_for_renaming (new_stmt);
last = new_stmt;
+ if (gimple_assign_single_p (last)
+ && !is_gimple_reg (gimple_assign_lhs (last)))
+ laststore = last;
}
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_vuse (laststore, gimple_vuse (stmt));
+ gimple_set_vdef (laststore, gimple_vdef (stmt));
+ move_ssa_defining_stmt_for_defs (laststore, stmt);
+ }
+ else
+ {
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
+ }
new_stmt = last;
}
else
Index: testsuite/gfortran.dg/pr44592.f90
===================================================================
--- testsuite/gfortran.dg/pr44592.f90 (revision 0)
+++ testsuite/gfortran.dg/pr44592.f90 (revision 0)
@@ -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