]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/125040 - iterate PRE clean
authorRichard Biener <rguenther@suse.de>
Fri, 26 Jun 2026 14:28:52 +0000 (16:28 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 1 Jul 2026 10:19:00 +0000 (12:19 +0200)
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.

gcc/testsuite/gcc.dg/torture/pr125040.c [new file with mode: 0644]
gcc/tree-ssa-pre.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr125040.c b/gcc/testsuite/gcc.dg/torture/pr125040.c
new file mode 100644 (file)
index 0000000..be73208
--- /dev/null
@@ -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);
+}
index cc182f6fe36db6b236e1f6f5d5aaf57ad6ef77a2..79f1639e143661857e85092e1b55d734978d8b81 100644 (file)
@@ -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)