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 @@ -1185,8 +1185,8 @@ static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM, AAResults &AAResults) { auto &MAMProxy = AM.getResult(F); - auto &MAM = MAMProxy.getManager(); - if (auto *R = MAM.template getCachedResult(*F.getParent())) { + if (auto *R = + MAMProxy.template getCachedResult(*F.getParent())) { AAResults.addAAResult(*R); MAMProxy .template registerOuterAnalysisInvalidation(); diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -381,10 +381,15 @@ public: class Result { public: + explicit Result() : FAM(nullptr) {} explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} + void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; } /// Accessor for the analysis manager. - FunctionAnalysisManager &getManager() { return *FAM; } + FunctionAnalysisManager &getManager() { + assert(FAM); + return *FAM; + } bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, CGSCCAnalysisManager::Invalidator &Inv); @@ -416,7 +421,8 @@ /// update result struct for the overall CGSCC walk. LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass( LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, - CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR); + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM); /// Helper to update the call graph after running a CGSCC pass. /// @@ -426,7 +432,8 @@ /// update result struct for the overall CGSCC walk. LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass( LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, - CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR); + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM); /// Adaptor that maps from a SCC to its functions. /// @@ -517,7 +524,7 @@ auto PAC = PA.getChecker(); if (!PAC.preserved() && !PAC.preservedSet>()) { CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N, - AM, UR); + AM, UR, FAM); assert( CG.lookupSCC(*N) == CurrentC && "Current SCC not updated to the SCC containing the current node!"); @@ -582,6 +589,10 @@ // a pointer that we can update. LazyCallGraph::SCC *C = &InitialC; + // Get Function analysis manager from its proxy. + FunctionAnalysisManager &FAM = + AM.getCachedResult(*C)->getManager(); + // Collect value handles for all of the indirect call sites. SmallVector CallHandles; @@ -720,6 +731,10 @@ // Update the analysis manager with each run and intersect the total set // of preserved analyses so we're ready to iterate. AM.invalidate(*C, PassPA); + auto *ResultFAMCP = + &AM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); + PA.intersect(std::move(PassPA)); } @@ -755,6 +770,10 @@ // Get the call graph for this module. LazyCallGraph &CG = AM.getResult(M); + // Get Function analysis manager from its proxy. + FunctionAnalysisManager &FAM = + AM.getCachedResult(M)->getManager(); + // We keep worklists to allow us to push more work onto the pass manager as // the passes are run. SmallPriorityWorklist RCWorklist; @@ -834,7 +853,9 @@ // manager into the Function analysis manager by getting a proxy here. // FIXME: This seems like a bit of a hack. We should find a cleaner // or more costructive way to ensure this happens. - (void)CGAM.getResult(*C, CG); + auto *ResultFAMCP = + &CGAM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); // Each time we visit a new SCC pulled off the worklist, // a transformation of a child SCC may have also modified this parent @@ -857,6 +878,9 @@ // that case, we'll end up doing a redundant invalidation here as // a consequence. CGAM.invalidate(*C, UR.CrossSCCPA); + ResultFAMCP = + &CGAM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); do { // Check that we didn't miss any update scenario. @@ -905,6 +929,9 @@ // late as it contains the nodes that were actively being // processed. CGAM.invalidate(*C, PassPA); + ResultFAMCP = + &CGAM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -63,6 +63,8 @@ namespace llvm { +class FunctionAnalysisManagerCGSCCProxy; + /// A special type used by analysis passes to provide an address that /// identifies that particular analysis pass type. /// @@ -785,7 +787,8 @@ /// /// \returns null if there is no cached result. template - typename PassT::Result *getCachedResult(IRUnitT &IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR, + bool calledFromProxy = false) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -797,7 +800,15 @@ detail::AnalysisResultModel; - return &static_cast(ResultConcept)->Result; + auto *RetRes = &static_cast(ResultConcept)->Result; + if (calledFromProxy) { + PreservedAnalyses PA = PreservedAnalyses::none(); + SmallDenseMap IsResultInvalidated; + Invalidator Inv(IsResultInvalidated, AnalysisResults); + assert(!RetRes->invalidate(IR, PA, Inv) && + "Cached result cannot be invalidated"); + } + return RetRes; } /// Register an analysis pass with the manager. @@ -1065,7 +1076,22 @@ public: explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {} - const AnalysisManagerT &getManager() const { return *OuterAM; } + /// Get a cached analysis. If the analysis can be invalidated, this will + /// assert. + template + typename PassT::Result *getCachedResult(IRUnitTParam &IR) const { + typename PassT::Result *Res = + OuterAM->template getCachedResult(IR, true); + return Res; + } + + /// Method provided for unit testing, not intended for general use. + template + bool cachedResultExists(IRUnitTParam &IR) const { + typename PassT::Result *Res = + OuterAM->template getCachedResult(IR); + return Res != nullptr; + } /// When invalidation occurs, remove any registered invalidation events. bool invalidate( diff --git a/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h b/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h --- a/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h +++ b/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h @@ -49,6 +49,7 @@ LazyCallGraph::SCC *SCC = nullptr; CGSCCAnalysisManager *AM = nullptr; CGSCCUpdateResult *UR = nullptr; + FunctionAnalysisManager *FAM = nullptr; ///} public: @@ -68,6 +69,8 @@ this->SCC = &SCC; this->AM = &AM; this->UR = &UR; + FAM = + &AM.getResult(SCC, LCG).getManager(); } ///} diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -69,6 +69,10 @@ // a pointer that we can update. LazyCallGraph::SCC *C = &InitialC; + // Get Function analysis manager from its proxy. + FunctionAnalysisManager &FAM = + AM.getCachedResult(*C)->getManager(); + for (auto &Pass : Passes) { if (DebugLogging) dbgs() << "Running pass: " << Pass->name() << " on " << *C << "\n"; @@ -104,6 +108,8 @@ // Update the analysis manager as each pass runs and potentially // invalidates analyses. AM.invalidate(*C, PassPA); + auto *ResultFAMCP = &AM.getResult(*C, G); + ResultFAMCP->updateFAM(FAM); // Finally, we intersect the final preserved analyses to compute the // aggregate preserved set for this pass manager. @@ -224,23 +230,19 @@ FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG) { - // Collect the FunctionAnalysisManager from the Module layer and use that to - // build the proxy result. - // - // This allows us to rely on the FunctionAnalysisMangaerModuleProxy to - // invalidate the function analyses. - auto &MAM = AM.getResult(C, CG).getManager(); + // Doing the following will change the pass order and as a result the tests + // Other/new-p*.ll which test pass order. + /* + auto &MAMProxy = AM.getResult(C, CG); Module &M = *C.begin()->getFunction().getParent(); - auto *FAMProxy = MAM.getCachedResult(M); - assert(FAMProxy && "The CGSCC pass manager requires that the FAM module " - "proxy is run on the module prior to entering the CGSCC " - "walk."); - - // Note that we special-case invalidation handling of this proxy in the CGSCC - // analysis manager's Module proxy. This avoids the need to do anything - // special here to recompute all of this if ever the FAM's module proxy goes + assert (MAMProxy.cachedResultExists(M) && + "The CGSCC pass manager requires that the FAM module proxy is run " + "on the module prior to entering the CGSCC walk"); + */ + // Create a new empty Result. This needs to have the FunctionAnalysisManager + // inside through the updateFAM() API whenever the FAM's module proxy goes // away. - return Result(FAMProxy->getManager()); + return Result(); } bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate( @@ -326,10 +328,10 @@ /// function analyses so that they don't retain stale handles. static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C, LazyCallGraph &G, - CGSCCAnalysisManager &AM) { - // Get the relevant function analysis manager. - auto &FAM = - AM.getResult(C, G).getManager(); + CGSCCAnalysisManager &AM, + FunctionAnalysisManager &FAM) { + auto *ResultFAMCP = &AM.getResult(C, G); + ResultFAMCP->updateFAM(FAM); // Now walk the functions in this SCC and invalidate any function analysis // results that might have outer dependencies on an SCC analysis. @@ -395,6 +397,10 @@ // them for each SCC that was split off. bool NeedFAMProxy = AM.getCachedResult(*OldC) != nullptr; + FunctionAnalysisManager *FAM = nullptr; + if (NeedFAMProxy) + FAM = + &AM.getResult(*OldC, G).getManager(); // We need to propagate an invalidation call to all but the newly current SCC // because the outer pass manager won't do that for us after splitting them. @@ -409,7 +415,7 @@ // Ensure the now-current SCC's function analyses are updated. if (NeedFAMProxy) - updateNewSCCFunctionAnalyses(*C, G, AM); + updateNewSCCFunctionAnalyses(*C, G, AM, *FAM); for (SCC &NewC : llvm::reverse(make_range(std::next(NewSCCRange.begin()), NewSCCRange.end()))) { @@ -420,7 +426,7 @@ // Ensure new SCCs' function analyses are updated. if (NeedFAMProxy) - updateNewSCCFunctionAnalyses(NewC, G, AM); + updateNewSCCFunctionAnalyses(NewC, G, AM, *FAM); // Also propagate a normal invalidation to the new SCC as only the current // will get one from the pass manager infrastructure. @@ -431,7 +437,8 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass( LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N, - CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, bool FunctionPass) { + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM, bool FunctionPass) { using Node = LazyCallGraph::Node; using Edge = LazyCallGraph::Edge; using SCC = LazyCallGraph::SCC; @@ -545,6 +552,9 @@ // Now update the call graph. C = incorporateNewSCCRange(RC->switchInternalEdgeToRef(N, E.getNode()), G, N, C, AM, UR); + auto *ResultFAMCP = + &AM.getResult(*C, G); + ResultFAMCP->updateFAM(FAM); } } @@ -630,6 +640,8 @@ // Now update the call graph. C = incorporateNewSCCRange(RC->switchInternalEdgeToRef(N, *RefTarget), G, N, C, AM, UR); + auto *ResultFAMCP = &AM.getResult(*C, G); + ResultFAMCP->updateFAM(FAM); } // Now promote ref edges into call edges. @@ -686,8 +698,11 @@ // If one of the invalidated SCCs had a cached proxy to a function // analysis manager, we need to create a proxy in the new current SCC as // the invalidated SCCs had their functions moved. - if (HasFunctionAnalysisProxy) - AM.getResult(*C, G); + if (HasFunctionAnalysisProxy) { + auto *ResultFAMCP = + &AM.getResult(*C, G); + ResultFAMCP->updateFAM(FAM); + } // Any analyses cached for this SCC are no longer precise as the shape // has changed by introducing this cycle. However, we have taken care to @@ -739,13 +754,15 @@ LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForFunctionPass( LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N, - CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) { - return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM) { + return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM, /* FunctionPass */ true); } LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForCGSCCPass( LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N, - CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) { - return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, + CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM) { + return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM, /* FunctionPass */ false); } diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1400,7 +1400,8 @@ static void updateCallGraphAfterCoroutineSplit( LazyCallGraph::Node &N, const coro::Shape &Shape, const SmallVectorImpl &Clones, LazyCallGraph::SCC &C, - LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) { + LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, + FunctionAnalysisManager &FAM) { if (!Shape.CoroBegin) return; @@ -1431,7 +1432,7 @@ // update of its own. Function passes run by the adaptor are not permitted to // add new edges of any kind to the graph, and the new edges inserted by this // pass would be misattributed to that unrelated function pass. - updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR); + updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM); } // When we see the coroutine the first time, we insert an indirect call to a @@ -1577,6 +1578,9 @@ // non-zero number of nodes, so we assume that here and grab the first // node's function's module. Module &M = *C.begin()->getFunction().getParent(); + auto &FAM = + AM.getResult(C, CG).getManager(); + if (!declaresCoroSplitIntrinsics(M)) return PreservedAnalyses::all(); @@ -1625,7 +1629,7 @@ SmallVector Clones; const coro::Shape Shape = splitCoroutine(F, Clones); - updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR); + updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM); } if (PrepareFn) diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -876,13 +876,13 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { - const ModuleAnalysisManager &MAM = - AM.getResult(InitialC, CG).getManager(); + const auto &MAMProxy = + AM.getResult(InitialC, CG); bool Changed = false; assert(InitialC.size() > 0 && "Cannot handle an empty SCC!"); Module &M = *InitialC.begin()->getFunction().getParent(); - ProfileSummaryInfo *PSI = MAM.getCachedResult(M); + ProfileSummaryInfo *PSI = MAMProxy.getCachedResult(M); if (!ImportedFunctionsStats && InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { @@ -995,9 +995,9 @@ // manager we get here for looking up results for functions other than this // node however because those functions aren't going to be mutated by this // pass. - FunctionAnalysisManager &FAM = - AM.getResult(*C, CG) - .getManager(); + auto *ResultFAMCP = + &AM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); // Get the remarks emission analysis for the caller. auto &ORE = FAM.getResult(F); @@ -1182,7 +1182,7 @@ // re-use the exact same logic for updating the call graph to reflect the // change. LazyCallGraph::SCC *OldC = C; - C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR); + C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR, FAM); LLVM_DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n"); RC = &C->getOuterRefSCC(); @@ -1228,9 +1228,10 @@ // Get the necessary information out of the call graph and nuke the // function there. Also, cclear out any cached analyses. auto &DeadC = *CG.lookupSCC(*CG.lookup(*DeadF)); - FunctionAnalysisManager &FAM = - AM.getResult(DeadC, CG) - .getManager(); + auto *ResultFAMCP = + &AM.getResult(*C, CG); + ResultFAMCP->updateFAM(FAM); + FAM.clear(*DeadF, DeadF->getName()); AM.clear(DeadC, DeadC.getName()); auto &DeadRC = DeadC.getOuterRefSCC(); diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3828,10 +3828,9 @@ auto *LI = AM.getCachedResult(F); auto *AA = &AM.getResult(F); - const ModuleAnalysisManager &MAM = - AM.getResult(F).getManager(); + auto &MAMProxy = AM.getResult(F); ProfileSummaryInfo *PSI = - MAM.getCachedResult(*F.getParent()); + MAMProxy.getCachedResult(*F.getParent()); auto *BFI = (PSI && PSI->hasProfileSummary()) ? &AM.getResult(F) : nullptr; diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1168,9 +1168,8 @@ PreservedAnalyses AddressSanitizerPass::run(Function &F, AnalysisManager &AM) { auto &MAMProxy = AM.getResult(F); - auto &MAM = MAMProxy.getManager(); Module &M = *F.getParent(); - if (auto *R = MAM.getCachedResult(M)) { + if (auto *R = MAMProxy.getCachedResult(M)) { const TargetLibraryInfo *TLI = &AM.getResult(F); AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope); if (Sanitizer.instrumentFunction(F, TLI)) diff --git a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp --- a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp +++ b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp @@ -2101,8 +2101,7 @@ auto &BFI = FAM.getResult(F); auto &DT = FAM.getResult(F); auto &MAMProxy = FAM.getResult(F); - auto &MAM = MAMProxy.getManager(); - auto &PSI = *MAM.getCachedResult(*F.getParent()); + auto &PSI = *MAMProxy.getCachedResult(*F.getParent()); auto &RI = FAM.getResult(F); auto &ORE = FAM.getResult(F); bool Changed = CHR(F, BFI, DT, PSI, RI, ORE).run(); diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp --- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -975,8 +975,8 @@ auto BFI = ConstHoistWithBlockFrequency ? &AM.getResult(F) : nullptr; - auto &MAM = AM.getResult(F).getManager(); - auto *PSI = MAM.getCachedResult(*F.getParent()); + auto &MAMProxy = AM.getResult(F); + auto *PSI = MAMProxy.getCachedResult(*F.getParent()); if (!runImpl(F, TTI, DT, BFI, F.getEntryBlock(), PSI)) return PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp --- a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp +++ b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -697,8 +697,8 @@ auto &TLI = AM.getResult(F); auto &AA = AM.getResult(F); auto &AC = AM.getResult(F); - auto &MAM = AM.getResult(F).getManager(); - auto *PSI = MAM.getCachedResult(*F.getParent()); + auto &MAMProxy = AM.getResult(F); + auto *PSI = MAMProxy.getCachedResult(*F.getParent()); auto *BFI = (PSI && PSI->hasProfileSummary()) ? &AM.getResult(F) : nullptr; MemorySSA *MSSA = EnableMSSALoopDependency diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp --- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -1409,10 +1409,9 @@ if (auto *LAMProxy = AM.getCachedResult(F)) LAM = &LAMProxy->getManager(); - const ModuleAnalysisManager &MAM = - AM.getResult(F).getManager(); + auto &MAMProxy = AM.getResult(F); ProfileSummaryInfo *PSI = - MAM.getCachedResult(*F.getParent()); + MAMProxy.getCachedResult(*F.getParent()); auto *BFI = (PSI && PSI->hasProfileSummary()) ? &AM.getResult(F) : nullptr; diff --git a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp --- a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp +++ b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp @@ -85,7 +85,7 @@ } else if (LCG) { LazyCallGraph::Node &N = LCG->get(Fn); LazyCallGraph::SCC *C = LCG->lookupSCC(N); - updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR); + updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM); } } diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -7994,10 +7994,9 @@ LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI, MSSA}; return LAM.getResult(L, AR); }; - const ModuleAnalysisManager &MAM = - AM.getResult(F).getManager(); + auto &MAMProxy = AM.getResult(F); ProfileSummaryInfo *PSI = - MAM.getCachedResult(*F.getParent()); + MAMProxy.getCachedResult(*F.getParent()); bool Changed = runImpl(F, SE, LI, TTI, DT, BFI, &TLI, DB, AA, AC, GetLAA, ORE, PSI); if (!Changed) diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll --- a/llvm/test/Other/new-pass-manager.ll +++ b/llvm/test/Other/new-pass-manager.ll @@ -27,7 +27,6 @@ ; CHECK-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-CGSCC-PASS-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-CGSCC-PASS-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-CGSCC-PASS-NEXT: Starting CGSCC pass manager run ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass ; CHECK-CGSCC-PASS-NEXT: Finished CGSCC pass manager run @@ -414,7 +413,6 @@ ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: RepeatedPass ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll --- a/llvm/test/Other/new-pm-defaults.ll +++ b/llvm/test/Other/new-pm-defaults.ll @@ -138,9 +138,9 @@ ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll --- a/llvm/test/Other/new-pm-lto-defaults.ll +++ b/llvm/test/Other/new-pm-lto-defaults.ll @@ -55,7 +55,6 @@ ; CHECK-O1-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O-NEXT: Running analysis: AAManager ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis @@ -74,6 +73,7 @@ ; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass ; CHECK-O2-NEXT: Finished llvm::Function pass manager run. ; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}InlinerPass> +; CHECK-O2-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O2-NEXT: Running pass: GlobalOptPass ; CHECK-O2-NEXT: Running pass: GlobalDCEPass ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> diff --git a/llvm/test/Other/new-pm-thinlto-defaults.ll b/llvm/test/Other/new-pm-thinlto-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-defaults.ll @@ -103,9 +103,9 @@ ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll @@ -75,9 +75,9 @@ ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll @@ -83,9 +83,9 @@ ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll @@ -71,9 +71,9 @@ ; CHECK-O123-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O123-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy on (foo) ; CHECK-O123-NEXT: Running analysis: PassInstrumentationAnalysis on (foo) -; CHECK-O123-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O123-NEXT: Starting CGSCC pass manager run. ; CHECK-O123-NEXT: Running pass: InlinerPass on (foo) +; CHECK-O123-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O123-NEXT: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-O123-NEXT: Finished CGSCC pass manager run. ; CHECK-O123-NEXT: Running pass: GlobalDCEPass @@ -103,9 +103,9 @@ ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis on foo ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: AAManager on foo diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll @@ -83,9 +83,9 @@ ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis -; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}> ; CHECK-O-NEXT: Running pass: AttributorCGSCCPass ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass diff --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp --- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp @@ -303,15 +303,28 @@ LazyCallGraph &CG, CGSCCUpdateResult &UR) { ++SCCPassRunCount1; - const ModuleAnalysisManager &MAM = - AM.getResult(C, CG).getManager(); - FunctionAnalysisManager &FAM = - AM.getResult(C, CG).getManager(); + // Note: The proper way to get to a module pass from a CGSCC pass is + // through the ModuleAnalysisManagerCGSCCProxy: + // ``` + // const auto &MAMProxy = + // AM.getResult(C, CG); + // ``` + // However getting a stateful analysis is incorrect usage, and the call + // to getCachedResult below asserts: + // ``` + // if (TestModuleAnalysis::Result *TMA = + // MAMProxy.getCachedResult( + // *C.begin()->getFunction().getParent())) + // AnalyzedModuleFunctionCount1 += TMA->FunctionCount; + // ``` + // For the purposes of this unittest, use the above MAM directly. if (TestModuleAnalysis::Result *TMA = MAM.getCachedResult( *C.begin()->getFunction().getParent())) AnalyzedModuleFunctionCount1 += TMA->FunctionCount; + FunctionAnalysisManager &FAM = + AM.getResult(C, CG).getManager(); TestSCCAnalysis::Result &AR = AM.getResult(C, CG); AnalyzedSCCFunctionCount1 += AR.FunctionCount; for (LazyCallGraph::Node &N : C) { @@ -375,19 +388,18 @@ // required module pass above. CGSCCPassManager CGPM1(/*DebugLogging*/ true); int CountFoundModuleAnalysis1 = 0; - CGPM1.addPass( - LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, - LazyCallGraph &CG, CGSCCUpdateResult &UR) { - const auto &MAM = - AM.getResult(C, CG).getManager(); - auto *TMA = MAM.getCachedResult( - *C.begin()->getFunction().getParent()); + CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, + CGSCCAnalysisManager &AM, LazyCallGraph &CG, + CGSCCUpdateResult &UR) { + const auto &MAMProxy = AM.getResult(C, CG); + bool TMA = MAMProxy.cachedResultExists( + *C.begin()->getFunction().getParent()); - if (TMA) - ++CountFoundModuleAnalysis1; + if (TMA) + ++CountFoundModuleAnalysis1; - return PreservedAnalyses::all(); - })); + return PreservedAnalyses::all(); + })); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); // The second CGSCC run checks that the module analysis got preserved the @@ -397,9 +409,9 @@ CGPM2.addPass( LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { - const auto &MAM = - AM.getResult(C, CG).getManager(); - auto *TMA = MAM.getCachedResult( + const auto &MAMProxy = + AM.getResult(C, CG); + bool TMA = MAMProxy.cachedResultExists( *C.begin()->getFunction().getParent()); if (TMA) @@ -416,19 +428,18 @@ // should have been invalidated by the above CGSCC run. CGSCCPassManager CGPM3(/*DebugLogging*/ true); int CountFoundModuleAnalysis3 = 0; - CGPM3.addPass( - LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, - LazyCallGraph &CG, CGSCCUpdateResult &UR) { - const auto &MAM = - AM.getResult(C, CG).getManager(); - auto *TMA = MAM.getCachedResult( - *C.begin()->getFunction().getParent()); + CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C, + CGSCCAnalysisManager &AM, LazyCallGraph &CG, + CGSCCUpdateResult &UR) { + const auto &MAMProxy = AM.getResult(C, CG); + bool TMA = MAMProxy.cachedResultExists( + *C.begin()->getFunction().getParent()); - if (TMA) - ++CountFoundModuleAnalysis3; + if (TMA) + ++CountFoundModuleAnalysis3; - return PreservedAnalyses::none(); - })); + return PreservedAnalyses::none(); + })); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); MPM.run(*M, MAM); @@ -455,17 +466,16 @@ // Start true and mark false if we ever failed to find a module analysis // because we expect this to succeed for each SCC. bool FoundModuleAnalysis1 = true; - FPM1.addPass( - LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { - const auto &MAM = - AM.getResult(F).getManager(); - auto *TMA = MAM.getCachedResult(*F.getParent()); + FPM1.addPass(LambdaFunctionPass([&](Function &F, + FunctionAnalysisManager &AM) { + const auto &MAMProxy = AM.getResult(F); + bool TMA = MAMProxy.cachedResultExists(*F.getParent()); - if (!TMA) - FoundModuleAnalysis1 = false; + if (!TMA) + FoundModuleAnalysis1 = false; - return PreservedAnalyses::all(); - })); + return PreservedAnalyses::all(); + })); CGSCCPassManager CGPM1(/*DebugLogging*/ true); CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1))); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1))); @@ -476,20 +486,19 @@ // Again, start true and mark false if we ever failed to find a module analysis // because we expect this to succeed for each SCC. bool FoundModuleAnalysis2 = true; - FPM2.addPass( - LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { - const auto &MAM = - AM.getResult(F).getManager(); - auto *TMA = MAM.getCachedResult(*F.getParent()); - - if (!TMA) - FoundModuleAnalysis2 = false; - - // Only fail to preserve analyses on one SCC and make sure that gets - // propagated. - return F.getName() == "h2" ? PreservedAnalyses::none() - : PreservedAnalyses::all(); - })); + FPM2.addPass(LambdaFunctionPass([&](Function &F, + FunctionAnalysisManager &AM) { + const auto &MAMProxy = AM.getResult(F); + bool TMA = MAMProxy.cachedResultExists(*F.getParent()); + + if (!TMA) + FoundModuleAnalysis2 = false; + + // Only fail to preserve analyses on one SCC and make sure that gets + // propagated. + return F.getName() == "h2" ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + })); CGSCCPassManager CGPM2(/*DebugLogging*/ true); CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2))); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2))); @@ -500,17 +509,16 @@ // Start false and mark true if we ever *succeeded* to find a module // analysis, as we expect this to fail for every function. bool FoundModuleAnalysis3 = false; - FPM3.addPass( - LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) { - const auto &MAM = - AM.getResult(F).getManager(); - auto *TMA = MAM.getCachedResult(*F.getParent()); + FPM3.addPass(LambdaFunctionPass([&](Function &F, + FunctionAnalysisManager &AM) { + const auto &MAMProxy = AM.getResult(F); + bool TMA = MAMProxy.cachedResultExists(*F.getParent()); - if (TMA) - FoundModuleAnalysis3 = true; + if (TMA) + FoundModuleAnalysis3 = true; - return PreservedAnalyses::none(); - })); + return PreservedAnalyses::none(); + })); CGSCCPassManager CGPM3(/*DebugLogging*/ true); CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3))); MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3))); @@ -879,7 +887,8 @@ } }; - TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {} + TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM) + : Runs(Runs), MAM(MAM) {} /// Run the analysis pass over the function and return a result. Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, @@ -888,9 +897,11 @@ auto &SCCDep = AM.getResult(C, CG); auto &ModuleProxy = AM.getResult(C, CG); - const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); // For the test, we insist that the module analysis starts off in the - // cache. + // cache. Getting a cached result that isn't stateless triggers an assert. + // auto &MDep = *ModuleProxy.getCachedResult( + // *C.begin()->getFunction().getParent()); + // Use MAM, for the purposes of this unittest. auto &MDep = *MAM.getCachedResult( *C.begin()->getFunction().getParent()); // Register the dependency as module analysis dependencies have to be @@ -906,6 +917,7 @@ static AnalysisKey Key; int &Runs; + ModuleAnalysisManager &MAM; }; AnalysisKey TestIndirectSCCAnalysis::Key; @@ -973,7 +985,9 @@ } }; - TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} + TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM, + CGSCCAnalysisManager &CGAM) + : Runs(Runs), MAM(MAM), CGAM(CGAM) {} /// Run the analysis pass over the function and return a result. Result run(Function &F, FunctionAnalysisManager &AM) { @@ -981,21 +995,23 @@ auto &FDep = AM.getResult(F); auto &ModuleProxy = AM.getResult(F); - const ModuleAnalysisManager &MAM = ModuleProxy.getManager(); // For the test, we insist that the module analysis starts off in the - // cache. + // cache. Getting a cached result that isn't stateless triggers an assert. + // Use MAM, for the purposes of this unittest. auto &MDep = *MAM.getCachedResult(*F.getParent()); // Register the dependency as module analysis dependencies have to be // pre-registered on the proxy. ModuleProxy.registerOuterAnalysisInvalidation< TestModuleAnalysis, TestIndirectFunctionAnalysis>(); - // For thet test we assume this is run inside a CGSCC pass manager. + // For the test we assume this is run inside a CGSCC pass manager. + // Use MAM, for the purposes of this unittest. const LazyCallGraph &CG = *MAM.getCachedResult(*F.getParent()); auto &CGSCCProxy = AM.getResult(F); - const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager(); // For the test, we insist that the CGSCC analysis starts off in the cache. + // Getting a cached result that isn't stateless triggers an assert. + // Use CGAM, for the purposes of this unittest. auto &SCCDep = *CGAM.getCachedResult(*CG.lookupSCC(*CG.lookup(F))); // Register the dependency as CGSCC analysis dependencies have to be @@ -1011,6 +1027,8 @@ static AnalysisKey Key; int &Runs; + ModuleAnalysisManager &MAM; + CGSCCAnalysisManager &CGAM; }; AnalysisKey TestIndirectFunctionAnalysis::Key; @@ -1023,7 +1041,7 @@ DoublyIndirectSCCAnalysisRuns = 0; CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); CGAM.registerPass( - [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); + [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); }); CGAM.registerPass([&] { return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); }); @@ -1031,7 +1049,8 @@ int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); FAM.registerPass([&] { - return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); + return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM, + CGAM); }); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1141,7 +1160,7 @@ DoublyIndirectSCCAnalysisRuns = 0; CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); }); CGAM.registerPass( - [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); }); + [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); }); CGAM.registerPass([&] { return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns); }); @@ -1149,7 +1168,8 @@ int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0; FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); FAM.registerPass([&] { - return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns); + return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM, + CGAM); }); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1198,7 +1218,7 @@ // Now update the call graph. auto &NewC = - updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); + updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM); assert(&NewC != &C && "Should get a new SCC due to update!"); (void)&NewC; @@ -1244,7 +1264,7 @@ // Now update the call graph. auto &NewC = - updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR); + updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM); assert(&NewC != &C && "Should get a new SCC due to update!"); (void)&NewC; @@ -1336,6 +1356,8 @@ if (C.getName() != "(h3, h1, h2)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnX = M->getFunction("x"); Function *FnH1 = M->getFunction("h1"); Function *FnH2 = M->getFunction("h2"); @@ -1354,7 +1376,7 @@ auto &H2N = *llvm::find_if( C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); ASSERT_NO_FATAL_FAILURE( - updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR)); + updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM)); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1371,6 +1393,8 @@ if (C.getName() != "(h3, h1, h2)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnX = M->getFunction("x"); Function *FnH1 = M->getFunction("h1"); Function *FnH2 = M->getFunction("h2"); @@ -1388,8 +1412,9 @@ auto &H2N = *llvm::find_if( C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; }); - ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR), - "Any new calls should be modeled as"); + ASSERT_DEATH( + updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM), + "Any new calls should be modeled as"); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1405,6 +1430,8 @@ if (C.getName() != "(f)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnF = M->getFunction("f"); Function *FnH2 = M->getFunction("h2"); ASSERT_NE(FnF, nullptr); @@ -1417,7 +1444,7 @@ auto &FN = *llvm::find_if( C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); ASSERT_NO_FATAL_FAILURE( - updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR)); + updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM)); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1434,6 +1461,8 @@ if (C.getName() != "(f)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnF = M->getFunction("f"); Function *FnH2 = M->getFunction("h2"); ASSERT_NE(FnF, nullptr); @@ -1445,8 +1474,9 @@ auto &FN = *llvm::find_if( C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); - ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR), - "Any new calls should be modeled as"); + ASSERT_DEATH( + updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM), + "Any new calls should be modeled as"); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1462,6 +1492,8 @@ if (C.getName() != "(f)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnF = M->getFunction("f"); Function *FnewF = Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M); @@ -1482,7 +1514,7 @@ C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); ASSERT_NO_FATAL_FAILURE( - updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR)); + updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM)); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1499,6 +1531,8 @@ if (C.getName() != "(f)") return; + auto &FAM = + AM.getResult(C, CG).getManager(); Function *FnF = M->getFunction("f"); Function *FnewF = Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M); @@ -1518,8 +1552,9 @@ auto &FN = *llvm::find_if( C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; }); - ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR), - "Any new calls should be modeled as"); + ASSERT_DEATH( + updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM), + "Any new calls should be modeled as"); })); ModulePassManager MPM(/*DebugLogging*/ true); @@ -1696,6 +1731,9 @@ CGPM.addPass(LambdaSCCPassNoPreserve( [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { + auto &FAM = + AM.getResult(C, CG).getManager(); + for (auto &N : C) { auto &F = N.getFunction(); if (F.getName() != "f") @@ -1723,7 +1761,7 @@ "f.ref", &*F.begin()->begin()); ASSERT_NO_FATAL_FAILURE( - updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR)) + updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM)) << "Updating the call graph with a demoted, self-referential " "call edge 'f -> f', and a newly inserted ref edge 'f -> g', " "caused a fatal failure"; diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp --- a/llvm/unittests/IR/PassManagerTest.cpp +++ b/llvm/unittests/IR/PassManagerTest.cpp @@ -107,20 +107,23 @@ struct TestFunctionPass : PassInfoMixin { TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, - int &AnalyzedFunctionCount, + int &AnalyzedFunctionCount, ModuleAnalysisManager &MAM, bool OnlyUseCachedResults = false) : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), - AnalyzedFunctionCount(AnalyzedFunctionCount), + AnalyzedFunctionCount(AnalyzedFunctionCount), MAM(MAM), OnlyUseCachedResults(OnlyUseCachedResults) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { ++RunCount; - const ModuleAnalysisManager &MAM = - AM.getResult(F).getManager(); + // Getting a cached result that isn't stateless through the proxy will + // trigger an assert: + // auto &ModuleProxy = AM.getResult(F); + // Use MAM, for the purposes of this unittest. if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult(*F.getParent())) + MAM.getCachedResult(*F.getParent())) { AnalyzedFunctionCount += TMA->FunctionCount; + } if (OnlyUseCachedResults) { // Hack to force the use of the cached interface. @@ -139,6 +142,7 @@ int &RunCount; int &AnalyzedInstrCount; int &AnalyzedFunctionCount; + ModuleAnalysisManager &MAM; bool OnlyUseCachedResults; }; @@ -436,8 +440,9 @@ { // Pointless scope to test move assignment. FunctionPassManager NestedFPM(/*DebugLogging*/ true); - NestedFPM.addPass(TestFunctionPass( - FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1)); + NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, + AnalyzedInstrCount1, + AnalyzedFunctionCount1, MAM)); FPM = std::move(NestedFPM); } NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); @@ -455,7 +460,7 @@ { FunctionPassManager FPM(/*DebugLogging*/ true); FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, - AnalyzedFunctionCount2)); + AnalyzedFunctionCount2, MAM)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -468,7 +473,7 @@ { FunctionPassManager FPM(/*DebugLogging*/ true); FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, - AnalyzedFunctionCount3)); + AnalyzedFunctionCount3, MAM)); FPM.addPass(TestInvalidationFunctionPass("f")); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -482,7 +487,7 @@ { FunctionPassManager FPM; FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, - AnalyzedFunctionCount4)); + AnalyzedFunctionCount4, MAM)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -495,7 +500,7 @@ FunctionPassManager FPM(/*DebugLogging*/ true); FPM.addPass(TestInvalidationFunctionPass("f")); FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, - AnalyzedFunctionCount5, + AnalyzedFunctionCount5, MAM, /*OnlyUseCachedResults=*/true)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -612,21 +617,22 @@ } }; - TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {} + TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM) + : Runs(Runs), MAM(MAM) {} /// Run the analysis pass over the function and return a result. Result run(Function &F, FunctionAnalysisManager &AM) { ++Runs; auto &FDep = AM.getResult(F); - auto &Proxy = AM.getResult(F); - const ModuleAnalysisManager &MAM = Proxy.getManager(); + auto &MAMProxy = AM.getResult(F); // For the test, we insist that the module analysis starts off in the - // cache. + // cache. Getting a cached result that isn't stateless trigger an assert. + // Use MAM, for the purposes of this unittest. auto &MDep = *MAM.getCachedResult(*F.getParent()); // And register the dependency as module analysis dependencies have to be // pre-registered on the proxy. - Proxy.registerOuterAnalysisInvalidation(); + MAMProxy.registerOuterAnalysisInvalidation(); return Result(FDep, MDep); } @@ -635,6 +641,7 @@ static AnalysisKey Key; int &Runs; + ModuleAnalysisManager &MAM; }; AnalysisKey TestIndirectFunctionAnalysis::Key; @@ -693,16 +700,16 @@ TEST_F(PassManagerTest, IndirectAnalysisInvalidation) { FunctionAnalysisManager FAM(/*DebugLogging*/ true); + ModuleAnalysisManager MAM(/*DebugLogging*/ true); int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0, IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0; FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); }); FAM.registerPass( - [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); }); + [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns, MAM); }); FAM.registerPass([&] { return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns); }); - ModuleAnalysisManager MAM(/*DebugLogging*/ true); MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); }); MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); diff --git a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp --- a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp +++ b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp @@ -779,9 +779,11 @@ .WillByDefault(Invoke([&](Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR) { auto &FAMP = AM.getResult(L, AR); - auto &FAM = FAMP.getManager(); Function &F = *L.getHeader()->getParent(); - if (FAM.getCachedResult(F)) + // This call will assert when trying to get the actual analysis if the + // FunctionAnalysis can be invalidated. Only check its existence. + // Alternatively, use FAM above, for the purposes of this unittest. + if (FAMP.cachedResultExists(F)) FAMP.registerOuterAnalysisInvalidation(); return MLAHandle.getResult();