From b401e3bd16c3d648464606d5e5b496dd61d12afc Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 10 May 2012 18:57:38 +0000 Subject: [PATCH] Teach DeadStoreElimination to eliminate exit-block stores with phi addresses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156558 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ValueTracking.h | 8 +++++ lib/Analysis/ValueTracking.cpp | 31 +++++++++++++++++++ .../Scalar/DeadStoreElimination.cpp | 22 +++++++++++-- .../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 f2f9db4ce4e..e8d45f6bb8d 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -151,6 +151,14 @@ namespace llvm { return GetUnderlyingObject(const_cast(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 &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 1418e01d7c8..d245783ec65 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 &Objects, + const TargetData *TD, + unsigned MaxLookup) { + SmallPtrSet Visited; + SmallVector 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(P)) { + Worklist.push_back(SI->getTrueValue()); + Worklist.push_back(SI->getFalseValue()); + continue; + } + + if (PHINode *PN = dyn_cast(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 a46e802f4c2..f498cc79349 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 Pointers; + GetUnderlyingObjects(getStoredPointerOperand(BBI), Pointers); // Stores to stack values are valid candidates for removal. - if (DeadStackObjects.count(Pointer)) { + bool AllDead = true; + for (SmallVectorImpl::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::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 7c8a9b3337e..a38620695e7 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 +}