On Mon, 17 Dec 2012, Richard Biener wrote:

> 
> The following patch fixes a miscompilation due to bogus loop iteration
> bound derived from array accesses in an inner loop.  idx_infer_loop_bounds
> analyzes the evoultion of an SSA name with respect to a loop it is not
> defined in - which seems to lead to random weird behavior.  The correct
> thing to do (as documented) is to analyze the evolution with respect
> to the loop the stmt we are interested in is in.
> 
> Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu.

Which shows that the very old fix for PR40281 isn't complete
(the patch regresses PR55687 again).  So the following extends
that fix.  I wonder whether we instead want to pass down
CHREC_VARIABLE and avoid doing the instantiation in the first
place ...

Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu.

Comments welcome.

Thanks,
Richard.

2012-12-17  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/55555
        * tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
        analyze evolution of the index for the loop it is used in.
        * tree-scalar-evolution.c (instantiate_scev_poly): Generalize
        fix for PR40281 and prune invalid SCEVs.

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

Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c   (revision 194552)
--- gcc/tree-ssa-loop-niter.c   (working copy)
*************** idx_infer_loop_bounds (tree base, tree *
*** 2671,2677 ****
        upper = false;
      }
  
!   ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx));
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
--- 2671,2682 ----
        upper = false;
      }
  
!   struct loop *dloop = loop_containing_stmt (data->stmt);
!   if (!dloop)
!     return true;
! 
!   ev = analyze_scalar_evolution (dloop, *idx);
!   ev = instantiate_parameters (loop, ev);
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
Index: gcc/tree-scalar-evolution.c
===================================================================
*** gcc/tree-scalar-evolution.c (revision 194552)
--- gcc/tree-scalar-evolution.c (working copy)
*************** instantiate_scev_poly (basic_block insta
*** 2268,2295 ****
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
                            CHREC_RIGHT (chrec), fold_conversions, cache,
                            size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
!   if (CHREC_LEFT (chrec) != op0
!       || CHREC_RIGHT (chrec) != op1)
      {
!       unsigned var = CHREC_VARIABLE (chrec);
! 
!       /* When the instantiated stride or base has an evolution in an
!        innermost loop, return chrec_dont_know, as this is not a
!        valid SCEV representation.  In the reduced testcase for
!        PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no
!        meaning.  */
!       if ((tree_is_chrec (op0) && CHREC_VARIABLE (op0) > var)
!         || (tree_is_chrec (op1) && CHREC_VARIABLE (op1) > var))
        return chrec_dont_know;
  
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (var, op0, op1);
      }
  
    return chrec;
--- 2268,2322 ----
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
+   /* When the instantiated stride or base has an evolution in an
+      innermost loop, return chrec_dont_know, as this is not a
+      valid SCEV representation.  In the reduced testcase for
+      PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no
+      meaning.  */
+   if (tree_does_not_contain_chrecs (op0))
+     ;
+   else
+     {
+       tree tem = op0;
+       while (TREE_CODE (tem) != POLYNOMIAL_CHREC)
+       {
+         if (CONVERT_EXPR_P (tem))
+           tem = TREE_OPERAND (tem, 0);
+         else
+           return chrec_dont_know;
+       }
+       if (!flow_loop_nested_p (get_chrec_loop (tem), get_chrec_loop (chrec)))
+       return chrec_dont_know;
+     }
+ 
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
                            CHREC_RIGHT (chrec), fold_conversions, cache,
                            size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
!   /* See above.  */
!   if (tree_does_not_contain_chrecs (op1))
!     ;
!   else
      {
!       tree tem = op1;
!       while (TREE_CODE (tem) != POLYNOMIAL_CHREC)
!       {
!         if (CONVERT_EXPR_P (tem))
!           tem = TREE_OPERAND (tem, 0);
!         else
!           return chrec_dont_know;
!       }
!       if (!flow_loop_nested_p (get_chrec_loop (tem), get_chrec_loop (chrec)))
        return chrec_dont_know;
+     }
  
+   if (CHREC_LEFT (chrec) != op0
+       || CHREC_RIGHT (chrec) != op1)
+     {
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
      }
  
    return chrec;
Index: gcc/testsuite/gcc.dg/torture/pr55555.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55555.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55555.c      (working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do run } */
+ 
+ double s[4] = { 1.0, 2.0, 3.0, 4.0 }, pol_x[2] = { 5.0, 6.0 };
+ 
+ __attribute__((noinline)) int
+ foo (void)
+ {
+   double coef_x[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+   int lxp = 0;
+   if (lxp <= 1)
+     do
+       {
+       double t = pol_x[lxp];
+       long S;
+       long l = lxp * 4L - 1;
+       for (S = 1; S <= 4; S++)
+         coef_x[S + l] = coef_x[S + l] + s[S - 1] * t;
+       }
+     while (lxp++ != 1);
+   asm volatile ("" : : "r" (coef_x) : "memory");
+   for (lxp = 0; lxp < 8; lxp++)
+     if (coef_x[lxp] != ((lxp & 3) + 1) * (5.0 + (lxp >= 4)))
+       __builtin_abort ();
+   return 1;
+ }
+ 
+ int
+ main ()
+ {
+   asm volatile ("" : : : "memory");
+   if (!foo ())
+     __builtin_abort ();
+   return 0;
+ }

Reply via email to