https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120560
--- Comment #6 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Richard Biener from comment #1)
> We have eliminated the exit in EVRP, it's input was
>
> <bb 2> :
>
> <bb 3> :
> # b_2 = PHI <2(2), b_8(5)>
> _1 = 1 - b_2;
> if (_1 > 6)
> goto <bb 4>; [INV]
> else
> goto <bb 5>; [INV]
>
> <bb 4> :
> // predicted unlikely by early return (on trees) predictor.
> return 0;
>
> <bb 5> :
> b_8 = b_2 + -2147483648;
> goto <bb 3>; [INV]
>
> which I think is OK.
>
> During EVRP we do SCEV / niter analysis and there it gets fishy, so this
> is likely another case of SCEV messing up overflow:
>
> Analyzing # of iterations of loop 1
> exit condition [-1, + , -2147483648(OVF)](no_overflow) <= 6
> bounds on difference of bases: 7 ... 7
> failed
>
> Induction variable (int) -1 + -2147483648(OVF) * iteration does not wrap in
> statement _1 = 1 - b_2;
> in loop 1.
> Statement _1 = 1 - b_2;
> is executed at most 0(OVF) (bounded by 0) + 1 times in loop 1.
>
> this is the IV for _1 and that looks wrong?
indeed. Tracing it, it seems to boil down to
// Calculate the final range of NAME if possible.
if (rinit.singleton_p () && rstep.singleton_p ())
{
widest_int nit;
if (!max_loop_iterations (l, &nit))
return false;
if (!induction_variable_may_overflow_p (type, rstep.lower_bound (), nit))
{
// Calculate the max bounds for init (init + niter * step).
wide_int w = wide_int::from (nit, TYPE_PRECISION (type), TYPE_SIGN
(type));
int_range<1> niter (type, w, w);
int_range_max max_step;
range_op_handler mult_handler (MULT_EXPR);
range_op_handler plus_handler (PLUS_EXPR);
if (!mult_handler.fold_range (max_step, type, niter, rstep)
|| !plus_handler.fold_range (max_init, type, rinit, max_step))
return false;
}
}
rinit is [2,2] an rstep is [-INF, -INF]
the call into tree-ssa-loop-niter.cc::max_loop_iterations is returning 0...
that seems wrong? we seem to iterate once.
anyway, with 0 being returned, we decide max_step is 0 * -INF, which is zero,
and then the initial value is 2+ 0, and always get [2,2] for the entire range.
If I make a change to punt if max_loop_iterations returns 0, then we avoid the
incorrect calculation and things work like they should.
Should 0 be returned? if so, perhaps bailing if the number of iteration is 0
would be worthwhile?
ie
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index ff11656559b..0cbd35fe848 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -316,7 +316,7 @@ range_of_var_in_loop (vrange &v, tree name, class loop *l,
gimple *stmt,
if (rinit.singleton_p () && rstep.singleton_p ())
{
widest_int nit;
- if (!max_loop_iterations (l, &nit))
+ if (!max_loop_iterations (l, &nit)) || nit == 0)
return false;
if (!induction_variable_may_overflow_p (type, rstep.lower_bound (),
nit))
If I hack it to be 1 when 0 is returned for this testcase, I also get the same
results as if I punt.. so 1 seems like the right answer?