This patch from Zdenek removes special code handling the forced
rewrite of the original BIV definition.  The code was broken,
so simply fallback to the general rewriting code which works fine.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
(the issue is latent on the branches).

Thanks Zdenek for the fix,
Richard.

2012-12-12  Zdenek Dvorak  <o...@ucw.cz>

        PR tree-optimization/55481
        * tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Fall
        back to general rewriting if we cannot leave an original biv
        definition alone.

        * gcc.dg/torture/pr55481.c: New testcase.

Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
*** gcc/tree-ssa-loop-ivopts.c  (revision 194438)
--- gcc/tree-ssa-loop-ivopts.c  (working copy)
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 6088,6122 ****
    if (cand->pos == IP_ORIGINAL
        && cand->incremented_at == use->stmt)
      {
!       tree step, ctype, utype;
!       enum tree_code incr_code = PLUS_EXPR, old_code;
  
        gcc_assert (is_gimple_assign (use->stmt));
        gcc_assert (gimple_assign_lhs (use->stmt) == 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.  */
!       old_code = gimple_assign_rhs_code (use->stmt);
!       if (old_code == PLUS_EXPR
!         || old_code == MINUS_EXPR
!         || old_code == POINTER_PLUS_EXPR)
        {
          if (gimple_assign_rhs1 (use->stmt) == cand->var_before)
            op = gimple_assign_rhs2 (use->stmt);
!         else if (old_code != MINUS_EXPR
!                  && gimple_assign_rhs2 (use->stmt) == cand->var_before)
            op = gimple_assign_rhs1 (use->stmt);
          else
            op = NULL_TREE;
--- 6088,6111 ----
    if (cand->pos == IP_ORIGINAL
        && cand->incremented_at == use->stmt)
      {
!       enum tree_code stmt_code;
  
        gcc_assert (is_gimple_assign (use->stmt));
        gcc_assert (gimple_assign_lhs (use->stmt) == cand->var_after);
  
        /* 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.  */
!       stmt_code = gimple_assign_rhs_code (use->stmt);
!       if (stmt_code == PLUS_EXPR
!         || stmt_code == MINUS_EXPR
!         || stmt_code == POINTER_PLUS_EXPR)
        {
          if (gimple_assign_rhs1 (use->stmt) == cand->var_before)
            op = gimple_assign_rhs2 (use->stmt);
!         else if (gimple_assign_rhs2 (use->stmt) == cand->var_before)
            op = gimple_assign_rhs1 (use->stmt);
          else
            op = NULL_TREE;
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 6124,6147 ****
        else
        op = NULL_TREE;
  
!       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);
-       gcc_assert (comp != NULL_TREE);
      }
  
    switch (gimple_code (use->stmt))
      {
      case GIMPLE_PHI:
--- 6113,6125 ----
        else
        op = NULL_TREE;
  
!       if (op && expr_invariant_in_loop_p (data->current_loop, op))
        return;
      }
  
+   comp = get_computation (data->current_loop, use, cand);
+   gcc_assert (comp != NULL_TREE);
+ 
    switch (gimple_code (use->stmt))
      {
      case GIMPLE_PHI:
Index: gcc/testsuite/gcc.dg/torture/pr55481.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55481.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55481.c      (revision 0)
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do run } */
+ 
+ int main()
+ {
+   signed char result = 0;
+   int n;
+   for (n = 0; n < 13; ++n)
+     {
+       int tem = result;
+       tem = tem + 31;
+       result = tem;
+     }
+   if (result != -109)
+     __builtin_abort ();
+   return 0;
+ }

Reply via email to