diff options
-rw-r--r-- | include/llvm/Analysis/ValueTracking.h | 8 | ||||
-rw-r--r-- | lib/Analysis/ValueTracking.cpp | 31 | ||||
-rw-r--r-- | lib/Transforms/Scalar/DeadStoreElimination.cpp | 22 | ||||
-rw-r--r-- | test/Transforms/DeadStoreElimination/simple.ll | 10 |
4 files changed, 68 insertions, 3 deletions
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index f2f9db4..e8d45f6 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -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); diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 1418e01..d245783 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -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. /// diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index a46e802..f498cc7 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -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); diff --git a/test/Transforms/DeadStoreElimination/simple.ll b/test/Transforms/DeadStoreElimination/simple.ll index 7c8a9b3..a386206 100644 --- a/test/Transforms/DeadStoreElimination/simple.ll +++ b/test/Transforms/DeadStoreElimination/simple.ll @@ -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 +} |