diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/ValueTracking.h | 8 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 31 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp | 22 | ||||
| -rw-r--r-- | llvm/test/Transforms/DeadStoreElimination/simple.ll | 10 | 
4 files changed, 68 insertions, 3 deletions
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index f2f9db4ce4e..e8d45f6bb8d 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/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/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 1418e01d7c8..d245783ec65 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/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/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index a46e802f4c2..f498cc79349 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/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/llvm/test/Transforms/DeadStoreElimination/simple.ll b/llvm/test/Transforms/DeadStoreElimination/simple.ll index 7c8a9b3337e..a38620695e7 100644 --- a/llvm/test/Transforms/DeadStoreElimination/simple.ll +++ b/llvm/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 +}  | 

