[gcc r16-9265] tree-optimization/125040 - iterate PRE clean

Richard Biener via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:c61050d76cbbbd1f18536e91095a420c8f52d380

commit r16-9265-gc61050d76cbbbd1f18536e91095a420c8f52d380
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.
    
    (cherry picked from commit b052d6bbbeea2b04c8a4f765e89b0b3f19f81764)

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 0e5eaf86bc7e..b3a3d1de0dd5 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -2140,22 +2140,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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.