https://gcc.gnu.org/g:b052d6bbbeea2b04c8a4f765e89b0b3f19f81764
commit r17-2053-gb052d6bbbeea2b04c8a4f765e89b0b3f19f81764 Author: Richard Biener <[email protected]> Date: Fri Jun 26 16:28:52 2026 +0200 tree-optimization/125040 - iterate PRE clean The testcase has a cycle in the value graph of ANTIC_IN, this means we have to iterate to correctly prune all invalid expressions. PR tree-optimization/125040 * tree-ssa-pre.cc (clean): Iterate processing. * gcc.dg/torture/pr125040.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/torture/pr125040.c | 14 ++++++++++++ gcc/tree-ssa-pre.cc | 38 +++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/gcc/testsuite/gcc.dg/torture/pr125040.c b/gcc/testsuite/gcc.dg/torture/pr125040.c new file mode 100644 index 000000000000..be732084cb0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr125040.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +int a() { + int b; + int *c = __builtin_calloc(sizeof(int), b); + int count; + for (int d; d;) + for (int e;; b++) { + c[e] = c[b - count - 1]; + c[b - count - 1] = count; + count = count + 1; + } + __builtin_printf("", c); +} diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc index cc182f6fe36d..79f1639e1436 100644 --- a/gcc/tree-ssa-pre.cc +++ b/gcc/tree-ssa-pre.cc @@ -2171,22 +2171,38 @@ static void clean (bitmap_set_t set1, bitmap_set_t set2 = NULL) { vec<pre_expr> exprs = sorted_array_from_bitmap_set (set1, false); - pre_expr expr; - int i; + bool changed; - FOR_EACH_VEC_ELT (exprs, i, expr) + do { - if (!valid_in_sets (set1, set2, expr)) + unsigned j = 0; + changed = false; + for (unsigned i = 0; i < exprs.length (); ++i) { - unsigned int val = get_expr_value_id (expr); - bitmap_clear_bit (&set1->expressions, get_expression_id (expr)); - /* We are entered with possibly multiple expressions for a value - so before removing a value from the set see if there's an - expression for it left. */ - if (! bitmap_find_leader (set1, val)) - bitmap_clear_bit (&set1->values, val); + pre_expr expr = exprs[i]; + if (!valid_in_sets (set1, set2, expr)) + { + unsigned int val = get_expr_value_id (expr); + bitmap_clear_bit (&set1->expressions, get_expression_id (expr)); + /* We are entered with possibly multiple expressions for a value + so before removing a value from the set see if there's an + expression for it left. */ + if (! bitmap_find_leader (set1, val)) + { + bitmap_clear_bit (&set1->values, val); + changed = true; + } + } + else + { + exprs[j] = expr; + ++j; + } } + exprs.truncate (j); } + /* As the value graph can have cycles we have to iterate here. */ + while (changed); exprs.release (); if (flag_checking)
