diff mbox series

tree-optimization/104543 - fix unroll-and-jam precondition

Message ID 20220215122208.13FED13C73@imap2.suse-dmz.suse.de
State New
Headers show
Series tree-optimization/104543 - fix unroll-and-jam precondition | expand

Commit Message

Richard Biener Feb. 15, 2022, 12:22 p.m. UTC
We have to make sure that outer loop exits come after the inner
loop since we otherwise will put it into the fused loop body.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

2022-02-15  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/104543
	* gimple-loop-jam.cc (unroll_jam_possible_p): Check outer loop exits
	come after the inner loop.

	* gcc.dg/torture/pr104543.c: New testcase.
---
 gcc/gimple-loop-jam.cc                  | 10 ++++++++--
 gcc/testsuite/gcc.dg/torture/pr104543.c | 21 +++++++++++++++++++++
 2 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr104543.c
diff mbox series

Patch

diff --git a/gcc/gimple-loop-jam.cc b/gcc/gimple-loop-jam.cc
index d9a77727665..e33dd9091df 100644
--- a/gcc/gimple-loop-jam.cc
+++ b/gcc/gimple-loop-jam.cc
@@ -198,7 +198,8 @@  unroll_jam_possible_p (class loop *outer, class loop *loop)
   if (!empty_block_p (loop->latch))
     return false;
 
-  if (!single_exit (loop))
+  edge exit;
+  if (!(exit = single_exit (loop)))
     return false;
 
   /* We need a perfect nest.  Quick check for adjacent inner loops.  */
@@ -259,7 +260,12 @@  unroll_jam_possible_p (class loop *outer, class loop *loop)
   n = get_loop_body_with_size (outer, bbs, n_basic_blocks_for_fn (cfun));
 
   for (i = 0; i < n; i++)
-    if (bbs[i]->loop_father == outer && bb_prevents_fusion_p (bbs[i]))
+    if (bbs[i]->loop_father == outer
+	&& (bb_prevents_fusion_p (bbs[i])
+	    /* Outer loop exits must come after the inner loop, otherwise
+	       we'll put the outer loop exit into the fused inner loop.  */
+	    || (loop_exits_from_bb_p (outer, bbs[i])
+		&& !dominated_by_p (CDI_DOMINATORS, bbs[i], exit->src))))
       break;
   free (bbs);
   if (i != n)
diff --git a/gcc/testsuite/gcc.dg/torture/pr104543.c b/gcc/testsuite/gcc.dg/torture/pr104543.c
new file mode 100644
index 00000000000..48963514f77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr104543.c
@@ -0,0 +1,21 @@ 
+/* { dg-do run } */
+/* { dg-additional-options "-floop-unroll-and-jam" } */
+
+int a[3], b, c;
+static int e()
+{
+  if (!c) {
+    for (b = 0; b < 3; b++)
+      for (c = 0; c < 3; c++)
+        a[c] ^= 1;
+    return -1;
+  }
+  return 0;
+}
+int main()
+{
+  e();
+  if (a[1] != 1)
+    __builtin_abort();
+  return 0;
+}