diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h --- a/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -61,6 +61,7 @@ class FenceInst; class Function; class InvokeInst; +class LoopInfo; class PreservedAnalyses; class TargetLibraryInfo; class Value; @@ -378,6 +379,50 @@ return ModRefInfo(FMRB & static_cast(ModRefInfo::ModRef)); } +/// Virtual base class for providers of capture information. +struct CaptureInfo { + virtual ~CaptureInfo() = 0; + virtual bool isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) = 0; +}; + +/// Context-free CaptureInfo provider, which computes and caches whether an +/// object is captured in the function at all, but does not distinguish whether +/// it was captured before or after the context instruction. +class SimpleCaptureInfo final : public CaptureInfo { + SmallDenseMap IsCapturedCache; + +public: + bool isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) override; +}; + +/// Context-sensitive CaptureInfo provider, which computes and caches the +/// earliest common dominator closure of all captures. It provides a good +/// approximation to a precise "captures before" analysis. +class EarliestEscapeInfo final : public CaptureInfo { + DominatorTree &DT; + const LoopInfo &LI; + + /// Map from identified local object to an instruction before which it does + /// not escape, or nullptr if it never escapes. The "earliest" instruction + /// may be a conservative approximation, e.g. the first instruction in the + /// function is always a legal choice. + DenseMap EarliestEscapes; + + /// Reverse map from instruction to the objects it is the earliest escape for. + /// This is used for cache invalidation purposes. + DenseMap> Inst2Obj; + +public: + EarliestEscapeInfo(DominatorTree &DT, const LoopInfo &LI) : DT(DT), LI(LI) {} + + bool isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) override; + + void removeInstruction(Instruction *I); +}; + /// Reduced version of MemoryLocation that only stores a pointer and size. /// Used for caching AATags independent BasicAA results. struct AACacheLoc { @@ -425,8 +470,7 @@ using AliasCacheT = SmallDenseMap; AliasCacheT AliasCache; - using IsCapturedCacheT = SmallDenseMap; - IsCapturedCacheT IsCapturedCache; + CaptureInfo *CI; /// Query depth used to distinguish recursive queries. unsigned Depth = 0; @@ -439,18 +483,26 @@ /// assumption is disproven. SmallVector AssumptionBasedResults; - AAQueryInfo() : AliasCache(), IsCapturedCache() {} + AAQueryInfo(CaptureInfo *CI) : CI(CI) {} /// Create a new AAQueryInfo based on this one, but with the cache cleared. /// This is used for recursive queries across phis, where cache results may /// not be valid. AAQueryInfo withEmptyCache() { - AAQueryInfo NewAAQI; + AAQueryInfo NewAAQI(CI); NewAAQI.Depth = Depth; return NewAAQI; } }; +/// AAQueryInfo that uses SimpleCaptureInfo. +class SimpleAAQueryInfo : public AAQueryInfo { + SimpleCaptureInfo CI; + +public: + SimpleAAQueryInfo() : AAQueryInfo(&CI) {} +}; + class BatchAAResults; class AAResults { @@ -770,7 +822,7 @@ /// helpers above. ModRefInfo getModRefInfo(const Instruction *I, const Optional &OptLoc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(I, OptLoc, AAQIP); } @@ -797,7 +849,7 @@ ModRefInfo callCapturesBefore(const Instruction *I, const MemoryLocation &MemLoc, DominatorTree *DT) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return callCapturesBefore(I, MemLoc, DT, AAQIP); } @@ -896,9 +948,12 @@ class BatchAAResults { AAResults &AA; AAQueryInfo AAQI; + SimpleCaptureInfo SimpleCI; public: - BatchAAResults(AAResults &AAR) : AA(AAR), AAQI() {} + BatchAAResults(AAResults &AAR) : AA(AAR), AAQI(&SimpleCI) {} + BatchAAResults(AAResults &AAR, CaptureInfo *CI) : AA(AAR), AAQI(CI) {} + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { return AA.alias(LocA, LocB, AAQI); } diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -119,7 +119,7 @@ AliasResult AAResults::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return alias(LocA, LocB, AAQIP); } @@ -162,7 +162,7 @@ bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return pointsToConstantMemory(Loc, AAQIP, OrLocal); } @@ -190,7 +190,7 @@ } ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(I, Call2, AAQIP); } @@ -217,7 +217,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(Call, Loc, AAQIP); } @@ -284,7 +284,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call1, const CallBase *Call2) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(Call1, Call2, AAQIP); } @@ -474,7 +474,7 @@ ModRefInfo AAResults::getModRefInfo(const LoadInst *L, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(L, Loc, AAQIP); } ModRefInfo AAResults::getModRefInfo(const LoadInst *L, @@ -499,7 +499,7 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(S, Loc, AAQIP); } ModRefInfo AAResults::getModRefInfo(const StoreInst *S, @@ -531,7 +531,7 @@ } ModRefInfo AAResults::getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(S, Loc, AAQIP); } @@ -547,7 +547,7 @@ ModRefInfo AAResults::getModRefInfo(const VAArgInst *V, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(V, Loc, AAQIP); } @@ -577,7 +577,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CatchPad, Loc, AAQIP); } @@ -597,7 +597,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CatchRet, Loc, AAQIP); } @@ -617,7 +617,7 @@ ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(CX, Loc, AAQIP); } @@ -645,7 +645,7 @@ ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc) { - AAQueryInfo AAQIP; + SimpleAAQueryInfo AAQIP; return getModRefInfo(RMW, Loc, AAQIP); } diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -223,6 +223,51 @@ return ObjectSize != MemoryLocation::UnknownSize && ObjectSize == Size; } +//===----------------------------------------------------------------------===// +// CaptureInfo implementations +//===----------------------------------------------------------------------===// + +CaptureInfo::~CaptureInfo() = default; + +bool SimpleCaptureInfo::isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) { + return isNonEscapingLocalObject(Object, &IsCapturedCache); +} + +bool EarliestEscapeInfo::isNotCapturedBeforeOrAt(const Value *Object, + const Instruction *I) { + if (!isIdentifiedFunctionLocal(Object)) + return false; + + auto Iter = EarliestEscapes.insert({Object, nullptr}); + if (Iter.second) { + Instruction *EarliestCapture = FindEarliestCapture( + Object, *const_cast(I->getFunction()), + /*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT); + if (EarliestCapture) { + auto Ins = Inst2Obj.insert({EarliestCapture, {}}); + Ins.first->second.push_back(Object); + } + Iter.first->second = EarliestCapture; + } + + // No capturing instruction. + if (!Iter.first->second) + return true; + + return I != Iter.first->second && + !isPotentiallyReachable(Iter.first->second, I, nullptr, &DT, &LI); +} + +void EarliestEscapeInfo::removeInstruction(Instruction *I) { + auto Iter = Inst2Obj.find(I); + if (Iter != Inst2Obj.end()) { + for (const Value *Obj : Iter->second) + EarliestEscapes.erase(Obj); + Inst2Obj.erase(I); + } +} + //===----------------------------------------------------------------------===// // GetElementPtr Instruction Decomposition and Analysis //===----------------------------------------------------------------------===// @@ -835,7 +880,7 @@ // then the call can not mod/ref the pointer unless the call takes the pointer // as an argument, and itself doesn't capture it. if (!isa(Object) && Call != Object && - isNonEscapingLocalObject(Object, &AAQI.IsCapturedCache)) { + AAQI.CI->isNotCapturedBeforeOrAt(Object, Call)) { // Optimistically assume that call doesn't touch Object and check this // assumption in the following loop. @@ -1514,10 +1559,10 @@ // location if that memory location doesn't escape. Or it may pass a // nocapture value to other functions as long as they don't capture it. if (isEscapeSource(O1) && - isNonEscapingLocalObject(O2, &AAQI.IsCapturedCache)) + AAQI.CI->isNotCapturedBeforeOrAt(O2, cast(O1))) return AliasResult::NoAlias; if (isEscapeSource(O2) && - isNonEscapingLocalObject(O1, &AAQI.IsCapturedCache)) + AAQI.CI->isNotCapturedBeforeOrAt(O1, cast(O2))) return AliasResult::NoAlias; } diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -38,7 +38,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CaptureTracking.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/LoopInfo.h" @@ -856,6 +855,7 @@ struct DSEState { Function &F; AliasAnalysis &AA; + EarliestEscapeInfo EI; /// The single BatchAA instance that is used to cache AA queries. It will /// not be invalidated over the whole run. This is safe, because: @@ -898,14 +898,11 @@ /// basic block. DenseMap IOLs; - DenseMap EarliestEscapes; - DenseMap> Inst2Obj; - DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, const TargetLibraryInfo &TLI, const LoopInfo &LI) - : F(F), AA(AA), BatchAA(AA), MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI), - DL(F.getParent()->getDataLayout()), LI(LI) {} + : F(F), AA(AA), EI(DT, LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT), + PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {} static DSEState get(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, @@ -1268,30 +1265,6 @@ DepWriteOffset) == OW_Complete; } - /// Returns true if \p Object is not captured before or by \p I. - bool notCapturedBeforeOrAt(const Value *Object, Instruction *I) { - if (!isIdentifiedFunctionLocal(Object)) - return false; - - auto Iter = EarliestEscapes.insert({Object, nullptr}); - if (Iter.second) { - Instruction *EarliestCapture = FindEarliestCapture( - Object, F, /*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT); - if (EarliestCapture) { - auto Ins = Inst2Obj.insert({EarliestCapture, {}}); - Ins.first->second.push_back(Object); - } - Iter.first->second = EarliestCapture; - } - - // No capturing instruction. - if (!Iter.first->second) - return true; - - return I != Iter.first->second && - !isPotentiallyReachable(Iter.first->second, I, nullptr, &DT, &LI); - } - // Returns true if \p Use may read from \p DefLoc. bool isReadClobber(const MemoryLocation &DefLoc, Instruction *UseInst) { if (isNoopIntrinsic(UseInst)) @@ -1309,25 +1282,6 @@ if (CB->onlyAccessesInaccessibleMemory()) return false; - // BasicAA does not spend linear time to check whether local objects escape - // before potentially aliasing accesses. To improve DSE results, compute and - // cache escape info for local objects in certain circumstances. - if (auto *LI = dyn_cast(UseInst)) { - // If the loads reads from a loaded underlying object accesses the load - // cannot alias DefLoc, if DefUO is a local object that has not escaped - // before the load. - auto *ReadUO = getUnderlyingObject(LI->getPointerOperand()); - auto *DefUO = getUnderlyingObject(DefLoc.Ptr); - auto *ReadLI = dyn_cast(ReadUO); - if (ReadLI && notCapturedBeforeOrAt(DefUO, ReadLI)) { - assert( - !PointerMayBeCapturedBefore(DefLoc.Ptr, false, true, ReadLI, &DT, - false, 0, &this->LI) && - "cached analysis disagrees with fresh PointerMayBeCapturedBefore"); - return false; - } - } - // NOTE: For calls, the number of stores removed could be slightly improved // by using AA.callCapturesBefore(UseInst, DefLoc, &DT), but that showed to // be expensive compared to the benefits in practice. For now, avoid more @@ -1769,14 +1723,7 @@ NowDeadInsts.push_back(OpI); } - // Clear any cached escape info for objects associated with the - // removed instructions. - auto Iter = Inst2Obj.find(DeadInst); - if (Iter != Inst2Obj.end()) { - for (const Value *Obj : Iter->second) - EarliestEscapes.erase(Obj); - Inst2Obj.erase(DeadInst); - } + EI.removeInstruction(DeadInst); DeadInst->eraseFromParent(); } } diff --git a/llvm/test/Transforms/DeadStoreElimination/captures-before-call.ll b/llvm/test/Transforms/DeadStoreElimination/captures-before-call.ll --- a/llvm/test/Transforms/DeadStoreElimination/captures-before-call.ll +++ b/llvm/test/Transforms/DeadStoreElimination/captures-before-call.ll @@ -11,7 +11,6 @@ ; CHECK-NEXT: [[V2:%.*]] = alloca i32, align 4 ; CHECK-NEXT: store i32 0, i32* [[V1]], align 4 ; CHECK-NEXT: call void @escape(i32* nonnull [[V1]]) -; CHECK-NEXT: store i32 55555, i32* [[V2]], align 4 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 [[CALL]], i32* [[V2]], align 4 ; CHECK-NEXT: call void @escape(i32* nonnull [[V2]]) @@ -46,7 +45,6 @@ define i32 @test_not_captured_before_call_same_bb() { ; CHECK-LABEL: @test_not_captured_before_call_same_bb( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: call void @escape_and_clobber(i32* [[A]]) @@ -63,7 +61,6 @@ define i32 @test_not_captured_before_call_same_bb_escape_unreachable_block() { ; CHECK-LABEL: @test_not_captured_before_call_same_bb_escape_unreachable_block( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: call void @escape_and_clobber(i32* [[A]]) @@ -106,7 +103,6 @@ define i32 @test_captured_after_call_same_bb_2_clobbered_later() { ; CHECK-LABEL: @test_captured_after_call_same_bb_2_clobbered_later( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: call void @escape_writeonly(i32* [[A]]) ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 @@ -125,7 +121,6 @@ define i32 @test_captured_sibling_path_to_call_other_blocks_1(i1 %c.1) { ; CHECK-LABEL: @test_captured_sibling_path_to_call_other_blocks_1( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: call void @escape_writeonly(i32* [[A]]) @@ -296,7 +291,6 @@ define i32 @test_not_captured_before_call_other_blocks_1(i1 %c.1) { ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_1( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] @@ -328,7 +322,6 @@ define i32 @test_not_captured_before_call_other_blocks_2(i1 %c.1) { ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_2( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] @@ -362,7 +355,6 @@ define i32 @test_not_captured_before_call_other_blocks_3(i1 %c.1) { ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_3( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] @@ -394,7 +386,6 @@ define i32 @test_not_captured_before_call_other_blocks_4(i1 %c.1) { ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_4( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: br label [[EXIT:%.*]] @@ -431,7 +422,6 @@ ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_5( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() @@ -499,7 +489,6 @@ ; CHECK-LABEL: @test_not_captured_before_call_other_blocks_7( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() ; CHECK-NEXT: call void @escape_writeonly(i32* [[A]]) ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] @@ -554,7 +543,6 @@ define i32 @test_captured_after_loop(i1 %c.1) { ; CHECK-LABEL: @test_captured_after_loop( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[R:%.*]] = call i32 @getval() @@ -613,7 +601,6 @@ ; CHECK-NEXT: bb: ; CHECK-NEXT: [[A:%.*]] = alloca i64, align 8 ; CHECK-NEXT: [[EXT_A:%.*]] = bitcast i64* [[A]] to i8* -; CHECK-NEXT: store i64 0, i64* [[A]], align 8 ; CHECK-NEXT: call void @clobber() ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXT_A]], i8* [[SRC:%.*]], i64 8, i1 false) ; CHECK-NEXT: store i64* [[A]], i64** [[ESCAPE:%.*]], align 8 @@ -641,7 +628,6 @@ ; CHECK-LABEL: @test_invoke_captures( ; CHECK-NEXT: bb: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: invoke void @clobber() ; CHECK-NEXT: to label [[BB2:%.*]] unwind label [[BB5:%.*]] ; CHECK: bb2: @@ -695,7 +681,6 @@ define i32 @test_not_captured_before_load_same_bb_noalias_call() { ; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_call( ; CHECK-NEXT: [[A:%.*]] = call i32* @alloc() -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval_nounwind() ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: call void @escape_and_clobber(i32* [[A]]) @@ -711,9 +696,8 @@ define i32 @test_not_captured_before_load_same_bb_noalias_arg(i32* noalias %a) { ; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_arg( -; CHECK-NEXT: store i32 55, i32* [[A:%.*]], align 4 ; CHECK-NEXT: [[R:%.*]] = call i32 @getval_nounwind() -; CHECK-NEXT: store i32 99, i32* [[A]], align 4 +; CHECK-NEXT: store i32 99, i32* [[A:%.*]], align 4 ; CHECK-NEXT: call void @escape_and_clobber(i32* [[A]]) ; CHECK-NEXT: ret i32 [[R]] ; diff --git a/llvm/test/Transforms/DeadStoreElimination/captures-before-load.ll b/llvm/test/Transforms/DeadStoreElimination/captures-before-load.ll --- a/llvm/test/Transforms/DeadStoreElimination/captures-before-load.ll +++ b/llvm/test/Transforms/DeadStoreElimination/captures-before-load.ll @@ -154,7 +154,6 @@ define i32 @test_not_captured_before_load_same_bb_clobber(i32** %in.ptr) { ; CHECK-LABEL: @test_not_captured_before_load_same_bb_clobber( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: call void @clobber() ; CHECK-NEXT: [[IN_LV_1:%.*]] = load i32*, i32** [[IN_PTR:%.*]], align 2 ; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, i32* [[IN_LV_1]], align 2 @@ -242,7 +241,6 @@ ; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, i32* [[IN_LV_1]], align 2 ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: store i32 99, i32* [[A]], align 4 ; CHECK-NEXT: call void @clobber() ; CHECK-NEXT: ret i32 [[IN_LV_2]] ; @@ -1124,7 +1122,6 @@ define i32 @test_not_captured_before_load_of_ptrtoint(i64 %in) { ; CHECK-LABEL: @test_not_captured_before_load_of_ptrtoint( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[IN_PTR:%.*]] = inttoptr i64 [[IN:%.*]] to i32* ; CHECK-NEXT: [[IN_PTR_LOAD:%.*]] = load i32, i32* [[IN_PTR]], align 4 ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 @@ -1145,7 +1142,6 @@ define i32 @test_not_captured_before_load_of_call() { ; CHECK-LABEL: @test_not_captured_before_load_of_call( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 55, i32* [[A]], align 4 ; CHECK-NEXT: [[IN_PTR:%.*]] = call i32* @getptr() #[[ATTR4:[0-9]+]] ; CHECK-NEXT: [[IN_PTR_LOAD:%.*]] = load i32, i32* [[IN_PTR]], align 4 ; CHECK-NEXT: store i32 99, i32* [[A]], align 4 @@ -1166,7 +1162,6 @@ ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[O:%.*]] = select i1 [[C:%.*]], i32* [[A]], i32* [[B]] -; CHECK-NEXT: store i32 55, i32* [[O]], align 4 ; CHECK-NEXT: [[IN_LV_1:%.*]] = load i32*, i32** [[IN_PTR:%.*]], align 2 ; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, i32* [[IN_LV_1]], align 2 ; CHECK-NEXT: store i32 99, i32* [[O]], align 4 diff --git a/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp b/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp --- a/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp +++ b/llvm/unittests/Analysis/BasicAliasAnalysisTest.cpp @@ -46,7 +46,7 @@ DominatorTree DT; AssumptionCache AC; BasicAAResult BAA; - AAQueryInfo AAQI; + SimpleAAQueryInfo AAQI; TestAnalyses(BasicAATest &Test) : DT(*Test.F), AC(*Test.F), BAA(Test.DL, *Test.F, Test.TLI, AC, &DT),