From f6f1f062cc8029aa75ca7d0e99fbc1e0b453d07e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 21 Nov 2010 07:34:32 +0000 Subject: [PATCH] implement PR8576, deleting dead stores with intervening may-alias stores. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119927 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/Analysis/MemoryDependenceAnalysis.h | 10 +++++++- lib/Analysis/MemoryDependenceAnalysis.cpp | 4 +-- .../Scalar/DeadStoreElimination.cpp | 25 ++++++++++++++++--- .../Transforms/DeadStoreElimination/simple.ll | 9 +++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index cc34992b456..c9c8116dc51 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -335,11 +335,19 @@ namespace llvm { /// critical edges. void invalidateCachedPredecessors(); - private: + /// getPointerDependencyFrom - Return the instruction on which a memory + /// location depends. If isLoad is true, this routine ignores may-aliases + /// with read-only operations. If isLoad is false, this routine ignores + /// may-aliases with reads from read-only locations. + /// + /// Note that this is an uncached query, and thus may be inefficient. + /// MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB); + + private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index a16e334e020..5fdf9a9c1a7 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -409,9 +409,9 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { if (MemLoc.Ptr) { // If we can do a pointer scan, make it happen. bool isLoad = !(MR & AliasAnalysis::Mod); - if (IntrinsicInst *II = dyn_cast(QueryInst)) { + if (IntrinsicInst *II = dyn_cast(QueryInst)) isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_end; - } + LocalCache = getPointerDependencyFrom(MemLoc, isLoad, ScanPos, QueryParent); } else if (isa(QueryInst) || isa(QueryInst)) { diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index 1ea0b15e4c9..02df1031e60 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -217,9 +217,28 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) { continue; } - // If not a definite must-alias dependency, ignore it. - if (!InstDep.isDef()) - continue; + if (!InstDep.isDef()) { + // If this is a may-aliased store that is clobbering the store value, we + // can keep searching past it for another must-aliased pointer that stores + // to the same location. For example, in: + // store -> P + // store -> Q + // store -> P + // we can remove the first store to P even though we don't know if P and Q + // alias. + if (StoreInst *SI = dyn_cast(Inst)) { + AliasAnalysis::Location Loc = + getAnalysis().getLocation(SI); + while (InstDep.isClobber() && isa(InstDep.getInst()) && + InstDep.getInst() != &BB.front()) + InstDep = MD.getPointerDependencyFrom(Loc, false, InstDep.getInst(), + &BB); + } + + // If not a definite must-alias dependency, ignore it. + if (!InstDep.isDef()) + continue; + } // If this is a store-store dependence, then the previous store is dead so // long as this store is at least as big as it. diff --git a/test/Transforms/DeadStoreElimination/simple.ll b/test/Transforms/DeadStoreElimination/simple.ll index f0c140d50a3..0a16603f55d 100644 --- a/test/Transforms/DeadStoreElimination/simple.ll +++ b/test/Transforms/DeadStoreElimination/simple.ll @@ -11,3 +11,12 @@ define void @test1(i32* %Q, i32* %P) { ; CHECK-NEXT: ret void } +; PR8576 - Should delete store of 10 even though p/q are may aliases. +define void @test2(i32 *%p, i32 *%q) { + store i32 10, i32* %p, align 4 + store i32 20, i32* %q, align 4 + store i32 30, i32* %p, align 4 + ret void +; CHECK: @test2 +; CHECK-NEXT: store i32 20 +}