OSDN Git Service

PR middle-end/20256
authorspop <spop@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 May 2006 14:25:59 +0000 (14:25 +0000)
committerspop <spop@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 May 2006 14:25:59 +0000 (14:25 +0000)
PR middle-end/26435
* tree-loop-linear.c (linear_transform_loops): Don't test perfect_nest_p.
Call rewrite_into_loop_closed_ssa only when something changed.
* lambda.h (gcc_loopnest_to_lambda_loopnest): Update declaration.
* lambda-code.c (can_convert_to_perfect_nest): Declared.
(gcc_loopnest_to_lambda_loopnest): Removed need_perfect_nest parameter.
Test for perfect_nest_p here.  Fix formating.
(replace_uses_equiv_to_x_with_y): Fix formating.
(stmt_uses_op): Removed.
(can_convert_to_perfect_nest): Removed loopivs parameter.
Complete the test by checking the scalar dependences.
(perfect_nestify): Remove the test for can_convert_to_perfect_nest.
Fix formating.

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

gcc/ChangeLog
gcc/lambda-code.c
gcc/lambda.h
gcc/testsuite/gcc.dg/tree-ssa/ltrans-1.c
gcc/testsuite/gcc.dg/tree-ssa/pr20256.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr26435.c [new file with mode: 0644]
gcc/tree-loop-linear.c

index eefaa9a..9baecb1 100644 (file)
@@ -1,3 +1,20 @@
+2006-05-17  Sebastian Pop  <pop@cri.ensmp.fr>
+
+       PR middle-end/20256
+       PR middle-end/26435
+       * tree-loop-linear.c (linear_transform_loops): Don't test perfect_nest_p.
+       Call rewrite_into_loop_closed_ssa only when something changed.
+       * lambda.h (gcc_loopnest_to_lambda_loopnest): Update declaration.
+       * lambda-code.c (can_convert_to_perfect_nest): Declared.
+       (gcc_loopnest_to_lambda_loopnest): Removed need_perfect_nest parameter.
+       Test for perfect_nest_p here.  Fix formating.
+       (replace_uses_equiv_to_x_with_y): Fix formating.
+       (stmt_uses_op): Removed.
+       (can_convert_to_perfect_nest): Removed loopivs parameter.
+       Complete the test by checking the scalar dependences.
+       (perfect_nestify): Remove the test for can_convert_to_perfect_nest.
+       Fix formating.
+
 2005-05-17  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        PR bootstrap/22541
index 3a28ee3..60f1be2 100644 (file)
@@ -147,6 +147,7 @@ static lambda_lattice lambda_lattice_new (int, int);
 static lambda_lattice lambda_lattice_compute_base (lambda_loopnest);
 
 static tree find_induction_var_from_exit_cond (struct loop *);
+static bool can_convert_to_perfect_nest (struct loop *);
 
 /* Create a new lambda body vector.  */
 
