PR69740 shows two instances where one or more transformations ultimately
lead to the removal of a basic block.
In both cases, removal of the basic block removes a path into an
irreducible region and turns the irreducible region into a natural loop.
When that occurs we need to be requesting loops to be fixed up.
My first patch was to handle this is was in tree-ssa-dce.c and that
fixed the initial problem report. As I was cobbling the patch together,
I pondered putting the changes into delete_basic_block because that
would capture other instances of this problem.
When I looked at the second instance, it came via a completely different
path (tail merging). Again it was a case where we called
delete_basic_block which in turn changed an irreducible region into a
natural loop. So I tossed my original patch and put the test into
delete_basic_block as you see here.
Bootstrapped and regression tested on x86_64-linux-gnu. OK for the
trunk and the gcc-5 branch after a suitable soak time?
Jeff
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 913abc8..42e5b4f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-24 Jeff Law <l...@redhat.com>
+
+ PR tree-optimization/69740
+ * cfghooks.c (delete_basic_block): Request loop fixups if we delete
+ a block with an outgoing edge to a block marked as being in anx
+ irreducible region.
+
2016-02-24 Jason Merrill <ja...@redhat.com>
* common.opt (flifetime-dse): Add -flifetime-dse=1.
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index bbb1017..4d31aa9 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -574,6 +574,14 @@ delete_basic_block (basic_block bb)
if (!cfg_hooks->delete_basic_block)
internal_error ("%s does not support delete_basic_block", cfg_hooks->name);
+ /* Look at BB's successors, if any are marked as BB_IRREDUCIBLE_LOOP, then
+ removing BB (and its outgoing edges) may make the loop a natural
+ loop. In which case we need to schedule loop fixups. */
+ if (current_loops)
+ for (edge_iterator ei = ei_start (bb->succs); !ei_end_p (ei); ei_next
(&ei))
+ if (ei_edge (ei)->dest->flags & BB_IRREDUCIBLE_LOOP)
+ loops_state_set (LOOPS_NEED_FIXUP);
+
cfg_hooks->delete_basic_block (bb);
if (current_loops != NULL)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 311232f..b0df819 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-04 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-02-24 Martin Sebor <mse...@redhat.com>
PR c++/69912
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();
+ }
+}