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

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #3)
> Found partial redundancy for expression {trunc_mod_expr,1,p_9(D)} (0008)
> Inserted _33 = 1 % p_9(D);
>  in predecessor 13 (0008)
> Inserting expression in block 5 for code hoisting: {trunc_mod_expr,1,p_9(D)}
> (0008)
> Inserted _37 = 1 % p_9(D);
>  in predecessor 5 (0008)
> Inserting expression in block 3 for code hoisting: {trunc_mod_expr,1,p_9(D)}
> (0008)
> Inserted _39 = 1 % p_9(D);
>  in predecessor 3 (0008)
> 
> with code hoisting disabled the issue is gone but the PRE insertion exposes
> the issue, making 1 % p_9(D) computed on all paths and making the hositing
> valid.

OK, so the partial redundancy is because 1 % p_9(D) is ANTIC_IN in the loop
exit, given we have not visited the in-loop continuation of the exit test
block the ANTIC_IN solution is MAX there making 1 % p_9(D) ANTIC_IN in the
loop header and thus in the latch where it then causes it to be ANTIC_IN
in the if (p_9(D) == 0) condition block.

I think this is correct and working as intended - note that the PRE
dataflow assumes that an edge is eventually executed (in this case,
a loop eventually terminates).  A similar "problem" can be constructed
by placing a call in a path that never returns (but the compiler not
knowing) - expressions after it will still be ANTIC at the start of the
block.

We can mitigate this by removing all traps from the expression set when
we have any of the ANTIC_INs MAX given we then implicitly relying on
the other edges being executed.

This might pessimize things quite a bit though given most memory references
can trap in the simplified analysis PRE performs and the problem of course also
trivially applies to null pointer checks and dereferences.

int x;
void __attribute__((noipa))
foo (int *p, unsigned n)
{
  unsigned i = 0;
  do
    {
      if (i == n)
        break;
      if (p)
        x = *p;
      i += 2;
    }
  while (1);
  x = *p;
}

int main ()
{
  foo ((int *)0, 1);  
}

shows this happening with -O2 -fno-tree-ch.

Reply via email to