diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index c1025434cc7..38b8b23fcc6 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -373,10 +373,10 @@ public: /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. - template void invalidate(Module &M) { + template void invalidate(IRUnitT IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. @@ -791,6 +791,31 @@ template struct NoopAnalysisRequirementPass { static StringRef name() { return "No-op Analysis Requirement Pass"; } }; +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template struct NoopAnalysisInvalidationPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(T &&Arg, AnalysisManagerT *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate(std::forward(Arg)); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "No-op Analysis Invalidation Pass"; } +}; + } #endif diff --git a/lib/Analysis/CGSCCPassManager.cpp b/lib/Analysis/CGSCCPassManager.cpp index 9a3ebea1c40..e13f41ae412 100644 --- a/lib/Analysis/CGSCCPassManager.cpp +++ b/lib/Analysis/CGSCCPassManager.cpp @@ -91,6 +91,7 @@ void CGSCCAnalysisManager::invalidateImpl(void *PassID, LazyCallGraph::SCC &C) { dbgs() << "Invalidating CGSCC analysis: " << lookupPass(PassID).name() << "\n"; CGSCCAnalysisResultLists[&C].erase(RI->second); + CGSCCAnalysisResults.erase(RI); } void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC &C, diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 1eab4ae19bf..6905a226fec 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -176,6 +176,7 @@ void FunctionAnalysisManager::invalidateImpl(void *PassID, Function &F) { dbgs() << "Invalidating function analysis: " << lookupPass(PassID).name() << "\n"; FunctionAnalysisResultLists[&F].erase(RI->second); + FunctionAnalysisResults.erase(RI); } void FunctionAnalysisManager::invalidateImpl(Function &F, diff --git a/test/Other/new-pass-manager.ll b/test/Other/new-pass-manager.ll index 6e250f63078..175a54a554b 100644 --- a/test/Other/new-pass-manager.ll +++ b/test/Other/new-pass-manager.ll @@ -107,6 +107,57 @@ ; CHECK-NO-OP-INVALIDATION: Starting module pass manager ; CHECK-NO-OP-INVALIDATION-NOT: Invalidating all non-preserved analyses +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='require,require,require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Starting module pass manager +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running module pass: No-op Analysis Requirement Pass +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS-NOT: Running module analysis: NoOpModuleAnalysis + +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='require,invalidate,require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Starting module pass manager +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module pass: No-op Analysis Requirement Pass +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Invalidating module analysis: NoOpModuleAnalysis +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis + +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='cgscc(require,require,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Starting CGSCC pass manager +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running CGSCC pass: No-op Analysis Requirement Pass +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS-NOT: Running CGSCC analysis: NoOpCGSCCAnalysis + +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='cgscc(require,invalidate,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Starting CGSCC pass manager +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC pass: No-op Analysis Requirement Pass +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Invalidating CGSCC analysis: NoOpCGSCCAnalysis +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis + +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='function(require,require,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Starting function pass manager +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running function pass: No-op Analysis Requirement Pass +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS-NOT: Running function analysis: NoOpFunctionAnalysis + +; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: -passes='function(require,invalidate,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Starting function pass manager +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function pass: No-op Analysis Requirement Pass +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Invalidating function analysis: NoOpFunctionAnalysis +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis + define void @foo() { ret void } diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index 90738620623..f3670d1ff2d 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -105,7 +105,7 @@ void llvm::registerFunctionAnalyses(FunctionAnalysisManager &FAM) { static bool isModulePassName(StringRef Name) { #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; #include "PassRegistry.def" @@ -115,7 +115,7 @@ static bool isModulePassName(StringRef Name) { static bool isCGSCCPassName(StringRef Name) { #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; #include "PassRegistry.def" @@ -125,7 +125,7 @@ static bool isCGSCCPassName(StringRef Name) { static bool isFunctionPassName(StringRef Name) { #define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; #include "PassRegistry.def" @@ -142,6 +142,10 @@ static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { if (Name == "require<" NAME ">") { \ MPM.addPass(NoopAnalysisRequirementPass()); \ return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + MPM.addPass(NoopAnalysisInvalidationPass()); \ + return true; \ } #include "PassRegistry.def" @@ -158,6 +162,10 @@ static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) { if (Name == "require<" NAME ">") { \ CGPM.addPass(NoopAnalysisRequirementPass()); \ return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + CGPM.addPass(NoopAnalysisInvalidationPass()); \ + return true; \ } #include "PassRegistry.def" @@ -174,6 +182,10 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { if (Name == "require<" NAME ">") { \ FPM.addPass(NoopAnalysisRequirementPass()); \ return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + FPM.addPass(NoopAnalysisInvalidationPass()); \ + return true; \ } #include "PassRegistry.def"