https://gcc.gnu.org/g:0f8c6f479e65af985d4d374cc9b3405327124d66

commit r16-4180-g0f8c6f479e65af985d4d374cc9b3405327124d66
Author: Richard Biener <[email protected]>
Date:   Wed Oct 1 14:55:17 2025 +0200

    tree-optimization/122079 - PRE antic compute doesn't converge
    
    The following re-instantiates the pruning of the ANTIC_IN value set
    by the previous iterations one by reverting part of
    r16-3945-gc30f58c3f7ec25.  The earlier fixes made sure the initial
    value set is appropriately big to not cause this to lose optimizations.
    But it seems to be still required for correctness given iteration
    order means we combine ANTIC_IN sets from different generations which
    can be prone to oscillations in CFG cycles.
    
            PR tree-optimization/122079
            * tree-ssa-pre.cc (compute_antic_aux): Re-instantiate
            ANTIC_IN value pruning by the old solution.
    
            * gcc.dg/torture/pr122079-2.c: New testcase.
            * gcc.dg/torture/pr122079-3.c: Likewise.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr122079-2.c | 27 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr122079-3.c | 27 +++++++++++++++++++++++++++
 gcc/tree-ssa-pre.cc                       | 27 +++++++++++++++++++++++++++
 3 files changed, 81 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-2.c 
b/gcc/testsuite/gcc.dg/torture/pr122079-2.c
new file mode 100644
index 000000000000..40c36b0fefff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122079-2.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+int a, b, *c = &a, d, e, f;
+void g(int *p) { a = p[0]; }
+int main() {
+  int h = 0;
+i:
+  d = c[0];
+  c[0] = h;
+  if (a)
+    goto j;
+k:
+  h = c[0] - 1;
+  while (1) {
+    if (b)
+      goto i;
+    if (f)
+      goto k;
+  j:
+    if (!e) {
+      int m[] = {c[0]};
+      g(m);
+      break;
+    }
+  }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-3.c 
b/gcc/testsuite/gcc.dg/torture/pr122079-3.c
new file mode 100644
index 000000000000..df95c7181997
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122079-3.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-loop-im" } */
+
+int a, b, c;
+void d(int[]);
+void e(int f[][2]) {
+g:
+  b = f[0][1];
+  if (c)
+    goto h;
+i:
+  if (a)
+    goto g;
+  if (f[1][1])
+    goto j;
+h:
+  if (f[1][1])
+    goto i;
+  goto k;
+j:
+  b--;
+  if (b + f[0][1])
+    goto i;
+k:
+  int l[] = {f[0][1]};
+  d(l);
+}
diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
index d08caab952a1..2a7dcbee52ce 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -2084,6 +2084,7 @@ compute_antic_aux (basic_block block, bool 
block_has_abnormal_pred_edge)
   edge e;
   edge_iterator ei;
 
+  bool was_visited = BB_VISITED (block);
   bool changed = ! BB_VISITED (block);
   bool any_max_on_edge = false;
 
@@ -2219,6 +2220,32 @@ compute_antic_aux (basic_block block, bool 
block_has_abnormal_pred_edge)
   /* clean (ANTIC_IN (block)) is defered to after the iteration converged
      because it can cause non-convergence, see for example PR81181.  */
 
+  if (was_visited
+      && bitmap_and_into (&ANTIC_IN (block)->values, &old->values))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "warning: intersecting with old ANTIC_IN "
+                "shrinks the set\n");
+      /* Prune expressions not in the value set.  */
+      bitmap_iterator bi;
+      unsigned int i;
+      unsigned int to_clear = -1U;
+      FOR_EACH_EXPR_ID_IN_SET (ANTIC_IN (block), i, bi)
+       {
+         if (to_clear != -1U)
+           {
+             bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear);
+             to_clear = -1U;
+           }
+         pre_expr expr = expression_for_id (i);
+         unsigned int value_id = get_expr_value_id (expr);
+         if (!bitmap_bit_p (&ANTIC_IN (block)->values, value_id))
+           to_clear = i;
+       }
+      if (to_clear != -1U)
+       bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear);
+    }
+
   if (!bitmap_set_equal (old, ANTIC_IN (block)))
     changed = true;

Reply via email to