aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cfghooks.c15
-rw-r--r--gcc/cfgloop.h32
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr69740-1.c12
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr69740-2.c19
6 files changed, 84 insertions, 11 deletions
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 <rguenther@suse.de>
+ Jeff Law <law@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.cheng@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 <rguenther@suse.de>
+ Jeff Law <law@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 <wschmidt@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();
+ }
+}