Teach DeadStoreElimination to eliminate exit-block stores with phi addresses.
authorDan Gohman <gohman@apple.com>
Thu, 10 May 2012 18:57:38 +0000 (18:57 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 10 May 2012 18:57:38 +0000 (18:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156558 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/ValueTracking.h
lib/Analysis/ValueTracking.cpp
lib/Transforms/Scalar/DeadStoreElimination.cpp
test/Transforms/DeadStoreElimination/simple.ll

index f2f9db4ce4e8c1dc00a322115fa54233b2ecfe04..e8d45f6bb8d43c3c61c00665a4a5ad6c43a87911 100644 (file)
@@ -151,6 +151,14 @@ namespace llvm {
     return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup);
   }
 
+  /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject
+  /// except that it can look through phi and select instructions and return
+  /// multiple objects.
+  void GetUnderlyingObjects(Value *V,
+                            SmallVectorImpl<Value *> &Objects,
+                            const TargetData *TD = 0,
+                            unsigned MaxLookup = 6);
+
   /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
   /// are lifetime markers.
   bool onlyUsedByLifetimeMarkers(const Value *V);
index 1418e01d7c814c4dd200a3481f559c11bb0bdd7d..d245783ec6529b75095eef4e166f844ee50c8626 100644 (file)
@@ -1796,6 +1796,37 @@ llvm::GetUnderlyingObject(Value *V, const TargetData *TD, unsigned MaxLookup) {
   return V;
 }
 
+void
+llvm::GetUnderlyingObjects(Value *V,
+                           SmallVectorImpl<Value *> &Objects,
+                           const TargetData *TD,
+                           unsigned MaxLookup) {
+  SmallPtrSet<Value *, 4> Visited;
+  SmallVector<Value *, 4> Worklist;
+  Worklist.push_back(V);
+  do {
+    Value *P = Worklist.pop_back_val();
+    P = GetUnderlyingObject(P, TD, MaxLookup);
+
+    if (!Visited.insert(P))
+      continue;
+
+    if (SelectInst *SI = dyn_cast<SelectInst>(P)) {
+      Worklist.push_back(SI->getTrueValue());
+      Worklist.push_back(SI->getFalseValue());
+      continue;
+    }
+
+    if (PHINode *PN = dyn_cast<PHINode>(P)) {
+      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+        Worklist.push_back(PN->getIncomingValue(i));
+      continue;
+    }
+
+    Objects.push_back(P);
+  } while (!Worklist.empty());
+}
+
 /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
 /// are lifetime markers.
 ///
index a46e802f4c2c03aa57291166022388f529c0d1d5..f498cc79349f733c8b9995eeca39629648d50f6c 100644 (file)
@@ -731,14 +731,30 @@ bool DSE::handleEndBlock(BasicBlock &BB) {
     // If we find a store, check to see if it points into a dead stack value.
     if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
       // See through pointer-to-pointer bitcasts
-      Value *Pointer = GetUnderlyingObject(getStoredPointerOperand(BBI));
+      SmallVector<Value *, 4> Pointers;
+      GetUnderlyingObjects(getStoredPointerOperand(BBI), Pointers);
 
       // Stores to stack values are valid candidates for removal.
-      if (DeadStackObjects.count(Pointer)) {
+      bool AllDead = true;
+      for (SmallVectorImpl<Value *>::iterator I = Pointers.begin(),
+           E = Pointers.end(); I != E; ++I)
+        if (!DeadStackObjects.count(*I)) {
+          AllDead = false;
+          break;
+        }
+
+      if (AllDead) {
         Instruction *Dead = BBI++;
 
         DEBUG(dbgs() << "DSE: Dead Store at End of Block:\n  DEAD: "
-                     << *Dead << "\n  Object: " << *Pointer << '\n');
+                     << *Dead << "\n  Objects: ";
+              for (SmallVectorImpl<Value *>::iterator I = Pointers.begin(),
+                   E = Pointers.end(); I != E; ++I) {
+                dbgs() << **I;
+                if (llvm::next(I) != E)
+                  dbgs() << ", ";
+              }
+              dbgs() << '\n');
 
         // DCE instructions only used to calculate that store.
         DeleteDeadInstruction(Dead, *MD, &DeadStackObjects);
index 7c8a9b3337ebb7cb6d4ea01c737871bcd26f8ee9..a38620695e71df3e271abbcb09d2c749fda37716 100644 (file)
@@ -266,3 +266,13 @@ define void @test21() {
 ; CHECK-NEXT: ret void
   ret void
 }
+
+; CHECK: @test22(
+define void @test22(i1 %i, i32 %k, i32 %m) nounwind {
+  %k.addr = alloca i32
+  %m.addr = alloca i32
+  %k.addr.m.addr = select i1 %i, i32* %k.addr, i32* %m.addr
+  store i32 0, i32* %k.addr.m.addr, align 4
+; CHECK-NEXT: ret void
+  ret void
+}