llvm.org GIT mirror llvm / 17395fa
[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". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225246 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 4 years ago
5 changed file(s) with 95 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
372372 /// \brief Invalidate a specific analysis pass for an IR module.
373373 ///
374374 /// Note that the analysis result can disregard invalidation.
375 template void invalidate(Module &M) {
375 template void invalidate(IRUnitT IR) {
376376 assert(AnalysisPasses.count(PassT::ID()) &&
377377 "This analysis pass was not registered prior to being invalidated");
378 derived_this()->invalidateImpl(PassT::ID(), M);
378 derived_this()->invalidateImpl(PassT::ID(), IR);
379379 }
380380
381381 /// \brief Invalidate analyses cached for an IR unit.
790790 static StringRef name() { return "No-op Analysis Requirement Pass"; }
791791 };
792792
793 /// \brief A template utility pass to force an analysis result to be
794 /// invalidated.
795 ///
796 /// This is a no-op pass which simply forces a specific analysis result to be
797 /// invalidated when it is run.
798 template struct NoopAnalysisInvalidationPass {
799 /// \brief Run this pass over some unit of IR.
800 ///
801 /// This pass can be run over any unit of IR and use any analysis manager
802 /// provided they satisfy the basic API requirements. When this pass is
803 /// created, these methods can be instantiated to satisfy whatever the
804 /// context requires.
805 template
806 PreservedAnalyses run(T &&Arg, AnalysisManagerT *AM) {
807 if (AM)
808 // We have to directly invalidate the analysis result as we can't
809 // enumerate all other analyses and use the preserved set to control it.
810 (void)AM->template invalidate(std::forward(Arg));
811
812 return PreservedAnalyses::all();
813 }
814
815 static StringRef name() { return "No-op Analysis Invalidation Pass"; }
816 };
817
793818 }
794819
795820 #endif
9090 dbgs() << "Invalidating CGSCC analysis: " << lookupPass(PassID).name()
9191 << "\n";
9292 CGSCCAnalysisResultLists[&C].erase(RI->second);
93 CGSCCAnalysisResults.erase(RI);
9394 }
9495
9596 void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC &C,
175175 dbgs() << "Invalidating function analysis: " << lookupPass(PassID).name()
176176 << "\n";
177177 FunctionAnalysisResultLists[&F].erase(RI->second);
178 FunctionAnalysisResults.erase(RI);
178179 }
179180
180181 void FunctionAnalysisManager::invalidateImpl(Function &F,
106106 ; CHECK-NO-OP-INVALIDATION: Starting module pass manager
107107 ; CHECK-NO-OP-INVALIDATION-NOT: Invalidating all non-preserved analyses
108108
109 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
110 ; RUN: -passes='require,require,require' %s 2>&1 \
111 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS
112 ; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Starting module pass manager
113 ; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running module pass: No-op Analysis Requirement Pass
114 ; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis
115 ; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS-NOT: Running module analysis: NoOpModuleAnalysis
116
117 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
118 ; RUN: -passes='require,invalidate,require' %s 2>&1 \
119 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS
120 ; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Starting module pass manager
121 ; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module pass: No-op Analysis Requirement Pass
122 ; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis
123 ; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Invalidating module analysis: NoOpModuleAnalysis
124 ; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running module analysis: NoOpModuleAnalysis
125
126 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
127 ; RUN: -passes='cgscc(require,require,require)' %s 2>&1 \
128 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS
129 ; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Starting CGSCC pass manager
130 ; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running CGSCC pass: No-op Analysis Requirement Pass
131 ; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis
132 ; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS-NOT: Running CGSCC analysis: NoOpCGSCCAnalysis
133
134 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
135 ; RUN: -passes='cgscc(require,invalidate,require)' %s 2>&1 \
136 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS
137 ; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Starting CGSCC pass manager
138 ; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC pass: No-op Analysis Requirement Pass
139 ; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis
140 ; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Invalidating CGSCC analysis: NoOpCGSCCAnalysis
141 ; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running CGSCC analysis: NoOpCGSCCAnalysis
142
143 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
144 ; RUN: -passes='function(require,require,require)' %s 2>&1 \
145 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS
146 ; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Starting function pass manager
147 ; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running function pass: No-op Analysis Requirement Pass
148 ; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis
149 ; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS-NOT: Running function analysis: NoOpFunctionAnalysis
150
151 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
152 ; RUN: -passes='function(require,invalidate,require)' %s 2>&1 \
153 ; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS
154 ; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Starting function pass manager
155 ; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function pass: No-op Analysis Requirement Pass
156 ; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis
157 ; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Invalidating function analysis: NoOpFunctionAnalysis
158 ; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running function analysis: NoOpFunctionAnalysis
159
109160 define void @foo() {
110161 ret void
111162 }
104104 static bool isModulePassName(StringRef Name) {
105105 #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
106106 #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
107 if (Name == "require<" NAME ">") \
107 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
108108 return true;
109109 #include "PassRegistry.def"
110110
114114 static bool isCGSCCPassName(StringRef Name) {
115115 #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
116116 #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
117 if (Name == "require<" NAME ">") \
117 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
118118 return true;
119119 #include "PassRegistry.def"
120120
124124 static bool isFunctionPassName(StringRef Name) {
125125 #define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
126126 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
127 if (Name == "require<" NAME ">") \
127 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
128128 return true;
129129 #include "PassRegistry.def"
130130
141141 if (Name == "require<" NAME ">") { \
142142 MPM.addPass(NoopAnalysisRequirementPass()); \
143143 return true; \
144 } \
145 if (Name == "invalidate<" NAME ">") { \
146 MPM.addPass(NoopAnalysisInvalidationPass()); \
147 return true; \
144148 }
145149 #include "PassRegistry.def"
146150
157161 if (Name == "require<" NAME ">") { \
158162 CGPM.addPass(NoopAnalysisRequirementPass()); \
159163 return true; \
164 } \
165 if (Name == "invalidate<" NAME ">") { \
166 CGPM.addPass(NoopAnalysisInvalidationPass()); \
167 return true; \
160168 }
161169 #include "PassRegistry.def"
162170
172180 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
173181 if (Name == "require<" NAME ">") { \
174182 FPM.addPass(NoopAnalysisRequirementPass()); \
183 return true; \
184 } \
185 if (Name == "invalidate<" NAME ">") { \
186 FPM.addPass(NoopAnalysisInvalidationPass()); \
175187 return true; \
176188 }
177189 #include "PassRegistry.def"