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 @@ -185,12 +185,9 @@ /// This is used for cache invalidation purposes. DenseMap> Inst2Obj; - const SmallPtrSetImpl &EphValues; - public: - EarliestEscapeInfo(DominatorTree &DT, const LoopInfo &LI, - const SmallPtrSetImpl &EphValues) - : DT(DT), LI(LI), EphValues(EphValues) {} + EarliestEscapeInfo(DominatorTree &DT, const LoopInfo &LI) + : DT(DT), LI(LI) {} bool isNotCapturedBeforeOrAt(const Value *Object, const Instruction *I) override; diff --git a/llvm/include/llvm/Analysis/CaptureTracking.h b/llvm/include/llvm/Analysis/CaptureTracking.h --- a/llvm/include/llvm/Analysis/CaptureTracking.h +++ b/llvm/include/llvm/Analysis/CaptureTracking.h @@ -25,7 +25,6 @@ class DominatorTree; class LoopInfo; class Function; - template class SmallPtrSetImpl; /// getDefaultMaxUsesToExploreForCaptureTracking - Return default value of /// the maximal number of uses to explore before giving up. It is used by @@ -42,14 +41,8 @@ /// MaxUsesToExplore specifies how many uses the analysis should explore for /// one value before giving up due too "too many uses". If MaxUsesToExplore /// is zero, a default value is assumed. - bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, - bool StoreCaptures, unsigned MaxUsesToExplore = 0); - - /// Variant of the above function which accepts a set of Values that are - /// ephemeral and cannot cause pointers to escape. bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, - const SmallPtrSetImpl &EphValues, unsigned MaxUsesToExplore = 0); /// PointerMayBeCapturedBefore - Return true if this pointer value may be @@ -83,7 +76,6 @@ Instruction * FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures, bool StoreCaptures, const DominatorTree &DT, - const SmallPtrSetImpl &EphValues, unsigned MaxUsesToExplore = 0); /// This callback is used in conjunction with PointerMayBeCaptured. In 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 @@ -206,7 +206,7 @@ if (Iter.second) { Instruction *EarliestCapture = FindEarliestCapture( Object, *const_cast(I->getFunction()), - /*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT, EphValues); + /*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT); if (EarliestCapture) { auto Ins = Inst2Obj.insert({EarliestCapture, {}}); Ins.first->second.push_back(Object); diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -16,7 +16,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CaptureTracking.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -75,10 +74,8 @@ namespace { struct SimpleCaptureTracker : public CaptureTracker { - explicit SimpleCaptureTracker( - - const SmallPtrSetImpl &EphValues, bool ReturnCaptures) - : EphValues(EphValues), ReturnCaptures(ReturnCaptures) {} + explicit SimpleCaptureTracker(bool ReturnCaptures) + : ReturnCaptures(ReturnCaptures) {} void tooManyUses() override { LLVM_DEBUG(dbgs() << "Captured due to too many uses\n"); @@ -89,17 +86,12 @@ if (isa(U->getUser()) && !ReturnCaptures) return false; - if (EphValues.contains(U->getUser())) - return false; - LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n"); Captured = true; return true; } - const SmallPtrSetImpl &EphValues; - bool ReturnCaptures; bool Captured = false; @@ -167,9 +159,8 @@ // escape are not in a cycle. struct EarliestCaptures : public CaptureTracker { - EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT, - const SmallPtrSetImpl &EphValues) - : EphValues(EphValues), DT(DT), ReturnCaptures(ReturnCaptures), F(F) {} + EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT) + : DT(DT), ReturnCaptures(ReturnCaptures), F(F) {} void tooManyUses() override { Captured = true; @@ -181,9 +172,6 @@ if (isa(I) && !ReturnCaptures) return false; - if (EphValues.contains(I)) - return false; - if (!EarliestCapture) EarliestCapture = I; else @@ -195,8 +183,6 @@ return false; } - const SmallPtrSetImpl &EphValues; - Instruction *EarliestCapture = nullptr; const DominatorTree &DT; @@ -216,18 +202,8 @@ /// counts as capturing it or not. The boolean StoreCaptures specified whether /// storing the value (or part of it) into memory anywhere automatically /// counts as capturing it or not. -bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures, - bool StoreCaptures, unsigned MaxUsesToExplore) { - SmallPtrSet Empty; - return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures, Empty, - MaxUsesToExplore); -} - -/// Variant of the above function which accepts a set of Values that are -/// ephemeral and cannot cause pointers to escape. -bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures, - bool StoreCaptures, - const SmallPtrSetImpl &EphValues, +bool llvm::PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore) { assert(!isa(V) && "It doesn't make sense to ask whether a global is captured."); @@ -240,7 +216,7 @@ LLVM_DEBUG(dbgs() << "Captured?: " << *V << " = "); - SimpleCaptureTracker SCT(EphValues, ReturnCaptures); + SimpleCaptureTracker SCT(ReturnCaptures); PointerMayBeCaptured(V, &SCT, MaxUsesToExplore); if (SCT.Captured) ++NumCaptured; @@ -287,13 +263,11 @@ Instruction * llvm::FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures, bool StoreCaptures, const DominatorTree &DT, - - const SmallPtrSetImpl &EphValues, unsigned MaxUsesToExplore) { assert(!isa(V) && "It doesn't make sense to ask whether a global is captured."); - EarliestCaptures CB(ReturnCaptures, F, DT, EphValues); + EarliestCaptures CB(ReturnCaptures, F, DT); PointerMayBeCaptured(V, &CB, MaxUsesToExplore); if (CB.Captured) ++NumCapturedBefore; 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,9 +38,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CaptureTracking.h" -#include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" @@ -850,9 +848,6 @@ // Post-order numbers for each basic block. Used to figure out if memory // accesses are executed before another access. DenseMap PostOrderNumbers; - // Values that are only used with assumes. Used to refine pointer escape - // analysis. - SmallPtrSet EphValues; /// Keep track of instructions (partly) overlapping with killing MemoryDefs per /// basic block. @@ -872,9 +867,9 @@ DSEState &operator=(const DSEState &) = delete; DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, - PostDominatorTree &PDT, AssumptionCache &AC, + PostDominatorTree &PDT, const TargetLibraryInfo &TLI, const LoopInfo &LI) - : F(F), AA(AA), EI(DT, LI, EphValues), BatchAA(AA, &EI), MSSA(MSSA), + : F(F), AA(AA), EI(DT, LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) { // Collect blocks with throwing instructions not modeled in MemorySSA and // alloc-like objects. @@ -905,8 +900,6 @@ AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) { return isa(E->getTerminator()); }); - - CodeMetrics::collectEphemeralValues(&F, &AC, EphValues); } LocationSize strengthenLocationSize(const Instruction *I, @@ -1076,7 +1069,7 @@ if (!isInvisibleToCallerOnUnwind(V)) { I.first->second = false; } else if (isNoAliasCall(V)) { - I.first->second = !PointerMayBeCaptured(V, true, false, EphValues); + I.first->second = !PointerMayBeCaptured(V, true, false); } } return I.first->second; @@ -1095,7 +1088,7 @@ // with the killing MemoryDef. But we refrain from doing so for now to // limit compile-time and this does not cause any changes to the number // of stores removed on a large test set in practice. - I.first->second = PointerMayBeCaptured(V, false, true, EphValues); + I.first->second = PointerMayBeCaptured(V, false, true); return !I.first->second; } @@ -2064,13 +2057,12 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, - AssumptionCache &AC, const TargetLibraryInfo &TLI, const LoopInfo &LI) { bool MadeChange = false; MSSA.ensureOptimizedUses(); - DSEState State(F, AA, MSSA, DT, PDT, AC, TLI, LI); + DSEState State(F, AA, MSSA, DT, PDT, TLI, LI); // For each store: for (unsigned I = 0; I < State.MemDefs.size(); I++) { MemoryDef *KillingDef = State.MemDefs[I]; @@ -2251,10 +2243,9 @@ DominatorTree &DT = AM.getResult(F); MemorySSA &MSSA = AM.getResult(F).getMSSA(); PostDominatorTree &PDT = AM.getResult(F); - AssumptionCache &AC = AM.getResult(F); LoopInfo &LI = AM.getResult(F); - bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, AC, TLI, LI); + bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI); #ifdef LLVM_ENABLE_STATS if (AreStatisticsEnabled()) @@ -2271,3 +2262,4 @@ PA.preserve(); return PA; } + diff --git a/llvm/test/Transforms/DeadStoreElimination/assume.ll b/llvm/test/Transforms/DeadStoreElimination/assume.ll --- a/llvm/test/Transforms/DeadStoreElimination/assume.ll +++ b/llvm/test/Transforms/DeadStoreElimination/assume.ll @@ -8,6 +8,7 @@ ; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32) ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]]) +; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1 ; CHECK-NEXT: ret void ; %tmp1 = call noalias ptr @_Znwm(i64 32) @@ -22,6 +23,7 @@ ; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32) ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]]) +; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1 ; CHECK-NEXT: call void @quux(ptr @global) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll b/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll --- a/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll +++ b/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll @@ -22,12 +22,7 @@ ret i1 0 } -; FIXME: At the moment, the function is incorrectly simplified to unreachable. define i32 @test() { -; CHECK-LABEL: define i32 @test() { -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable -; entry: %a = alloca i32, align 4 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %a)