This is an updated patch to address BZ69740. When the patch was originally committed, there was a flurry of regressions related to the loop optimizers.
Essentially the loop optimizers would change the CFG and we'd conservatively set LOOPS_NEED_FIXUP. At the end of the given loop optimizer pass we'd call check_verify_loop_structure which would assert no loops need fixing up. Opps.
Richi noted that 1. The loop optimizers shouldn't be making changes to the CFG which result in needing loop fixups and 2. check_verify_loop_structure will verify that the loops don't need fixups and if they do it will complain.
Thus we can have check_verify_loop_structure clear LOOPS_NEED_FIXUP and let the normal verification run. This has the additional advantage that we don't do unnecessary loop fixup passes.
Bootstrapped and regression tested on x86_64-linux-gnu. Note that the tests for the regressions caused when the prior version of this patch are already in the testsuite. Installed on the trunk.
I'm going to hold off backporting for a bit this time. Thanks, Jeff
commit cbf273cb7415a5a2e3a09aa81f466526a97e7d17 Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon Mar 7 17:01:54 2016 +0000 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. * cfgloop.h (check_verify_loop_structure): Clear LOOPS_NEED_FIXUP. Move after definition of loops_state_clear. PR tree-optimization/69740 * gcc.c-torture/compile/pr69740-1.c: New test. * gcc.c-torture/compile/pr69740-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@234036 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bab6530..9f83f36 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2016-02-26 Richard Biener <rguent...@suse.de> + Jeff Law <l...@redhat.com> + + 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. + * cfgloop.h (check_verify_loop_structure): Clear LOOPS_NEED_FIXUP. + Move after definition of loops_state_clear. + 2016-03-07 Bin Cheng <bin.ch...@arm.com> PR rtl-optimization/69052 diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index bbb1017..06c05d1 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -408,7 +408,20 @@ void remove_edge (edge e) { if (current_loops != NULL) - rescan_loop_exit (e, false, true); + { + rescan_loop_exit (e, false, true); + + /* Removal of an edge inside an irreducible region or which leads + to an irreducible region can turn the region into a natural loop. + In that case, ask for the loop structure fixups. + + FIXME: Note that LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS is not always + set, so always ask for fixups when removing an edge in that case. */ + 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/cfgloop.h b/gcc/cfgloop.h index 882861c..54e738f 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -314,16 +314,6 @@ extern void delete_loop (struct loop *); extern void verify_loop_structure (void); -/* Check loop structure invariants, if internal consistency checks are - enabled. */ - -static inline void -checking_verify_loop_structure (void) -{ - if (flag_checking) - verify_loop_structure (); -} - /* Loop analysis. */ extern bool just_once_each_iteration_p (const struct loop *, const_basic_block); gcov_type expected_loop_iterations_unbounded (const struct loop *); @@ -546,6 +536,28 @@ loops_state_clear (unsigned flags) loops_state_clear (cfun, flags); } +/* Check loop structure invariants, if internal consistency checks are + enabled. */ + +static inline void +checking_verify_loop_structure (void) +{ + /* VERIFY_LOOP_STRUCTURE essentially asserts that no loops need fixups. + + The loop optimizers should never make changes to the CFG which + require loop fixups. But the low level CFG manipulation code may + set the flag conservatively. + + Go ahead and clear the flag here. That avoids the assert inside + VERIFY_LOOP_STRUCTURE, and if there is an inconsistency in the loop + structures VERIFY_LOOP_STRUCTURE will detect it. + + This also avoid the compile time cost of excessive fixups. */ + loops_state_clear (LOOPS_NEED_FIXUP); + if (flag_checking) + verify_loop_structure (); +} + /* Loop iterators. */ /* Flags for loop iteration. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4447ba6..bf8e231 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-02-26 Richard Biener <rguent...@suse.de> + Jeff Law <l...@redhat.com> + + PR tree-optimization/69740 + * gcc.c-torture/compile/pr69740-1.c: New test. + * gcc.c-torture/compile/pr69740-2.c: New test. + 2016-03-07 Bill Schmidt <wschm...@linux.vnet.ibm.com> * lib/target-supports.exp 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(); + } +}