https://gcc.gnu.org/g:1265afa91d51606605f85e732344e86e4e4dae9b
commit r15-7059-g1265afa91d51606605f85e732344e86e4e4dae9b Author: Richard Biener <rguent...@suse.de> Date: Mon Jan 20 11:50:53 2025 +0100 tree-optimization/118552 - failed LC SSA update after unrolling 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. 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. Diff: --- gcc/cfgloopmanip.cc | 13 ++++++++++--- gcc/testsuite/gcc.dg/torture/pr118552.c | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/gcc/cfgloopmanip.cc b/gcc/cfgloopmanip.cc index 17bcf9f4acc4..573146b2e284 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 000000000000..03ee0d0ca3f2 --- /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; +}