The sinking code currently does not heuristically avoid placing code into an irreducible region in the same way it avoids placing into a deeper loop nest. Critically for the PR we may not insert a VDEF into a irreducible region that does not contain a virtual definition. The following adds the missing heuristic and also a stop-gap for the VDEF issue - since we cannot determine validity inside an irreducible region we have to reject any VDEF movement with destination inside such region, even when it originates there. In particular irreducible sub-cycles are not tracked separately and can cause issues.
I chose to not complicate the already partly incomplete assert but prune it down to essentials. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/121756 * tree-ssa-sink.cc (select_best_block): Avoid irreducible regions in otherwise same loop depth. (statement_sink_location): When sinking a VDEF, never place that into an irreducible region. * gcc.dg/torture/pr121756.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr121756.c | 30 +++++++++++++++++++++++++ gcc/tree-ssa-sink.cc | 17 +++++++++----- 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr121756.c diff --git a/gcc/testsuite/gcc.dg/torture/pr121756.c b/gcc/testsuite/gcc.dg/torture/pr121756.c new file mode 100644 index 00000000000..37c5c50e47e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr121756.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ + +int a, b, *c = &b; +static void g(int i) { + int d = 0, e, f[] = {a}, j = a; + e = b; + if (e - i) + return; + a = 0; +h: + if (e) { + e = j; + if (f[3]) + goto k; + goto h; + } + while (1) { d = -1; + while (1) { + if (d - 1 - j < 0) + return; + k: + if (f[1]) + break; + } + } +} +int main() { + g(1); + return 0; +} diff --git a/gcc/tree-ssa-sink.cc b/gcc/tree-ssa-sink.cc index 2244e89fbb7..60dfe5282a7 100644 --- a/gcc/tree-ssa-sink.cc +++ b/gcc/tree-ssa-sink.cc @@ -245,6 +245,12 @@ select_best_block (basic_block early_bb, else if (bb_loop_depth (temp_bb) > bb_loop_depth (best_bb)) ; + /* Likewise an irreducible region inside an otherwise same loop + depth. */ + else if ((temp_bb->flags & BB_IRREDUCIBLE_LOOP) + && !(best_bb->flags & BB_IRREDUCIBLE_LOOP)) + ; + /* But sink the least distance, if the new candidate on the same loop depth is post-dominated by the current best block pick the new candidate. */ @@ -265,11 +271,7 @@ select_best_block (basic_block early_bb, } gcc_checking_assert (best_bb == early_bb - || (!do_not_sink (stmt, early_bb, best_bb) - && ((bb_loop_depth (best_bb) - < bb_loop_depth (early_bb)) - || !dominated_by_p (CDI_POST_DOMINATORS, - early_bb, best_bb)))); + || !do_not_sink (stmt, early_bb, best_bb)); return best_bb; } @@ -500,7 +502,10 @@ statement_sink_location (gimple *stmt, basic_block frombb, operand update, requiring inserting of a PHI node. */ || (gimple_vdef (stmt) && bestbb != sinkbb - && !dominated_by_p (CDI_POST_DOMINATORS, bestbb, sinkbb))) + && !dominated_by_p (CDI_POST_DOMINATORS, bestbb, sinkbb)) + /* Likewise avoid placing VDEFs into an irreducible region. */ + || (gimple_vdef (stmt) + && (bestbb->flags & BB_IRREDUCIBLE_LOOP))) return false; *togsi = gsi_after_labels (bestbb); -- 2.43.0