On Fri, Feb 26, 2016 at 8:50 AM, Jeff Law <l...@redhat.com> wrote: > On 02/25/2016 03:00 AM, Richard Biener wrote: >> >> >> So I fail to see how only successor edges are relevant. Isn't the >> important >> case to catch whether we remove an edge marked EDGE_IRREDUCIBLE_LOOP? >> Even if the BB persists we might have exposed a new loop here. >> >> Note that it is not safe to look at {BB,EDGE}_IRREDUCIBLE_LOOP if the loop >> state does not have LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS set >> (the flags may be stale or missing). So it might be that we can't rely on >> non-loop passes modifying the CFG to handle this optimistically. >> >> Thus, how about (my main point) moving this to remove_edge instead, like > > Yea. That works. The !loops_state_satisfies_p check will almost certainly > cause us to trigger loop cleanups more often, but I think it's the > right/safe thing to do to catch cases where we haven't go the > IRREDUCIBLE_LOOP flags set. > > > Bootstrapped and regression tested on x86_64-linux-gnu. OK for the trunk?
Ok with a comment added before that check. Richard. > Thanks, > Jeff > > > PR tree-optimization/69740 > * cfghooks.c (remove_edge): Request loop fixups if we delete > an edge that might turn an irreducible loop into a natural > loop. > > PR tree-optimization/69740 > * gcc.c-torture/compile/pr69740-1.c: New test. > * gcc.c-torture/compile/pr69740-2.c: New test. > > diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c > index bbb1017..f80e455 100644 > --- a/gcc/cfghooks.c > +++ b/gcc/cfghooks.c > @@ -408,7 +408,14 @@ void > remove_edge (edge e) > { > if (current_loops != NULL) > - rescan_loop_exit (e, false, true); > + { > + rescan_loop_exit (e, false, true); > + > + if (!loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS) > + || (e->flags & EDGE_IRREDUCIBLE_LOOP) > + || (e->dest->flags & BB_IRREDUCIBLE_LOOP)) > + loops_state_set (LOOPS_NEED_FIXUP); > + } > > /* This is probably not needed, but it doesn't hurt. */ > /* FIXME: This should be called via a remove_edge hook. */ > diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c > b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c > new file mode 100644 > index 0000000..ac867d8 > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c > @@ -0,0 +1,12 @@ > +char a; > +short b; > +void fn1() { > + if (b) > + ; > + else { > + int c[1] = {0}; > + l1:; > + } > + if (a) > + goto l1; > +} > diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c > b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c > new file mode 100644 > index 0000000..a89c9a0 > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c > @@ -0,0 +1,19 @@ > +inline int foo(int *p1, int p2) { > + int z = *p1; > + while (z > p2) > + p2 = 2; > + return z; > +} > +int main() { > + int i; > + for (;;) { > + int j, k; > + i = foo(&k, 7); > + if (k) > + j = i; > + else > + k = j; > + if (2 != j) > + __builtin_abort(); > + } > +} >