@@ -1457,14 +1458,13 @@ DEF_VEC_ALLOC_P(lambda_loop,heap);
 
 lambda_loopnest
 gcc_loopnest_to_lambda_loopnest (struct loops *currloops,
-                                struct loop * loop_nest,
+                                struct loop *loop_nest,
                                 VEC(tree,heap) **inductionvars,
-                                VEC(tree,heap) **invariants,
-                                bool need_perfect_nest)
+                                VEC(tree,heap) **invariants)
 {
   lambda_loopnest ret = NULL;
-  struct loop *temp;
-  int depth = 0;
+  struct loop *temp = loop_nest;
+  int depth = depth_of_nest (loop_nest);
   size_t i;
   VEC(lambda_loop,heap) *loops = NULL;
   VEC(tree,heap) *uboundvars = NULL;
@@ -1472,9 +1472,11 @@ gcc_loopnest_to_lambda_loopnest (struct loops *currloops,
   VEC(int,heap) *steps = NULL;
   lambda_loop newloop;
   tree inductionvar = NULL;
-  
-  depth = depth_of_nest (loop_nest);
-  temp = loop_nest;
+  bool perfect_nest = perfect_nest_p (loop_nest);
+
+  if (!perfect_nest && !can_convert_to_perfect_nest (loop_nest))
+    goto fail;
+
   while (temp)
     {
       newloop = gcc_loop_to_lambda_loop (temp, depth, invariants,
@@ -1482,12 +1484,14 @@ gcc_loopnest_to_lambda_loopnest (struct loops *currloops,
                                         &lboundvars, &uboundvars,
                                         &steps);
       if (!newloop)
-       return NULL;
+       goto fail;
+
       VEC_safe_push (tree, heap, *inductionvars, inductionvar);
       VEC_safe_push (lambda_loop, heap, loops, newloop);
       temp = temp->inner;
     }
-  if (need_perfect_nest)
+
+  if (!perfect_nest)
     {
       if (!perfect_nestify (currloops, loop_nest, 
                            lboundvars, uboundvars, steps, *inductionvars))
@@ -1501,9 +1505,12 @@ gcc_loopnest_to_lambda_loopnest (struct loops *currloops,
        fprintf (dump_file,
                 "Successfully converted loop nest to perfect loop nest.\n");
     }
+
   ret = lambda_loopnest_new (depth, 2 * depth);
+
   for (i = 0; VEC_iterate (lambda_loop, loops, i, newloop); i++)
     LN_LOOPS (ret)[i] = newloop;
+
  fail:
   VEC_free (lambda_loop, heap, loops);
   VEC_free (tree, heap, uboundvars);
@@ -2110,13 +2117,12 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
     {
       tree use = USE_FROM_PTR (use_p);
       tree step = NULL_TREE;
-      tree access_fn = NULL_TREE;
-      
-      
-      access_fn = instantiate_parameters
-       (loop, analyze_scalar_evolution (loop, use));
-      if (access_fn != NULL_TREE && access_fn != chrec_dont_know)
-       step = evolution_part_in_loop_num (access_fn, loop->num);
+      tree scev = instantiate_parameters (loop,
+                                         analyze_scalar_evolution (loop, use));
+
+      if (scev != NULL_TREE && scev != chrec_dont_know)
+       step = evolution_part_in_loop_num (scev, loop->num);
+
       if ((step && step != chrec_dont_know 
           && TREE_CODE (step) == INTEGER_CST
           && int_cst_value (step) == xstep)
@@ -2125,22 +2131,6 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
     }
 }
 
-/* Return TRUE if STMT uses tree OP in it's uses.  */
-
-static bool
-stmt_uses_op (tree stmt, tree op)
-{
-  ssa_op_iter iter;
-  tree use;
-
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
-    {
-      if (use == op)
-       return true;
-    }
-  return false;
-}
-
 /* Return true if STMT is an exit PHI for LOOP */
 
 static bool
@@ -2210,14 +2200,12 @@ can_put_after_inner_loop (struct loop *loop, tree stmt)
 
 
 
-/* Return TRUE if LOOP is an imperfect nest that we can convert to a perfect
-   one.  LOOPIVS is a vector of induction variables, one per loop.  
-   ATM, we only handle imperfect nests of depth 2, where all of the statements
-   occur after the inner loop.  */
+/* Return TRUE if LOOP is an imperfect nest that we can convert to a
+   perfect one.  At the moment, we only handle imperfect nests of
+   depth 2, where all of the statements occur after the inner loop.  */
 
 static bool
-can_convert_to_perfect_nest (struct loop *loop,
-                            VEC(tree,heap) *loopivs)
+can_convert_to_perfect_nest (struct loop *loop)
 {
   basic_block *bbs;
   tree exit_condition, phi;
@@ -2237,19 +2225,13 @@ can_convert_to_perfect_nest (struct loop *loop,
        {
          for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi); bsi_next (&bsi))
            { 
-             size_t j;
              tree stmt = bsi_stmt (bsi);
-             tree iv;
-             
+
              if (stmt == exit_condition
                  || not_interesting_stmt (stmt)
                  || stmt_is_bumper_for_loop (loop, stmt))
                continue;
-             /* If the statement uses inner loop ivs, we == screwed.  */
-             for (j = 1; VEC_iterate (tree, loopivs, j, iv); j++)
-               if (stmt_uses_op (stmt, iv))
-                 goto fail;
-             
+
              /* If this is a scalar operation that can be put back
                 into the inner loop, or after the inner loop, through
                 copying, then do so. This works on the theory that
@@ -2258,10 +2240,65 @@ can_convert_to_perfect_nest (struct loop *loop,
                 win we get from rearranging the memory walk
                 the loop is doing so that it has better
                 cache behavior.  */
-             if (TREE_CODE (stmt) == MODIFY_EXPR
-                 && (can_put_in_inner_loop (loop->inner, stmt)
-                     || can_put_after_inner_loop (loop, stmt)))
-               continue;
+             if (TREE_CODE (stmt) == MODIFY_EXPR)
+               {
+                 use_operand_p use_a, use_b;
+                 imm_use_iterator imm_iter;
+                 ssa_op_iter op_iter, op_iter1;
+                 tree op0 = TREE_OPERAND (stmt, 0);
+                 tree scev = instantiate_parameters
+                   (loop, analyze_scalar_evolution (loop, op0));
+
+                 /* If the IV is simple, it can be duplicated.  */
+                 if (!automatically_generated_chrec_p (scev))
+                   {
+                     tree step = evolution_part_in_loop_num (scev, loop->num);
+                     if (step && step != chrec_dont_know 
+                         && TREE_CODE (step) == INTEGER_CST)
+                       continue;
+                   }
+
+                 /* The statement should not define a variable used
+                    in the inner loop.  */
+                 if (TREE_CODE (op0) == SSA_NAME)
+                   FOR_EACH_IMM_USE_FAST (use_a, imm_iter, op0)
+                     if (bb_for_stmt (USE_STMT (use_a))->loop_father
+                         == loop->inner)
+                       goto fail;
+
+                 FOR_EACH_SSA_USE_OPERAND (use_a, stmt, op_iter, SSA_OP_USE)
+                   {
+                     tree node, op = USE_FROM_PTR (use_a);
+
+                     /* The variables should not be used in both loops.  */
+                     FOR_EACH_IMM_USE_FAST (use_b, imm_iter, op)
+                     if (bb_for_stmt (USE_STMT (use_b))->loop_father
+                         == loop->inner)
+                       goto fail;
+
+                     /* The statement should not use the value of a
+                        scalar that was modified in the loop.  */
+                     node = SSA_NAME_DEF_STMT (op);
+                     if (TREE_CODE (node) == PHI_NODE)
+                       FOR_EACH_PHI_ARG (use_b, node, op_iter1, SSA_OP_USE)
+                         {
+                           tree arg = USE_FROM_PTR (use_b);
+
+                           if (TREE_CODE (arg) == SSA_NAME)
+                             {
+                               tree arg_stmt = SSA_NAME_DEF_STMT (arg);
+
+                               if (bb_for_stmt (arg_stmt)->loop_father
+                                   == loop->inner)
+                                 goto fail;
+                             }
+                         }
+                   }
+
+                 if (can_put_in_inner_loop (loop->inner, stmt)
+                     || can_put_after_inner_loop (loop, stmt))
+                   continue;
+               }
 
              /* Otherwise, if the bb of a statement we care about isn't
                 dominated by the header of the inner loop, then we can't
@@ -2351,14 +2388,10 @@ perfect_nestify (struct loops *loops,
   tree stmt;
   tree oldivvar, ivvar, ivvarinced;
   VEC(tree,heap) *phis = NULL;
-
-  if (!can_convert_to_perfect_nest (loop, loopivs))
-    return false;
-
-  /* Create the new loop */
-
+  
+  /* Create the new loop.  */
   olddest = loop->single_exit->dest;
-  preheaderbb =  loop_split_edge_with (loop->single_exit, NULL);
+  preheaderbb = loop_split_edge_with (loop->single_exit, NULL);
   headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
   
   /* Push the exit phi nodes that we are moving.  */
@@ -2490,7 +2523,7 @@ perfect_nestify (struct loops *loops,
                    }
                  
                  /* Make copies of this statement to put it back next
-                    to its uses. */
+                    to its uses.  */
                  FOR_EACH_IMM_USE_STMT (imm_stmt, imm_iter, 
                                         TREE_OPERAND (stmt, 0))
                    {
@@ -2506,8 +2539,10 @@ perfect_nestify (struct loops *loops,
                          newname = SSA_NAME_VAR (newname);
                          newname = make_ssa_name (newname, newstmt);
                          TREE_OPERAND (newstmt, 0) = newname;
+
                          FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
                            SET_USE (use_p, newname);
+
                          bsi_insert_before (&tobsi, newstmt, BSI_SAME_STMT);
                          update_stmt (newstmt);
                          update_stmt (imm_stmt);
@@ -2535,10 +2570,9 @@ perfect_nestify (struct loops *loops,
                      continue;
                    }
                  
-                 replace_uses_equiv_to_x_with_y (loop, stmt, 
-                                                 oldivvar,  
-                                                 VEC_index (int, steps, 0),
-                                                 ivvar);
+                 replace_uses_equiv_to_x_with_y 
+                   (loop, stmt, oldivvar, VEC_index (int, steps, 0), ivvar);
+
                  bsi_move_before (&bsi, &tobsi);
                  
                  /* If the statement has any virtual operands, they may
index fc5679a..5eb6399 100644 (file)
@@ -199,8 +199,7 @@ void print_lambda_body_vector (FILE *, lambda_body_vector);
 lambda_loopnest gcc_loopnest_to_lambda_loopnest (struct loops *,
                                                 struct loop *,
                                                 VEC(tree,heap) **,
-                                                VEC(tree,heap) **,
-                                                bool);
+                                                VEC(tree,heap) **);
 void lambda_loopnest_to_gcc_loopnest (struct loop *,
                                      VEC(tree,heap) *, VEC(tree,heap) *,
                                      lambda_loopnest, lambda_trans_matrix);
index a3a9975..736a4d9 100644 (file)
@@ -18,7 +18,6 @@ int foo(int N, int *res)
     }
   *res = sum + N;
 }
-/* { dg-final { scan-tree-dump-times "converted loop nest to perfect
-   loop nest" 1 "ltrans"} } */ 
+/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 1 "ltrans"} } */ 
 /* { dg-final { scan-tree-dump-times "transformed loop" 1 "ltrans"} } */ 
 /* { dg-final { cleanup-tree-dump "ltrans" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20256.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20256.c
new file mode 100644 (file)
index 0000000..aa482ed
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
+/* { dg-require-effective-target size32plus } */
+
+int foo()
+{
+  int x[2][2], y[2];
+  int i, n, s;
+
+  /* This is a reduction: there is a scalar dependence that cannot be
+     removed by rewriting IVs.  This code cannot and should not be
+     transformed into a perfect loop.  */
+  for (n = 0; n < 2; n++)
+    {
+      s = 0;
+      for (i = 0; i < 2; i++)
+        s += x[n][i]*y[i];
+      s += 1;
+    }
+
+  return s;
+}
+
+/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 0 "ltrans"} } */ 
+/* { dg-final { cleanup-tree-dump "ltrans" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr26435.c b/gcc/testsuite/gcc.dg/tree-ssa/pr26435.c
new file mode 100644 (file)
index 0000000..907c5d2
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -ftree-loop-linear -fdump-tree-ltrans-all" } */
+/* { dg-require-effective-target size32plus } */
+
+int foo(int *p, int n)
+{
+  int i, j, k = 0;
+
+  /* This is a reduction: there is a scalar dependence that cannot be
+     removed by rewriting IVs.  This code cannot and should not be
+     transformed into a perfect loop.  */
+  for (i = 0; i < 2; ++i, p += n)
+    for (j = 0; j < 2; ++j)
+      k += p[j];
+
+  return k;
+}
+
+/* { dg-final { scan-tree-dump-times "converted loop nest to perfect loop nest" 0 "ltrans"} } */ 
+/* { dg-final { cleanup-tree-dump "ltrans" } } */
index c648ef7..e0f5bd2 100644 (file)
@@ -241,6 +241,7 @@ try_interchange_loops (lambda_trans_matrix trans,
 void
 linear_transform_loops (struct loops *loops)
 {
+  bool modified = false;
   unsigned int i;
   VEC(tree,heap) *oldivs = NULL;
   VEC(tree,heap) *invariants = NULL;
@@ -255,7 +256,6 @@ linear_transform_loops (struct loops *loops)
       lambda_loopnest before, after;
       lambda_trans_matrix trans;
       bool problem = false;
-      bool need_perfect_nest = false;
       /* If it's not a loop nest, we don't want it.
          We also don't handle sibling loops properly, 
          which are loops of the following form:
@@ -319,13 +319,9 @@ linear_transform_loops (struct loops *loops)
          continue;
        }
 
-      if (!perfect_nest_p (loop_nest))
-       need_perfect_nest = true;
+      before = gcc_loopnest_to_lambda_loopnest (loops, loop_nest, &oldivs,
+                                               &invariants);
 
-      before = gcc_loopnest_to_lambda_loopnest (loops,
-                                               loop_nest, &oldivs, 
-                                               &invariants,
-                                               need_perfect_nest);
       if (!before)
        continue;
             
@@ -345,6 +341,7 @@ linear_transform_loops (struct loops *loops)
 
       lambda_loopnest_to_gcc_loopnest (loop_nest, oldivs, invariants,
                                       after, trans);
+      modified = true;
 
       if (dump_file)
        fprintf (dump_file, "Successfully transformed loop.\n");
@@ -356,5 +353,7 @@ linear_transform_loops (struct loops *loops)
   VEC_free (tree, heap, oldivs);
   VEC_free (tree, heap, invariants);
   scev_reset ();
-  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_full_phi);
+
+  if (modified)
+    rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_full_phi);
 }