This fixes a missed dead store elimination case.  We were not
properly disregarding a loop PHI use we have already visited.

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

Richard.

2012-07-04  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/53844
        * tree-ssa-dse.c (dse_possible_dead_store_p): Properly handle
        the loop virtual PHI.

        * g++.dg/tree-ssa/pr53844.C: New testcase.

Index: gcc/tree-ssa-dse.c
===================================================================
--- gcc/tree-ssa-dse.c  (revision 189248)
+++ gcc/tree-ssa-dse.c  (working copy)
@@ -94,7 +94,7 @@ dse_possible_dead_store_p (gimple stmt,
   temp = stmt;
   do
     {
-      gimple use_stmt;
+      gimple use_stmt, defvar_def;
       imm_use_iterator ui;
       bool fail = false;
       tree defvar;
@@ -108,6 +108,7 @@ dse_possible_dead_store_p (gimple stmt,
        defvar = PHI_RESULT (temp);
       else
        defvar = gimple_vdef (temp);
+      defvar_def = temp;
       temp = NULL;
       FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
        {
@@ -139,7 +140,14 @@ dse_possible_dead_store_p (gimple stmt,
                  fail = true;
                  BREAK_FROM_IMM_USE_STMT (ui);
                }
-             temp = use_stmt;
+             /* Do not consider the PHI as use if it dominates the 
+                stmt defining the virtual operand we are processing,
+                we have processed it already in this case.  */
+             if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
+                 && !dominated_by_p (CDI_DOMINATORS,
+                                     gimple_bb (defvar_def),
+                                     gimple_bb (use_stmt)))
+               temp = use_stmt;
            }
          /* If the statement is a use the store is not dead.  */
          else if (ref_maybe_used_by_stmt_p (use_stmt,
Index: gcc/testsuite/g++.dg/tree-ssa/pr53844.C
===================================================================
--- gcc/testsuite/g++.dg/tree-ssa/pr53844.C     (revision 0)
+++ gcc/testsuite/g++.dg/tree-ssa/pr53844.C     (working copy)
@@ -0,0 +1,78 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized-vops" }
+
+struct VBase;
+
+//Very minimal numeric vector class where Base provides the policy
+template<typename Base=VBase>
+struct Vector : public Base{
+       
+       inline Vector(const Base& b)
+       :Base(b)
+       {
+       }
+
+       //Assignment from any other sort of Vector
+       template<typename Base2>
+       void operator= (const Vector<Base2>& from)
+       {
+               for(int i=0; i<100; i++){
+                       (*this)[i]=from[i];
+               }
+       }
+};
+
+
+//Base class to represent pointer as a Vector
+struct VBase{
+       double * const my_data;
+
+       double& operator[](int i) {
+               return my_data[i];
+       }
+
+       const double& operator[](int i) const {
+               return my_data[i];
+       }
+};
+
+//Base class providing very minimalistic expression template
+template<class B2> struct ScalarMulExpr
+{
+       const int& mul;
+       const Vector<B2>& vec;
+
+       int size() const
+       {
+               return vec.size();
+       }
+
+       double operator[](int i) const
+       {
+               return vec[i]*mul;
+       }
+
+       ScalarMulExpr(const Vector<B2>& vec_, const int& m)
+       :mul(m),vec(vec_)
+       {
+       }
+};
+
+//Allow vector to be multiplied by a scalar
+template<class B2>
+Vector<ScalarMulExpr<B2> > operator*(const Vector<B2>& lhs, const int& rhs)
+{
+       return ScalarMulExpr<B2>(lhs, rhs);
+}
+
+//Test function producing suboptimal asm code
+void test(const Vector<>& in, Vector<>& out, int i)
+{
+       out=in*1*1*1*1*1*1*1*1*1*1*1;
+}
+
+// There should be a single store remaining, inside the loops.  All
+// dead stores to unused temporaries should have been removed.
+
+// { dg-final { scan-tree-dump-times "VDEF" 1 "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }

Reply via email to