The testcase has a cycle in the value graph of ANTIC_IN, this means
we have to iterate to correctly prune all invalid expressions.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/125040
* tree-ssa-pre.cc (clean): Iterate processing.
* gcc.dg/torture/pr125040.c: New testcase.
---
gcc/testsuite/gcc.dg/torture/pr125040.c | 14 +++++++++
gcc/tree-ssa-pre.cc | 38 ++++++++++++++++++-------
2 files changed, 41 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr125040.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr125040.c
b/gcc/testsuite/gcc.dg/torture/pr125040.c
new file mode 100644
index 00000000000..be732084cb0
--- /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 cc182f6fe36..79f1639e143 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)
--
2.51.0