[llvm] r225246 - [PM] Add a utility pass template that synthesizes the invalidation of

Chandler Carruth chandlerc at gmail.com
Mon Jan 5 20:49:45 PST 2015


Author: chandlerc
Date: Mon Jan  5 22:49:44 2015
New Revision: 225246

URL: http://llvm.org/viewvc/llvm-project?rev=225246&view=rev
Log:
[PM] Add a utility pass template that synthesizes the invalidation of
a specific analysis result.

This is quite handy to test things, and will also likely be very useful
for debugging issues. You could narrow down pass validation failures by
walking these invalidate pass runs up and down the pass pipeline, etc.
I've added support to the pass pipeline parsing to be able to create one
of these for any analysis pass desired.

Just adding this class uncovered one latent bug where the
AnalysisManager CRTP base class had a hard-coded Module type rather than
using IRUnitT.

I've also added tests for invalidation and caching of analyses in
a basic way across all the pass managers. These in turn uncovered two
more bugs where we failed to correctly invalidate an analysis -- its
results were invalidated but the key for re-running the pass was never
cleared and so it was never re-run. Quite nasty. I'm very glad to debug
this here rather than with a full system.

Also, yes, the naming here is horrid. I'm going to update some of the
names to be slightly less awful shortly. But really, I've no "good"
ideas for naming. I'll be satisfied if I can get it to "not bad".

Modified:
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
    llvm/trunk/lib/IR/PassManager.cpp
    llvm/trunk/test/Other/new-pass-manager.ll
    llvm/trunk/tools/opt/Passes.cpp

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=225246&r1=225245&r2=225246&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Mon Jan  5 22:49:44 2015
@@ -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 Noo
   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

Modified: llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=225246&r1=225245&r2=225246&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CGSCCPassManager.cpp (original)
+++ llvm/trunk/lib/Analysis/CGSCCPassManager.cpp Mon Jan  5 22:49:44 2015
@@ -91,6 +91,7 @@ void CGSCCAnalysisManager::invalidateImp
     dbgs() << "Invalidating CGSCC analysis: " << lookupPass(PassID).name()
            << "\n";
   CGSCCAnalysisResultLists[&C].erase(RI->second);
+  CGSCCAnalysisResults.erase(RI);
 }
 
 void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC &C,

Modified: llvm/trunk/lib/IR/PassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=225246&r1=225245&r2=225246&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassManager.cpp (original)
+++ llvm/trunk/lib/IR/PassManager.cpp Mon Jan  5 22:49:44 2015
@@ -176,6 +176,7 @@ void FunctionAnalysisManager::invalidate
     dbgs() << "Invalidating function analysis: " << lookupPass(PassID).name()
            << "\n";
   FunctionAnalysisResultLists[&F].erase(RI->second);
+  FunctionAnalysisResults.erase(RI);
 }
 
 void FunctionAnalysisManager::invalidateImpl(Function &F,

Modified: llvm/trunk/test/Other/new-pass-manager.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pass-manager.ll?rev=225246&r1=225245&r2=225246&view=diff
==============================================================================
--- llvm/trunk/test/Other/new-pass-manager.ll (original)
+++ llvm/trunk/test/Other/new-pass-manager.ll Mon Jan  5 22:49:44 2015
@@ -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
 }

Modified: llvm/trunk/tools/opt/Passes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.cpp?rev=225246&r1=225245&r2=225246&view=diff
==============================================================================
--- llvm/trunk/tools/opt/Passes.cpp (original)
+++ llvm/trunk/tools/opt/Passes.cpp Mon Jan  5 22:49:44 2015
@@ -105,7 +105,7 @@ void llvm::registerFunctionAnalyses(Func
 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 N
 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 Na
 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(ModulePa
   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(CGSCCPass
   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(Functi
   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"
 





More information about the llvm-commits mailing list