https://gcc.gnu.org/g:312ba8d740bb4302a038e11c45891addf0c7e9f9

commit r16-7135-g312ba8d740bb4302a038e11c45891addf0c7e9f9
Author: Richard Biener <[email protected]>
Date:   Thu Jan 29 08:47:44 2026 +0100

    tree-optimization/116747 - ICE in cselim due to duplicate sinking
    
    The following avoids queueing duplicate stmts in the set of sinkings
    to consider as well as pick candidates in an order that ensures
    we don't unnecessarily re-order stores.  While we currently only can
    trigger the ICE with out-of-bound accesses future enhancements
    to how we deal with dependence analysis in this pass could expose
    the issue to a wider range of testcases, so this makes it future-proof.
    
            PR tree-optimization/116747
            * tree-ssa-phiopt.cc (cond_if_else_store_replacement): Avoid
            duplicate stmts in the set of store pairs to process.
    
            * gcc.dg/tree-ssa/cselim-4.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c | 32 ++++++++++++++++++++++++++++++++
 gcc/tree-ssa-phiopt.cc                   | 23 ++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c 
b/gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c
new file mode 100644
index 000000000000..2e1121a834a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-expensive-optimizations -fno-tree-dse -fgimple" } */
+
+/* We're testing the CSELIM pass but we need VRP to compute the range
+   for b_4 to make the array1[] accesses out-of-bound.  */
+
+int array1[1];
+int __GIMPLE (ssa,startwith("vrp"),guessed_local(1073741824))
+f1 (int a, short unsigned int b1, int c)
+{
+  int b;
+
+  __BB(2,guessed_local(1073741824)):
+  b_3 = (int) b1_2(D);
+  b_4 = b_3 + 1;
+  if (a_5(D) != 0)
+    goto __BB3(guessed(67108864));
+  else
+    goto __BB4(guessed(67108864));
+
+  __BB(3,guessed_local(536870912)):
+  array1[b_4] = c_7(D);
+  array1[b_4] = c_7(D);
+  goto __BB5(precise(134217728));
+
+  __BB(4,guessed_local(536870912)):
+  array1[b_4] = c_7(D);
+  goto __BB5(precise(134217728));
+
+  __BB(5,guessed_local(1073741824)):
+  return;
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 167b86b3accb..fcf44136d0a4 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -3349,9 +3349,21 @@ cond_if_else_store_replacement (basic_block then_bb, 
basic_block else_bb,
       return false;
     }
 
-  /* Find pairs of stores with equal LHS.  */
+  /* Clear visited on else stores, we want to make sure to pick each store
+     at most once to avoid quadratic behavior.  */
+  for (auto else_dr : else_datarefs)
+    {
+      if (DR_IS_READ (else_dr))
+       continue;
+      gimple_set_visited (DR_STMT (else_dr), false);
+    }
+
+  /* Find pairs of stores with equal LHS.  Work from the end to avoid
+     re-ordering stores unnecessarily.  */
   auto_vec<std::pair<gimple *, gimple *>, 1> stores_pairs;
-  for (auto then_dr : then_datarefs)
+  unsigned i;
+  data_reference_p then_dr;
+  FOR_EACH_VEC_ELT_REVERSE (then_datarefs, i, then_dr)
     {
       if (DR_IS_READ (then_dr))
         continue;
@@ -3362,12 +3374,16 @@ cond_if_else_store_replacement (basic_block then_bb, 
basic_block else_bb,
        continue;
       found = false;
 
-      for (auto else_dr : else_datarefs)
+      unsigned j;
+      data_reference_p else_dr;
+      FOR_EACH_VEC_ELT_REVERSE (else_datarefs, j, else_dr)
         {
           if (DR_IS_READ (else_dr))
             continue;
 
           else_store = DR_STMT (else_dr);
+         if (gimple_visited_p (else_store))
+           continue;
           else_lhs = gimple_get_lhs (else_store);
          if (else_lhs == NULL_TREE)
            continue;
@@ -3382,6 +3398,7 @@ cond_if_else_store_replacement (basic_block then_bb, 
basic_block else_bb,
       if (!found)
         continue;
 
+      gimple_set_visited (else_store, true);
       stores_pairs.safe_push (std::make_pair (then_store, else_store));
     }

Reply via email to