From: Richard Biener Date: Wed, 1 Oct 2025 12:55:17 +0000 (+0200) Subject: tree-optimization/122079 - PRE antic compute doesn't converge X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f8c6f479e65af985d4d374cc9b3405327124d66;p=thirdparty%2Fgcc.git tree-optimization/122079 - PRE antic compute doesn't converge The following re-instantiates the pruning of the ANTIC_IN value set by the previous iterations one by reverting part of r16-3945-gc30f58c3f7ec25. The earlier fixes made sure the initial value set is appropriately big to not cause this to lose optimizations. But it seems to be still required for correctness given iteration order means we combine ANTIC_IN sets from different generations which can be prone to oscillations in CFG cycles. PR tree-optimization/122079 * tree-ssa-pre.cc (compute_antic_aux): Re-instantiate ANTIC_IN value pruning by the old solution. * gcc.dg/torture/pr122079-2.c: New testcase. * gcc.dg/torture/pr122079-3.c: Likewise. --- diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-2.c b/gcc/testsuite/gcc.dg/torture/pr122079-2.c new file mode 100644 index 00000000000..40c36b0feff --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr122079-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ + +int a, b, *c = &a, d, e, f; +void g(int *p) { a = p[0]; } +int main() { + int h = 0; +i: + d = c[0]; + c[0] = h; + if (a) + goto j; +k: + h = c[0] - 1; + while (1) { + if (b) + goto i; + if (f) + goto k; + j: + if (!e) { + int m[] = {c[0]}; + g(m); + break; + } + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-3.c b/gcc/testsuite/gcc.dg/torture/pr122079-3.c new file mode 100644 index 00000000000..df95c718199 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr122079-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-im" } */ + +int a, b, c; +void d(int[]); +void e(int f[][2]) { +g: + b = f[0][1]; + if (c) + goto h; +i: + if (a) + goto g; + if (f[1][1]) + goto j; +h: + if (f[1][1]) + goto i; + goto k; +j: + b--; + if (b + f[0][1]) + goto i; +k: + int l[] = {f[0][1]}; + d(l); +} diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc index d08caab952a..2a7dcbee52c 100644 --- a/gcc/tree-ssa-pre.cc +++ b/gcc/tree-ssa-pre.cc @@ -2084,6 +2084,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge) edge e; edge_iterator ei; + bool was_visited = BB_VISITED (block); bool changed = ! BB_VISITED (block); bool any_max_on_edge = false; @@ -2219,6 +2220,32 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge) /* clean (ANTIC_IN (block)) is defered to after the iteration converged because it can cause non-convergence, see for example PR81181. */ + if (was_visited + && bitmap_and_into (&ANTIC_IN (block)->values, &old->values)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "warning: intersecting with old ANTIC_IN " + "shrinks the set\n"); + /* Prune expressions not in the value set. */ + bitmap_iterator bi; + unsigned int i; + unsigned int to_clear = -1U; + FOR_EACH_EXPR_ID_IN_SET (ANTIC_IN (block), i, bi) + { + if (to_clear != -1U) + { + bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear); + to_clear = -1U; + } + pre_expr expr = expression_for_id (i); + unsigned int value_id = get_expr_value_id (expr); + if (!bitmap_bit_p (&ANTIC_IN (block)->values, value_id)) + to_clear = i; + } + if (to_clear != -1U) + bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear); + } + if (!bitmap_set_equal (old, ANTIC_IN (block))) changed = true;