https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65258

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
There are of course two issues here - one VRP not optimizing away the dead code
and unrolling creating the dead code in the first place (thus number of
iteration
analysis being not very precise).

Number of iteration analysis has a hard time exercising SCEV here as that
cannot
handle division (generally such IVs are not affine, in this case the evolution
of j/8 is not affine in the j loop).

Now for the VRP issue it is forwprop that replaces the sequence of i-- with
i = j/8 - 1, i = j/8 - 2, ... thereby making VRPs life hard with

  <bb 3>:
  i_9 = j_3 / 8;
  i_26 = i_9 + 4294967295;
  if (i_9 != 0)
    goto <bb 4>;
  else
    goto <bb 14>;

  <bb 4>:
  a[i_26] = 0;
  i_30 = i_9 + 4294967294;
  if (i_26 != 0)
    goto <bb 5>;
  else
    goto <bb 14>;

  <bb 5>:
  a[i_30] = 0;
  i_34 = i_9 + 4294967293;
  if (i_30 != 0)
    goto <bb 6>;
  else
    goto <bb 14>;

where the assertion on i_26 != 0 doesn't help it improving the range
for i_34 (which is based on i_9 again).

Disabling forwprop2 fixes the warning and makes VRP1 do its job.  It is
match.pd:491 that does the transform.

Of course I can write the problematic code in plain C as well so VRP should
better deal with it somehow.

We can "easily" do

  i_38 = i_53 + 4294967292;
  if (i_34 != 0)
    goto <bb 7>;
  else
    goto <bb 14>;

  <bb 7>:
  i_56 = ASSERT_EXPR <i_53, i_53 != 3>;
  a[i_38] = 0;
  i_42 = i_56 + 4294967291;
  if (i_38 != 0)
    goto <bb 8>;
  else 
    goto <bb 14>;

  <bb 8>: 
  i_57 = ASSERT_EXPR <i_56, i_56 != 4>;
  a[i_42] = 0;

but then we'd still need an assert for i_42 as well which is quite backward.

In fact the way VRP works makes this quite hard to do.  For a "real"
sophisticated VRP we'd walk the full dominator tree dominating each
predicate to compute value-ranges for SSA names dominated by those predicates
(but that's quadratic).

That said - with the above we are down to a single warning (but the code is
not removed).  We are not able to simplify the last branch to false and
the branch after gets UNDEFINED into the comparison so we can fold either
way (we could put builtin_unreachable before that branch...).

So - not sure if improving to

t.c: In function 'main':
t.c:8:3: warning: array subscript is above array bounds [-Warray-bounds]
  a[i] = 0;
   ^

is worth it.

Reply via email to