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?

Reply via email to