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? Thanks, Richard. 2016-02-22 Richard Biener <rguent...@suse.de> PR middle-end/68963 * tree-ssa-loop-niter.c (idx_infer_loop_bounds): Do not record an upper bound for accesses not always executed. Do not record an estimate for accesses with wrapping IVs. * gcc.dg/torture/pr68963.c: New testcase. Index: gcc/tree-ssa-loop-niter.c =================================================================== *** gcc/tree-ssa-loop-niter.c (revision 233598) --- gcc/tree-ssa-loop-niter.c (working copy) *************** idx_infer_loop_bounds (tree base, tree * *** 3183,3196 **** && tree_int_cst_compare (next, high) <= 0) return true; ! /* If access is not executed on every iteration, we must ensure that overlow may ! not make the access valid later. */ ! if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt)) ! && scev_probably_wraps_p (initial_condition_in_loop_num (ev, loop->num), ! step, data->stmt, loop, true)) reliable = false; ! record_nonwrapping_iv (loop, init, step, data->stmt, low, high, reliable, upper); return true; } --- 3183,3200 ---- && tree_int_cst_compare (next, high) <= 0) return true; ! /* If access is not executed on every iteration we cannot derive any ! upper bound. */ ! if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt))) ! upper = false; ! /* If the IV of the access may wrap then the array size is not good for ! an estimate either. */ ! if (scev_probably_wraps_p (initial_condition_in_loop_num (ev, loop->num), ! step, data->stmt, loop, true)) reliable = false; ! record_nonwrapping_iv (loop, init, step, data->stmt, low, high, ! reliable, upper); return true; } 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; + }