Index: osprey/be/opt/opt_dse.cxx
===================================================================
--- osprey/be/opt/opt_dse.cxx	(revision 3698)
+++ osprey/be/opt/opt_dse.cxx	(working copy)
@@ -91,7 +91,24 @@
 using std::vector;
 #include "opt_alias_rule.h"
 #include "idx_32_set.h"
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+# include <ext/hash_set>
+using __gnu_cxx::hash_set;
+#else
+# include <set>
+#endif
 
+typedef struct
+{
+  size_t operator() (const VER_STAB_ENTRY *k) const { return (size_t)k; }
+} hash_VSE;
+typedef struct
+{
+   bool operator() (const VER_STAB_ENTRY *k1, const VER_STAB_ENTRY *k2) const { return k1 == k2; }
+} equal_VSE;
+
+typedef hash_set<VER_STAB_ENTRY*, hash_VSE, equal_VSE> VSE_SET;
+
 // ====================================================================
 // ====================================================================
 
@@ -110,6 +127,7 @@
 #endif
     vector <WN *> *_last_store_vec;
     vector <IDX_32_SET *> * _alias_aux_vec;
+    VSE_SET* _vse_requried_set;
 
     //
     // access methods
@@ -174,6 +192,10 @@
     void Propagate_vsym_wn( WN *wn ) const;
     void Propagate_vsym_bb( BB_NODE *bb ) const;
 
+    // required info untiliy.
+    BOOL VSE_required(VER_STAB_ENTRY* vse) const;
+    void Set_VSE_required(VER_STAB_ENTRY* vse) const {_vse_requried_set->insert(vse);}
+
   public:
 
     DSE( CFG *cfg, OPT_STAB *opt_stab, MEM_POOL *pool, EXC *exc, BOOL tracing )
@@ -207,6 +229,9 @@
             }
           }
         }       
+
+        // allocate_vse_requried_set
+        _vse_requried_set = CXX_NEW(VSE_SET, pool);
       }
 
     ~DSE( void )
@@ -446,6 +471,9 @@
   // we only need to propagate this usage if the symbol
   // was not already marked as having a use
   if ( vse->Any_use() ) return;
+
+  // mark this vse is requried from some path.
+  Set_VSE_required(vse);
   
   BOOL vse_live=TRUE;
   // now recursively follow this symbol's use-def chain
@@ -520,21 +548,7 @@
 DSE::Set_Required_MU( MU_NODE *mu, BOOL real_use ) const
 {
   VER_STAB_ENTRY *ver = Opt_stab()->Ver_stab_entry(mu->Opnd());
-  Set_last_store(ver->Aux_id(), NULL);
-
-  // there may be implied mu-nodes, so that we need to traverse the alias set 
-  const BS      *alias_set = Opt_stab()->Rule()->Alias_Set_Indirect( Opt_stab());
-  for (AUX_ID idx = BS_Choose( alias_set );
-    idx != (AUX_ID) BS_CHOOSE_FAILURE;
-    idx = BS_Choose_Next ( alias_set, idx )) {
-  
-    // Volatile do not appear in any mu and chi
-    if (!Opt_stab()->Aux_stab_entry(idx)->Is_volatile() ||
-      Opt_stab()->Aux_stab_entry(idx)->Is_virtual() ){
-      Set_last_store(idx, NULL);
-    }
-  }
-  
+  Set_last_store(ver->Aux_id(), NULL);  
   Set_Required_VSE( ver, real_use, NULL );
 }
 
@@ -694,6 +708,27 @@
       	}
       }
     }
+
+    // if chi node is not live, due to same location.
+    // check if it aliased with any live chi node.
+    if(!*chi_is_live) {
+      CHI_LIST_ITER chi_iter;
+      CHI_NODE *cnode;
+      FOR_ALL_NODE( cnode, chi_iter, Init(Opt_stab()->Get_generic_chi_list(chiwn))) {
+        if (cnode->Aux_id() == vaux) continue;
+
+        // skip non-live chi node
+        VER_STAB_ENTRY *vsym = Opt_stab()->Ver_stab_entry(cnode->Result());
+        if (!vsym->Any_use()) continue;
+        
+        if (_opt_stab->Rule()->Aliased_Memop(_opt_stab->Aux_stab_entry(vaux)->Points_to(),
+                       _opt_stab->Aux_stab_entry(cnode->Aux_id())->Points_to())) {
+          *chi_is_live = TRUE;
+          break;
+        }
+      }
+    }
+    
     if(*chi_is_live)
       Set_last_store(vaux, chiwn);
   } 
@@ -723,6 +758,31 @@
 
   VER_STAB_ENTRY *opnd_ver = Opt_stab()->Ver_stab_entry(chi->Opnd());
   Set_Required_VSE( opnd_ver, real_use, NULL );
+
+  if (*chi_is_live) {
+    // mark all aliased chi nodes be live
+    CHI_LIST_ITER chi_iter;
+    CHI_NODE *cnode;
+    FOR_ALL_NODE( cnode, chi_iter, Init(Opt_stab()->Get_generic_chi_list(chiwn))) {
+      if (cnode->Aux_id() == vaux) continue;
+
+      // skip already live chi node
+      VER_STAB_ENTRY *vsym = Opt_stab()->Ver_stab_entry(cnode->Result());
+      if (vsym->Any_use()) continue;
+
+      // skip non-required chi node
+      if (!VSE_required(vsym)) continue;
+
+      // skip non-aliased chi node
+      if (!_opt_stab->Rule()->Aliased_Memop(_opt_stab->Aux_stab_entry(vaux)->Points_to(),
+                       _opt_stab->Aux_stab_entry(cnode->Aux_id())->Points_to())) {
+        continue;
+      }
+      // force cnode live.
+      Set_last_store(cnode->Aux_id(), NULL);
+      Set_Required_VSE( vsym, FALSE, NULL );
+    }
+  }
 }
 // ====================================================================
 // Recursively set the flags that say the variables it references
@@ -1068,6 +1128,19 @@
 
 #endif
 
+/* return true if vse is called by set_required_vse
+ */
+BOOL 
+DSE::VSE_required(VER_STAB_ENTRY* vse) const
+{
+  VSE_SET::iterator iter;
+  iter = _vse_requried_set->find(vse);
+  if (iter != _vse_requried_set->end()) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
 // ====================================================================
 // Driver for the dead-store elimination phase
 // ====================================================================
