summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/PassManager.h29
-rw-r--r--llvm/lib/Analysis/CGSCCPassManager.cpp1
-rw-r--r--llvm/lib/IR/PassManager.cpp1
-rw-r--r--llvm/test/Other/new-pass-manager.ll51
-rw-r--r--llvm/tools/opt/Passes.cpp18
5 files changed, 95 insertions, 5 deletions
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index c1025434cc7..38b8b23fcc6 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/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 <typename PassT> void invalidate(Module &M) {
+ template <typename PassT> 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 <typename AnalysisT> 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 <typename AnalysisT> 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 <typename T, typename AnalysisManagerT>
+ 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<AnalysisT>(std::forward<T>(Arg));
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "No-op Analysis Invalidation Pass"; }
+};
+
}
#endif
diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp
index 9a3ebea1c40..e13f41ae412 100644
--- a/llvm/lib/Analysis/CGSCCPassManager.cpp
+++ b/llvm/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/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp
index 1eab4ae19bf..6905a226fec 100644
--- a/llvm/lib/IR/PassManager.cpp
+++ b/llvm/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/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll
index 6e250f63078..175a54a554b 100644
--- a/llvm/test/Other/new-pass-manager.ll
+++ b/llvm/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<no-op-module>,require<no-op-module>,require<no-op-module>' %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<no-op-module>,invalidate<no-op-module>,require<no-op-module>' %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<no-op-cgscc>,require<no-op-cgscc>,require<no-op-cgscc>)' %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<no-op-cgscc>,invalidate<no-op-cgscc>,require<no-op-cgscc>)' %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<no-op-function>,require<no-op-function>,require<no-op-function>)' %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<no-op-function>,invalidate<no-op-function>,require<no-op-function>)' %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/llvm/tools/opt/Passes.cpp b/llvm/tools/opt/Passes.cpp
index 90738620623..f3670d1ff2d 100644
--- a/llvm/tools/opt/Passes.cpp
+++ b/llvm/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<decltype(CREATE_PASS)>()); \
return true; \
+ } \
+ if (Name == "invalidate<" NAME ">") { \
+ MPM.addPass(NoopAnalysisInvalidationPass<decltype(CREATE_PASS)>()); \
+ return true; \
}
#include "PassRegistry.def"
@@ -158,6 +162,10 @@ static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
if (Name == "require<" NAME ">") { \
CGPM.addPass(NoopAnalysisRequirementPass<decltype(CREATE_PASS)>()); \
return true; \
+ } \
+ if (Name == "invalidate<" NAME ">") { \
+ CGPM.addPass(NoopAnalysisInvalidationPass<decltype(CREATE_PASS)>()); \
+ return true; \
}
#include "PassRegistry.def"
@@ -174,6 +182,10 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
if (Name == "require<" NAME ">") { \
FPM.addPass(NoopAnalysisRequirementPass<decltype(CREATE_PASS)>()); \
return true; \
+ } \
+ if (Name == "invalidate<" NAME ">") { \
+ FPM.addPass(NoopAnalysisInvalidationPass<decltype(CREATE_PASS)>()); \
+ return true; \
}
#include "PassRegistry.def"
OpenPOWER on IntegriCloud