OSDN Git Service

PR middle-end/44592
authormatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 28 Jun 2010 15:14:31 +0000 (15:14 +0000)
committermatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 28 Jun 2010 15:14:31 +0000 (15:14 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161496 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/pr44592.f90 [new file with mode: 0644]

index aa93333..fd8b6d9 100644 (file)
@@ -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
index a37b4a3..8fb604d 100644 (file)
@@ -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);
     }
index 59b0bf9..7bdfc34 100644 (file)
@@ -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 (file)
index 0000000..8b043ba
--- /dev/null
@@ -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