When unrolling changes nesting relationship of loops we fail to mark blocks as in need to change for LC SSA update. Specifically the LC SSA PHI on a former inner loop exit might be misplaced if that loop becomes a sibling of its outer loop.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/118552 * cfgloopmanip.cc (fix_loop_placement): Properly mark exit source blocks as to be scanned for LC SSA update when the loops nesting relationship changed. (fix_loop_placements): Adjust. (fix_bb_placements): Likewise. * gcc.dg/torture/pr118552.c: New testcase. --- gcc/cfgloopmanip.cc | 13 +++++++--- gcc/testsuite/gcc.dg/torture/pr118552.c | 34 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr118552.c diff --git a/gcc/cfgloopmanip.cc b/gcc/cfgloopmanip.cc index 17bcf9f4acc..573146b2e28 100644 --- a/gcc/cfgloopmanip.cc +++ b/gcc/cfgloopmanip.cc @@ -123,7 +123,8 @@ fix_bb_placement (basic_block bb) invalidate the information about irreducible regions. */ static bool -fix_loop_placement (class loop *loop, bool *irred_invalidated) +fix_loop_placement (class loop *loop, bool *irred_invalidated, + bitmap loop_closed_ssa_invalidated) { unsigned i; edge e; @@ -153,6 +154,10 @@ fix_loop_placement (class loop *loop, bool *irred_invalidated) if (e->flags & EDGE_IRREDUCIBLE_LOOP) *irred_invalidated = true; rescan_loop_exit (e, false, false); + /* Any LC SSA PHIs on e->dest might now be on the wrong edge + if their defs were in a former outer loop. */ + if (loop_closed_ssa_invalidated) + bitmap_set_bit (loop_closed_ssa_invalidated, e->src->index); } ret = true; @@ -224,7 +229,8 @@ fix_bb_placements (basic_block from, if (from->loop_father->header == from) { /* Subloop header, maybe move the loop upward. */ - if (!fix_loop_placement (from->loop_father, irred_invalidated)) + if (!fix_loop_placement (from->loop_father, irred_invalidated, + loop_closed_ssa_invalidated)) continue; target_loop = loop_outer (from->loop_father); if (loop_closed_ssa_invalidated) @@ -1057,7 +1063,8 @@ fix_loop_placements (class loop *loop, bool *irred_invalidated, while (loop_outer (loop)) { outer = loop_outer (loop); - if (!fix_loop_placement (loop, irred_invalidated)) + if (!fix_loop_placement (loop, irred_invalidated, + loop_closed_ssa_invalidated)) break; /* Changing the placement of a loop in the loop tree may alter the diff --git a/gcc/testsuite/gcc.dg/torture/pr118552.c b/gcc/testsuite/gcc.dg/torture/pr118552.c new file mode 100644 index 00000000000..03ee0d0ca3f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr118552.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-ch -fno-tree-ccp -fno-tree-fre" } */ + +volatile int a; +int b, c, d, e; +int main() { + int f = 1, g = 1; +h: + if (!d) + ; + else { + int i = 1; + j: + e = 0; + for (; e < 3; e++) { + if (e) + for (; g < 2; g++) { + if (c) + return 0; + if (f) + goto j; + } + a; + if (i) + continue; + f = i = 0; + } + } + f = 2; + b++; + if (c) + goto h; + return 0; +} -- 2.43.0