On Mon, 22 Feb 2016, Richard Biener wrote:

> 
> The following patch fixes invalid upper bounds recorded for conditonal
> array accesses - it doesn't depend on whether their IV wrap or not
> (and we were unsetting 'reliable' only anyway).  In fact conditional
> accesses should be good enough for an estimate, just wrapping ones
> not.  Until we determine whether the controlling expression is
> dependent on the loop IV that's probably the best to do here.
> 
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
> 
> Honza, about reliable vs. non-reliable - was that the original intent
> or did you want to always record 'reliable' but really reset 'upper'
> here?

Ok, so this was the wrong place to fix and we should actually record
those bounds.  But the actual bound recorded is wrong as
record_nonwrapping_iv for IVs { -y, +, 1 }_1 and an array index
range of [0, 3] falls back to using 0 for the initial value of the
IV for the purpose of niter compute - that's of course only valid
if the stmt is always executed.

And in fact if the IV were { -1, +, 1 }_1 and the array index
range [0, 3] we could conclude the loop doesn't loop at all as
the first iteration would contain undefined behavior (if the
stmt was always executed) - currently we compute an upper bound
of 3 - (-1) here which is overly conservative.

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

Richard.

2016-02-24  Richard Biener  <rguent...@suse.de>

        PR middle-end/68963
        * tree-ssa-loop-niter.c (derive_constant_upper_bound_ops): Fix
        bogus check.
        (record_nonwrapping_iv): Do not fall back to the low/high bound
        for non-constant IV bases if the stmt is not always executed.

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

Index: gcc/testsuite/gcc.dg/torture/pr68963.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr68963.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr68963.c      (working copy)
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do run } */
+ 
+ static const float a[3] = { 1, 2, 3 };
+ int b = 3;
+ 
+ __attribute__((noinline, noclone)) void
+ bar (int x)
+ {
+   if (x != b++)
+     __builtin_abort ();
+ }
+ 
+ void
+ foo (float *x, int y)
+ {
+   int i;
+   for (i = 0; i < 2 * y; ++i)
+     {
+       if (i < y)
+       x[i] = a[i];
+       else
+       {
+         bar (i);
+         x[i] = a[i - y];
+       }
+     }
+ }
+ 
+ int
+ main ()
+ {
+   float x[10];
+   unsigned int i;
+   for (i = 0; i < 10; ++i)
+     x[i] = 1337;
+   foo (x, 3);
+   for (i = 0; i < 10; ++i)
+     if (x[i] != (i < 6 ? (i % 3) + 1 : 1337))
+       __builtin_abort ();
+   return 0;
+ }
Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c   (revision 233634)
--- gcc/tree-ssa-loop-niter.c   (working copy)
*************** derive_constant_upper_bound_ops (tree ty
*** 2757,2763 ****
                                 enum tree_code code, tree op1)
  {
    tree subtype, maxt;
!   widest_int bnd, max, mmax, cst;
    gimple *stmt;
  
    if (INTEGRAL_TYPE_P (type))
--- 2757,2763 ----
                                 enum tree_code code, tree op1)
  {
    tree subtype, maxt;
!   widest_int bnd, max, cst;
    gimple *stmt;
  
    if (INTEGRAL_TYPE_P (type))
*************** derive_constant_upper_bound_ops (tree ty
*** 2823,2830 ****
          /* OP0 + CST.  We need to check that
             BND <= MAX (type) - CST.  */
  
!         mmax -= cst;
!         if (wi::ltu_p (bnd, max))
            return max;
  
          return bnd + cst;
--- 2823,2830 ----
          /* OP0 + CST.  We need to check that
             BND <= MAX (type) - CST.  */
  
!         widest_int mmax = max - cst;
!         if (wi::leu_p (bnd, mmax))
            return max;
  
          return bnd + cst;
*************** record_nonwrapping_iv (struct loop *loop
*** 3065,3071 ****
          && get_range_info (orig_base, &min, &max) == VR_RANGE
          && wi::gts_p (high, max))
        base = wide_int_to_tree (unsigned_type, max);
!       else if (TREE_CODE (base) != INTEGER_CST)
        base = fold_convert (unsigned_type, high);
        delta = fold_build2 (MINUS_EXPR, unsigned_type, base, extreme);
        step = fold_build1 (NEGATE_EXPR, unsigned_type, step);
--- 3065,3073 ----
          && get_range_info (orig_base, &min, &max) == VR_RANGE
          && wi::gts_p (high, max))
        base = wide_int_to_tree (unsigned_type, max);
!       else if (TREE_CODE (base) != INTEGER_CST
!              && dominated_by_p (CDI_DOMINATORS,
!                                 loop->latch, gimple_bb (stmt)))
        base = fold_convert (unsigned_type, high);
        delta = fold_build2 (MINUS_EXPR, unsigned_type, base, extreme);
        step = fold_build1 (NEGATE_EXPR, unsigned_type, step);
*************** record_nonwrapping_iv (struct loop *loop
*** 3080,3086 ****
          && get_range_info (orig_base, &min, &max) == VR_RANGE
          && wi::gts_p (min, low))
        base = wide_int_to_tree (unsigned_type, min);
!       else if (TREE_CODE (base) != INTEGER_CST)
        base = fold_convert (unsigned_type, low);
        delta = fold_build2 (MINUS_EXPR, unsigned_type, extreme, base);
      }
--- 3082,3090 ----
          && get_range_info (orig_base, &min, &max) == VR_RANGE
          && wi::gts_p (min, low))
        base = wide_int_to_tree (unsigned_type, min);
!       else if (TREE_CODE (base) != INTEGER_CST
!              && dominated_by_p (CDI_DOMINATORS,
!                                 loop->latch, gimple_bb (stmt)))
        base = fold_convert (unsigned_type, low);
        delta = fold_build2 (MINUS_EXPR, unsigned_type, extreme, base);
      }

Reply via email to