]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/116747 - ICE in cselim due to duplicate sinking
authorRichard Biener <rguenther@suse.de>
Thu, 29 Jan 2026 07:47:44 +0000 (08:47 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 29 Jan 2026 11:37:47 +0000 (12:37 +0100)
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.

gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c [new file with mode: 0644]
gcc/tree-ssa-phiopt.cc

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 (file)
index 0000000..2e1121a
--- /dev/null
@@ -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;
+}
index 167b86b3accb26559471e00f9435800b0ff055df..fcf44136d0a4f790069d1e8fab2c8afa0e309470 100644 (file)
@@ -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));
     }