PR tree-optimization/22438
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 22 Sep 2005 11:24:00 +0000 (11:24 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 22 Sep 2005 11:24:00 +0000 (11:24 +0000)
* tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Handle all
preserved iv rhs rewriting specially.

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

gcc/ChangeLog
gcc/tree-ssa-loop-ivopts.c

index 471414d..5ba52fe 100644 (file)
@@ -1,3 +1,9 @@
+2005-09-21  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       PR tree-optimization/22438
+       * tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Handle all
+       preserved iv rhs rewriting specially.
+
 2005-09-21  Daniel Berlin  <dberlin@dberlin.org>
 
        * tree-data-ref.c (analyze_array_indexes): Only estimate when
index 44ebc5c..8bfbf7f 100644 (file)
@@ -5331,22 +5331,58 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
      introduce a new computation (that might also need casting the
      variable to unsigned and back).  */
   if (cand->pos == IP_ORIGINAL
-      && TREE_CODE (use->stmt) == MODIFY_EXPR
-      && TREE_OPERAND (use->stmt, 0) == cand->var_after)
+      && cand->incremented_at == use->stmt)
     {
+      tree step, ctype, utype;
+      enum tree_code incr_code = PLUS_EXPR;
+
+      gcc_assert (TREE_CODE (use->stmt) == MODIFY_EXPR);
+      gcc_assert (TREE_OPERAND (use->stmt, 0) == cand->var_after);
+
+      step = cand->iv->step;
+      ctype = TREE_TYPE (step);
+      utype = TREE_TYPE (cand->var_after);
+      if (TREE_CODE (step) == NEGATE_EXPR)
+       {
+         incr_code = MINUS_EXPR;
+         step = TREE_OPERAND (step, 0);
+       }
+
+      /* Check whether we may leave the computation unchanged.
+        This is the case only if it does not rely on other
+        computations in the loop -- otherwise, the computation
+        we rely upon may be removed in remove_unused_ivs,
+        thus leading to ICE.  */
       op = TREE_OPERAND (use->stmt, 1);
+      if (TREE_CODE (op) == PLUS_EXPR
+         || TREE_CODE (op) == MINUS_EXPR)
+       {
+         if (TREE_OPERAND (op, 0) == cand->var_before)
+           op = TREE_OPERAND (op, 1);
+         else if (TREE_CODE (op) == PLUS_EXPR
+                  && TREE_OPERAND (op, 1) == cand->var_before)
+           op = TREE_OPERAND (op, 0);
+         else
+           op = NULL_TREE;
+       }
+      else
+       op = NULL_TREE;
 
-      /* Be a bit careful.  In case variable is expressed in some
-        complicated way, rewrite it so that we may get rid of this
-        complicated expression.  */
-      if ((TREE_CODE (op) == PLUS_EXPR
-          || TREE_CODE (op) == MINUS_EXPR)
-         && TREE_OPERAND (op, 0) == cand->var_before
-         && TREE_CODE (TREE_OPERAND (op, 1)) == INTEGER_CST)
+      if (op
+         && (TREE_CODE (op) == INTEGER_CST
+             || operand_equal_p (op, step, 0)))
        return;
+
+      /* Otherwise, add the necessary computations to express
+        the iv.  */
+      op = fold_convert (ctype, cand->var_before);
+      comp = fold_convert (utype,
+                          build2 (incr_code, ctype, op,
+                                  unshare_expr (step)));
     }
+  else
+    comp = get_computation (data->current_loop, use, cand);
 
-  comp = get_computation (data->current_loop, use, cand);
   switch (TREE_CODE (use->stmt))
     {
     case PHI_NODE: