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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |hubicka at gcc dot gnu.org

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
We enter cunroll with

  <bb 2> [local count: 10631108]:

  <bb 3> [local count: 284435276]:
  # RANGE [irange] int [0, 2]
  # counter_4 = PHI <counter_6(5), 0(2)>

  <bb 4> [local count: 1073741823]:
  if (counter_4 == 2)
    goto <bb 6>; [74.50%]
  else
    goto <bb 5>; [25.50%]

  <bb 6> [local count: 799937655]:
  goto <bb 4>; [100.00%]

  <bb 5> [local count: 273804168]:
  # RANGE [irange] int [1, 2]
  counter_6 = counter_4 + 1;
  # USE = nonlocal escaped null 
  # CLB = nonlocal escaped null 
  printf ("%i\n", counter_4);
  goto <bb 3>; [100.00%]

and then we do

Estimating # of iterations of loop 2
Loop 1 iterates at most 1 times.
Loop 1 likely iterates at most 1 times.

which is wrong.  I think the issue is in record_nonwrapping_iv which in
r6-7091-ge53d562a36ead2 got a fix not using ranges from not always executing
stmts (but oddly enough gating only one end, and seemingly the wrong one?).
In this case the inner endless loops makes the apparent post-dominated
block with the increment actually _not_ execute.

So that "always executed" thing is not properly implemented (we also expect
the caller to pass "upper" as false).

Similar case could be constructed by accessing an array with fixed bounds
in the latch, the "simple" case

int a[3];
int foo(void) {
    unsigned counter = 0;
    while (1) {
        if (counter >= 2) continue;
        printf("%i\n", a[++counter]);
    }
    return 0;
}

works because with -O2 we refuse unrolling due to code size growth:

Loop 1 iterates at most 1 times.
Loop 1 likely iterates at most 1 times.
...
Not unrolling loop 1: it is not innermost and code would grow.

That said, we do not handle possibly infinite subloops or calls that might
not return as properly blocking any of the
number-of-iteration-because-of-undefined-behavior heuristics.

Interestingly enough the following also "works" (unrolling also increases
code size, but we compute two iterations for this).

void __attribute__((noipa)) bar (int i)
{
  if (i == __INT_MAX__)
    while (1);
}

int a[3];
int foo(void) {
    int counter = __INT_MAX__ - 2;
    while (1) {
        bar (counter);
        printf("%i\n", counter++);
    }
    return 0;
}

this needs some investigation more in detail but the underlying issue is that
we do not model inner loops or calls correctly here.

Probably best done in infer_loop_bounds_from_undefined itself which walks
BBs and stmts.  I'll note it's tricky as even

  if (foo)
    bar ();
  ++counter;

thus a conditional call should be a blocker for this.  Honza - I guess
IPA modref has done this kind of "walking" already, is there a place
to copy / factor for this?

Reply via email to