From d03a67dc69251dc86c0772a432380a6e9bcb8617 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 15 Feb 2022 12:27:14 +0100 Subject: [PATCH] tree-optimization/104543 - fix unroll-and-jam precondition 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. 2022-02-15 Richard Biener 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 --git a/gcc/gimple-loop-jam.cc b/gcc/gimple-loop-jam.cc index d9a7772..e33dd90 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 0000000..4896351 --- /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; +} -- 2.7.4