llvm.org GIT mirror llvm / 77e1655
[PM] Improve the debugging and logging facilities of the CGSCC bits of the new pass manager. This adds operator<< overloads for the various bits of the LazyCallGraph, dump methods for use from the debugger, and debug logging using them to the CGSCC pass manager. Having this was essential for debugging the call graph update patch, and I've extracted what I could from that patch here to minimize the delta. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273961 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 4 years ago
5 changed file(s) with 127 addition(s) and 41 deletion(s). Raw diff Collapse all Expand all
6666 class ModuleToPostOrderCGSCCPassAdaptor
6767 : public PassInfoMixin> {
6868 public:
69 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
70 : Pass(std::move(Pass)) {}
69 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false)
70 : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
7171 // We have to explicitly define all the special member functions because MSVC
7272 // refuses to generate them.
7373 ModuleToPostOrderCGSCCPassAdaptor(
7474 const ModuleToPostOrderCGSCCPassAdaptor &Arg)
75 : Pass(Arg.Pass) {}
75 : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
7676 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
77 : Pass(std::move(Arg.Pass)) {}
77 : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
7878 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
7979 ModuleToPostOrderCGSCCPassAdaptor &RHS) {
8080 using std::swap;
8181 swap(LHS.Pass, RHS.Pass);
82 swap(LHS.DebugLogging, RHS.DebugLogging);
8283 }
8384 ModuleToPostOrderCGSCCPassAdaptor &
8485 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
9697 LazyCallGraph &CG = AM.getResult(M);
9798
9899 PreservedAnalyses PA = PreservedAnalyses::all();
99 for (LazyCallGraph::RefSCC &OuterC : CG.postorder_ref_sccs())
100 for (LazyCallGraph::SCC &C : OuterC) {
100 for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
101 if (DebugLogging)
102 dbgs() << "Running an SCC pass across the RefSCC: " << RC << "\n";
103
104 for (LazyCallGraph::SCC &C : RC) {
101105 PreservedAnalyses PassPA = Pass.run(C, CGAM);
102106
103107 // We know that the CGSCC pass couldn't have invalidated any other
114118 // analyses will eventually occur when the module pass completes.
115119 PA.intersect(std::move(PassPA));
116120 }
121 }
117122
118123 // By definition we preserve the proxy. This precludes *any* invalidation
119124 // of CGSCC analyses by the proxy, but that's OK because we've taken
125130
126131 private:
127132 CGSCCPassT Pass;
133 bool DebugLogging;
128134 };
129135
130136 /// \brief A function to deduce a function pass type and wrap it in the
131137 /// templated adaptor.
132138 template
133139 ModuleToPostOrderCGSCCPassAdaptor
134 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
135 return ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass));
140 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false) {
141 return ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass), DebugLogging);
136142 }
137143
138144 extern template class InnerAnalysisManagerProxy
158164 class CGSCCToFunctionPassAdaptor
159165 : public PassInfoMixin> {
160166 public:
161 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
162 : Pass(std::move(Pass)) {}
167 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false)
168 : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
163169 // We have to explicitly define all the special member functions because MSVC
164170 // refuses to generate them.
165171 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
166 : Pass(Arg.Pass) {}
172 : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
167173 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
168 : Pass(std::move(Arg.Pass)) {}
174 : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
169175 friend void swap(CGSCCToFunctionPassAdaptor &LHS,
170176 CGSCCToFunctionPassAdaptor &RHS) {
171177 using std::swap;
172178 swap(LHS.Pass, RHS.Pass);
179 swap(LHS.DebugLogging, RHS.DebugLogging);
173180 }
174181 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
175182 swap(*this, RHS);
181188 // Setup the function analysis manager from its proxy.
182189 FunctionAnalysisManager &FAM =
183190 AM.getResult(C).getManager();
191
192 if (DebugLogging)
193 dbgs() << "Running function passes across an SCC: " << C << "\n";
184194
185195 PreservedAnalyses PA = PreservedAnalyses::all();
186196 for (LazyCallGraph::Node &N : C) {
210220
211221 private:
212222 FunctionPassT Pass;
223 bool DebugLogging;
213224 };
214225
215226 /// \brief A function to deduce a function pass type and wrap it in the
216227 /// templated adaptor.
217228 template
218229 CGSCCToFunctionPassAdaptor
219 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
220 return CGSCCToFunctionPassAdaptor(std::move(Pass));
230 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false) {
231 return CGSCCToFunctionPassAdaptor(std::move(Pass),
232 DebugLogging);
221233 }
222234 }
223235
4747 #include "llvm/IR/Module.h"
4848 #include "llvm/IR/PassManager.h"
4949 #include "llvm/Support/Allocator.h"
50 #include "llvm/Support/raw_ostream.h"
5051 #include
5152 #include
5253
221222 /// Internal helper to remove the edge to the given function.
222223 void removeEdgeInternal(Function &ChildF);
223224
225 /// Print the name of this node's function.
226 friend raw_ostream &operator<<(raw_ostream &OS, const Node &N);
227
228 /// Dump the name of this node's function to stderr.
229 void dump() const;
230
224231 public:
225232 LazyCallGraph &getGraph() const { return *G; }
226233
352359 Nodes.clear();
353360 }
354361
362 /// Print a short descrtiption useful for debugging or logging.
363 ///
364 /// We print the function names in the SCC wrapped in '()'s and skipping
365 /// the middle functions if there are a large number.
366 friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C);
367
368 /// Dump a short description of this SCC to stderr.
369 void dump() const;
370
355371 #ifndef NDEBUG
356372 /// Verify invariants about the SCC.
357373 ///
372388
373389 RefSCC &getOuterRefSCC() const { return *OuterRefSCC; }
374390
375 /// Short name useful for debugging or logging.
376 ///
377 /// We use the name of the first function in the SCC to name the SCC for
378 /// the purposes of debugging and logging.
391 /// Provide a short name by printing this SCC to a std::string.
392 ///
393 /// This copes with the fact that we don't have a name per-se for an SCC
394 /// while still making the use of this in debugging and logging useful.
379395 std::string getName() const {
380396 std::string Name;
381 int i = 0;
382 for (Node &N : *this) {
383 if (i > 0)
384 Name += ", ";
385 // Elide the inner elements if there are too many.
386 if (i > 8) {
387 Name += "..., ";
388 Name += Nodes.back()->getFunction().getName().str();
389 break;
390 }
391 Name += N.getFunction().getName().str();
392 ++i;
393 }
397 raw_string_ostream OS(Name);
398 OS << *this;
399 OS.flush();
394400 return Name;
395401 }
396402 };
425431 /// formRefSCCFast on the graph itself.
426432 RefSCC(LazyCallGraph &G);
427433
434 /// Print a short description useful for debugging or logging.
435 ///
436 /// We print the SCCs wrapped in '[]'s and skipping the middle SCCs if
437 /// there are a large number.
438 friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC);
439
440 /// Dump a short description of this RefSCC to stderr.
441 void dump() const;
442
428443 #ifndef NDEBUG
429444 /// Verify invariants about the RefSCC and all its SCCs.
430445 ///
476491 /// Test if this RefSCC is a descendant of \a C.
477492 bool isDescendantOf(const RefSCC &C) const;
478493
479 /// Short name useful for debugging or logging.
480 ///
481 /// We use the name of the first function in the SCC to name the SCC for
482 /// the purposes of debugging and logging.
483 StringRef getName() const {
484 return begin()->begin()->getFunction().getName();
494 /// Provide a short name by printing this SCC to a std::string.
495 ///
496 /// This copes with the fact that we don't have a name per-se for an SCC
497 /// while still making the use of this in debugging and logging useful.
498 std::string getName() const {
499 std::string Name;
500 raw_string_ostream OS(Name);
501 OS << *this;
502 OS.flush();
503 return Name;
485504 }
486505
487506 ///@{
119119 EdgeIndexMap.erase(IndexMapI);
120120 }
121121
122 raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::Node &N) {
123 return OS << N.F.getName();
124 }
125
126 void LazyCallGraph::Node::dump() const {
127 dbgs() << *this << '\n';
128 }
129
122130 LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
123131 DEBUG(dbgs() << "Building CG for module: " << M.getModuleIdentifier()
124132 << "\n");
172180 return *this;
173181 }
174182
183 raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::SCC &C) {
184 OS << '(';
185 int i = 0;
186 for (LazyCallGraph::Node &N : C) {
187 if (i > 0)
188 OS << ", ";
189 // Elide the inner elements if there are too many.
190 if (i > 8) {
191 OS << "..., " << *C.Nodes.back();
192 break;
193 }
194 OS << N;
195 ++i;
196 }
197 OS << ')';
198 return OS;
199 }
200
201 void LazyCallGraph::SCC::dump() const {
202 dbgs() << *this << '\n';
203 }
204
175205 #ifndef NDEBUG
176206 void LazyCallGraph::SCC::verify() {
177207 assert(OuterRefSCC && "Can't have a null RefSCC!");
192222 #endif
193223
194224 LazyCallGraph::RefSCC::RefSCC(LazyCallGraph &G) : G(&G) {}
225
226 raw_ostream &llvm::operator<<(raw_ostream &OS,
227 const LazyCallGraph::RefSCC &RC) {
228 OS << '[';
229 int i = 0;
230 for (LazyCallGraph::SCC &C : RC) {
231 if (i > 0)
232 OS << ", ";
233 // Elide the inner elements if there are too many.
234 if (i > 4) {
235 OS << "..., " << *RC.SCCs.back();
236 break;
237 }
238 OS << C;
239 ++i;
240 }
241 OS << ']';
242 return OS;
243 }
244
245 void LazyCallGraph::RefSCC::dump() const {
246 dbgs() << *this << '\n';
247 }
195248
196249 #ifndef NDEBUG
197250 void LazyCallGraph::RefSCC::verify() {
560560 PipelineText = PipelineText.substr(1);
561561
562562 // Add the nested pass manager with the appropriate adaptor.
563 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
563 CGPM.addPass(
564 createCGSCCToFunctionPassAdaptor(std::move(NestedFPM), DebugLogging));
564565 } else {
565566 // Otherwise try to parse a pass name.
566567 size_t End = PipelineText.find_first_of(",)");
626627 PipelineText = PipelineText.substr(1);
627628
628629 // Add the nested pass manager with the appropriate adaptor.
629 MPM.addPass(
630 createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
630 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM),
631 DebugLogging));
631632 } else if (PipelineText.startswith("function(")) {
632633 FunctionPassManager NestedFPM(DebugLogging);
633634
688689 DebugLogging) ||
689690 !PipelineText.empty())
690691 return false;
691 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
692 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM), DebugLogging));
692693 return true;
693694 }
694695
2121 ; CHECK-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor
2222 ; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}>
2323 ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
24 ; CHECK-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)]
2425 ; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run
2526 ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass
2627 ; CHECK-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run