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.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        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 | 32 ++++++++++++++++++++++++
 gcc/tree-ssa-phiopt.cc                   | 23 ++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cselim-4.c

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 00000000000..2e1121a834a
--- /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 167b86b3acc..fcf44136d0a 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));
     }
 
-- 
2.51.0

Reply via email to