Index: include/llvm/Analysis/AliasAnalysis.h =================================================================== --- include/llvm/Analysis/AliasAnalysis.h +++ include/llvm/Analysis/AliasAnalysis.h @@ -690,6 +690,9 @@ return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); } + void startKeepingCaches(); + void stopKeepingCaches(); + private: class Concept; @@ -771,6 +774,12 @@ virtual ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) = 0; + // Don't clear internal caches. Only call when we know thare are no functional + // IR changes. Call its counterpart below to clear caches and make AA + // stateless again. + virtual void startKeepingCaches() = 0; + virtual void stopKeepingCaches() = 0; + /// @} }; @@ -822,6 +831,9 @@ const CallBase *Call2) override { return Result.getModRefInfo(Call1, Call2); } + + void startKeepingCaches() override { Result.startKeepingCaches(); } + void stopKeepingCaches() override { Result.stopKeepingCaches(); } }; /// A CRTP-driven "mixin" base class to help implement the function alias @@ -898,6 +910,14 @@ return AAR ? AAR->getModRefInfo(Call1, Call2) : CurrentResult.getModRefInfo(Call1, Call2); } + + void startKeepingCaches() { + AAR ? AAR->startKeepingCaches() : CurrentResult.startKeepingCaches(); + } + + void stopKeepingCaches() { + AAR ? AAR->stopKeepingCaches() : CurrentResult.stopKeepingCaches(); + } }; explicit AAResultBase() = default; @@ -947,6 +967,9 @@ ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { return ModRefInfo::ModRef; } + + void startKeepingCaches() {} + void stopKeepingCaches() {} }; /// Return true if this pointer is returned by a noalias function. Index: include/llvm/Analysis/BasicAliasAnalysis.h =================================================================== --- include/llvm/Analysis/BasicAliasAnalysis.h +++ include/llvm/Analysis/BasicAliasAnalysis.h @@ -100,7 +100,12 @@ /// call site is not known. FunctionModRefBehavior getModRefBehavior(const Function *Fn); + void startKeepingCaches(); + void stopKeepingCaches(); + private: + bool keepBasicAAInternalCaches = false; + // A linear transformation of a Value; this class represents ZExt(SExt(V, // SExtBits), ZExtBits) * Scale + Offset. struct VariableGEPIndex { Index: lib/Analysis/AliasAnalysis.cpp =================================================================== --- lib/Analysis/AliasAnalysis.cpp +++ lib/Analysis/AliasAnalysis.cpp @@ -372,6 +372,16 @@ return Result; } +void AAResults::startKeepingCaches() { + for (const auto &AA : AAs) + AA->startKeepingCaches(); +} + +void AAResults::stopKeepingCaches() { + for (const auto &AA : AAs) + AA->stopKeepingCaches(); +} + raw_ostream &llvm::operator<<(raw_ostream &OS, AliasResult AR) { switch (AR) { case NoAlias: Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -816,6 +816,16 @@ } #endif +void BasicAAResult::startKeepingCaches() { + keepBasicAAInternalCaches = true; +} + +void BasicAAResult::stopKeepingCaches() { + AliasCache.shrink_and_clear(); + IsCapturedCache.shrink_and_clear(); + keepBasicAAInternalCaches = false; +} + AliasResult BasicAAResult::alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { assert(notDifferentParent(LocA.Ptr, LocB.Ptr) && @@ -834,8 +844,12 @@ // shrink_and_clear so it quickly returns to the inline capacity of the // SmallDenseMap if it ever grows larger. // FIXME: This should really be shrink_to_inline_capacity_and_clear(). - AliasCache.shrink_and_clear(); - IsCapturedCache.shrink_and_clear(); + + if (!keepBasicAAInternalCaches) { + AliasCache.shrink_and_clear(); + IsCapturedCache.shrink_and_clear(); + } + VisitedPhiBBs.clear(); return Alias; } Index: lib/Analysis/MemorySSA.cpp =================================================================== --- lib/Analysis/MemorySSA.cpp +++ lib/Analysis/MemorySSA.cpp @@ -1155,7 +1155,9 @@ MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT) : AA(AA), DT(DT), F(Func), LiveOnEntryDef(nullptr), Walker(nullptr), SkipWalker(nullptr), NextID(0) { + AA->startKeepingCaches(); buildMemorySSA(); + AA->stopKeepingCaches(); } MemorySSA::~MemorySSA() {