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();
+  }
+}

Reply via email to