diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/CGSCCPassManager.cpp | 87 | ||||
-rw-r--r-- | llvm/lib/Analysis/LoopPassManager.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/IR/PassManager.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Passes/PassRegistry.def | 1 |
5 files changed, 132 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp index c72b0efce81..b2bee0258d1 100644 --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -13,6 +13,8 @@ using namespace llvm; +// Explicit template instantiations and specialization defininitions for core +// template typedefs. namespace llvm { // Explicit instantiations for the core proxy templates. @@ -22,9 +24,9 @@ template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, CGSCCUpdateResult &>; template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>; template class OuterAnalysisManagerProxy<ModuleAnalysisManager, - LazyCallGraph::SCC>; + LazyCallGraph::SCC, LazyCallGraph &>; template class InnerAnalysisManagerProxy<FunctionAnalysisManager, - LazyCallGraph::SCC>; + LazyCallGraph::SCC, LazyCallGraph &>; template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>; /// Explicitly specialize the pass manager run method to handle call graph @@ -84,6 +86,87 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, return PA; } +bool CGSCCAnalysisManagerModuleProxy::Result::invalidate( + Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &Inv) { + // If this proxy or the call graph is going to be invalidated, we also need + // to clear all the keys coming from that analysis. + // + // We also directly invalidate the FAM's module proxy if necessary, and if + // that proxy isn't preserved we can't preserve this proxy either. We rely on + // it to handle module -> function analysis invalidation in the face of + // structural changes and so if it's unavailable we conservatively clear the + // entire SCC layer as well rather than trying to do invaliadtion ourselves. + if (!PA.preserved<CGSCCAnalysisManagerModuleProxy>() || + Inv.invalidate<LazyCallGraphAnalysis>(M, PA) || + Inv.invalidate<FunctionAnalysisManagerModuleProxy>(M, PA)) { + InnerAM->clear(); + + // And the proxy itself should be marked as invalid so that we can observe + // the new call graph. This isn't strictly necessary because we cheat + // above, but is still useful. + return true; + } + + // Ok, we have a graph, so we can propagate the invalidation down into it. + for (auto &RC : G->postorder_ref_sccs()) + for (auto &C : RC) + InnerAM->invalidate(C, PA); + + // Return false to indicate that this result is still a valid proxy. + return false; +} + +template <> +CGSCCAnalysisManagerModuleProxy::Result +CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM) { + // Force the Function analysis manager to also be available so that it can + // be accessed in an SCC analysis and proxied onward to function passes. + // FIXME: It is pretty awkward to just drop the result here and assert that + // we can find it again later. + (void)AM.getResult<FunctionAnalysisManagerModuleProxy>(M); + + return Result(*InnerAM, AM.getResult<LazyCallGraphAnalysis>(M)); +} + +AnalysisKey FunctionAnalysisManagerCGSCCProxy::Key; + +FunctionAnalysisManagerCGSCCProxy::Result +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<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager(); + Module &M = *C.begin()->getFunction().getParent(); + auto *FAMProxy = MAM.getCachedResult<FunctionAnalysisManagerModuleProxy>(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 + // away. + return Result(FAMProxy->getManager()); +} + +bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate( + LazyCallGraph::SCC &C, const PreservedAnalyses &PA, + CGSCCAnalysisManager::Invalidator &Inv) { + for (LazyCallGraph::Node &N : C) + FAM->invalidate(N.getFunction(), PA); + + // This proxy doesn't need to handle invalidation itself. Instead, the + // module-level CGSCC proxy handles it above by ensuring that if the + // module-level FAM proxy becomes invalid the entire SCC layer, which + // includes this proxy, is cleared. + return false; +} + } // End llvm namespace namespace { diff --git a/llvm/lib/Analysis/LoopPassManager.cpp b/llvm/lib/Analysis/LoopPassManager.cpp index 8bac19a5821..5b40a0beff7 100644 --- a/llvm/lib/Analysis/LoopPassManager.cpp +++ b/llvm/lib/Analysis/LoopPassManager.cpp @@ -17,12 +17,30 @@ using namespace llvm; -// Explicit instantiations for core typedef'ed templates. +// Explicit template instantiations and specialization defininitions for core +// template typedefs. namespace llvm { template class PassManager<Loop>; template class AnalysisManager<Loop>; template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>; + +template <> +bool LoopAnalysisManagerFunctionProxy::Result::invalidate( + Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv) { + // If this proxy isn't marked as preserved, the set of Function objects in + // the module may have changed. We therefore can't call + // InnerAM->invalidate(), because any pointers to Functions it has may be + // stale. + if (!PA.preserved(LoopAnalysisManagerFunctionProxy::ID())) + InnerAM->clear(); + + // FIXME: Proper suppor for invalidation isn't yet implemented for the LPM. + + // Return false to indicate that this result is still a valid proxy. + return false; +} } PreservedAnalyses llvm::getLoopPassPreservedAnalyses() { diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp index 171805f7d24..7c478ea1cf6 100644 --- a/llvm/lib/IR/PassManager.cpp +++ b/llvm/lib/IR/PassManager.cpp @@ -13,7 +13,8 @@ using namespace llvm; -// Explicit template instantiations for core template typedefs. +// Explicit template instantiations and specialization defininitions for core +// template typedefs. namespace llvm { template class AllAnalysesOn<Module>; template class AllAnalysesOn<Function>; @@ -23,6 +24,31 @@ template class AnalysisManager<Module>; template class AnalysisManager<Function>; template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; + +template <> +bool FunctionAnalysisManagerModuleProxy::Result::invalidate( + Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &Inv) { + // If this proxy isn't marked as preserved, then even if the result remains + // valid, the key itself may no longer be valid, so we clear everything. + // + // Note that in order to preserve this proxy, a module pass must ensure that + // the FAM has been completely updated to handle the deletion of functions. + // Specifically, any FAM-cached results for those functions need to have been + // forcibly cleared. When preserved, this proxy will only invalidate results + // cached on functions *still in the module* at the end of the module pass. + if (!PA.preserved(FunctionAnalysisManagerModuleProxy::ID())) { + InnerAM->clear(); + return true; + } + + // Otherwise propagate the invalidation event to all the remaining IR units. + for (Function &F : M) + InnerAM->invalidate(F, PA); + + // Return false to indicate that this result is still a valid proxy. + return false; +} } AnalysisKey PreservedAnalyses::AllAnalysesKey; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 98694fd9788..ce523ae5793 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -769,7 +769,6 @@ void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, ModuleAnalysisManager &MAM) { MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); - CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); }); CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); }); FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index d3a6be871ad..a35e7e8caf1 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -79,6 +79,7 @@ MODULE_PASS("verify", VerifierPass()) #define CGSCC_ANALYSIS(NAME, CREATE_PASS) #endif CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) +CGSCC_ANALYSIS("fam-proxy", FunctionAnalysisManagerCGSCCProxy()) #undef CGSCC_ANALYSIS #ifndef CGSCC_PASS |