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

Reply via email to