aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2025-09-03 10:41:17 +0200
committerRichard Biener <rguenth@gcc.gnu.org>2025-09-03 14:33:36 +0200
commitdf64893e7082d7fae5d6863fd02371b37c78557f (patch)
tree17efa550baadd114e4b164c6cef68a69fc1251d1 /gcc
parentc8a24f60b6874fca4fb3adb153f8d5f1dd72b951 (diff)
downloadgcc-df64893e7082d7fae5d6863fd02371b37c78557f.zip
gcc-df64893e7082d7fae5d6863fd02371b37c78557f.tar.gz
gcc-df64893e7082d7fae5d6863fd02371b37c78557f.tar.bz2
tree-optimization/121756 - handle irreducible regions when sinking
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. 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121756.c30
-rw-r--r--gcc/tree-ssa-sink.cc17
2 files changed, 41 insertions, 6 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr121756.c b/gcc/testsuite/gcc.dg/torture/pr121756.c
new file mode 100644
index 0000000..37c5c50
--- /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 2244e89f..60dfe528 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);