1 //===- Standard pass instrumentations handling ----------------*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines IR-printing pass instrumentation callbacks as well as
11 /// StandardInstrumentations class that manages standard pass instrumentations.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Passes/StandardInstrumentations.h"
16 #include "llvm/ADT/Any.h"
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/Analysis/CallGraphSCCPass.h"
19 #include "llvm/Analysis/LazyCallGraph.h"
20 #include "llvm/Analysis/LoopInfo.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/IRPrintingPasses.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/IR/PassInstrumentation.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/FormatVariadic.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include <unordered_set>
30 #include <vector>
31 
32 using namespace llvm;
33 
34 // TODO: remove once all required passes are marked as such.
35 static cl::opt<bool>
36     EnableOptnone("enable-npm-optnone", cl::init(true),
37                   cl::desc("Enable skipping optional passes optnone functions "
38                            "under new pass manager"));
39 
40 cl::opt<bool> PreservedCFGCheckerInstrumentation::VerifyPreservedCFG(
41     "verify-cfg-preserved", cl::Hidden,
42 #ifdef NDEBUG
43     cl::init(false));
44 #else
45     cl::init(true));
46 #endif
47 
48 // FIXME: Change `-debug-pass-manager` from boolean to enum type. Similar to
49 // `-debug-pass` in legacy PM.
50 static cl::opt<bool>
51     DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false),
52                    cl::desc("Print all pass management debugging information. "
53                             "`-debug-pass-manager` must also be specified"));
54 
55 // An option that prints out the IR after passes, similar to
56 // -print-after-all except that it only prints the IR after passes that
57 // change the IR.  Those passes that do not make changes to the IR are
58 // reported as not making any changes.  In addition, the initial IR is
59 // also reported.  Other hidden options affect the output from this
60 // option.  -filter-passes will limit the output to the named passes
61 // that actually change the IR and other passes are reported as filtered out.
62 // The specified passes will either be reported as making no changes (with
63 // no IR reported) or the changed IR will be reported.  Also, the
64 // -filter-print-funcs and -print-module-scope options will do similar
65 // filtering based on function name, reporting changed IRs as functions(or
66 // modules if -print-module-scope is specified) for a particular function
67 // or indicating that the IR has been filtered out.  The extra options
68 // can be combined, allowing only changed IRs for certain passes on certain
69 // functions to be reported in different formats, with the rest being
70 // reported as filtered out.
71 static cl::opt<bool> PrintChanged("print-changed",
72                                   cl::desc("Print changed IRs"),
73                                   cl::init(false), cl::Hidden);
74 // An option that supports the -print-changed option.  See
75 // the description for -print-changed for an explanation of the use
76 // of this option.  Note that this option has no effect without -print-changed.
77 static cl::list<std::string>
78     PrintPassesList("filter-passes", cl::value_desc("pass names"),
79                     cl::desc("Only consider IR changes for passes whose names "
80                              "match for the print-changed option"),
81                     cl::CommaSeparated, cl::Hidden);
82 
83 namespace {
84 
85 /// Extracting Module out of \p IR unit. Also fills a textual description
86 /// of \p IR for use in header when printing.
87 Optional<std::pair<const Module *, std::string>>
88 unwrapModule(Any IR, bool Force = false) {
89   if (any_isa<const Module *>(IR))
90     return std::make_pair(any_cast<const Module *>(IR), std::string());
91 
92   if (any_isa<const Function *>(IR)) {
93     const Function *F = any_cast<const Function *>(IR);
94     if (!Force && !llvm::isFunctionInPrintList(F->getName()))
95       return None;
96 
97     const Module *M = F->getParent();
98     return std::make_pair(M, formatv(" (function: {0})", F->getName()).str());
99   }
100 
101   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
102     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
103     for (const LazyCallGraph::Node &N : *C) {
104       const Function &F = N.getFunction();
105       if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
106         const Module *M = F.getParent();
107         return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str());
108       }
109     }
110     assert(!Force && "Expected to have made a pair when forced.");
111     return None;
112   }
113 
114   if (any_isa<const Loop *>(IR)) {
115     const Loop *L = any_cast<const Loop *>(IR);
116     const Function *F = L->getHeader()->getParent();
117     if (!Force && !isFunctionInPrintList(F->getName()))
118       return None;
119     const Module *M = F->getParent();
120     std::string LoopName;
121     raw_string_ostream ss(LoopName);
122     L->getHeader()->printAsOperand(ss, false);
123     return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str());
124   }
125 
126   llvm_unreachable("Unknown IR unit");
127 }
128 
129 void printIR(raw_ostream &OS, const Function *F, StringRef Banner,
130              StringRef Extra = StringRef(), bool Brief = false) {
131   if (Brief) {
132     OS << F->getName() << '\n';
133     return;
134   }
135 
136   if (!llvm::isFunctionInPrintList(F->getName()))
137     return;
138   OS << Banner << Extra << "\n" << static_cast<const Value &>(*F);
139 }
140 
141 void printIR(raw_ostream &OS, const Module *M, StringRef Banner,
142              StringRef Extra = StringRef(), bool Brief = false,
143              bool ShouldPreserveUseListOrder = false) {
144   if (Brief) {
145     OS << M->getName() << '\n';
146     return;
147   }
148 
149   if (llvm::isFunctionInPrintList("*") || llvm::forcePrintModuleIR()) {
150     OS << Banner << Extra << "\n";
151     M->print(OS, nullptr, ShouldPreserveUseListOrder);
152   } else {
153     for (const auto &F : M->functions()) {
154       printIR(OS, &F, Banner, Extra);
155     }
156   }
157 }
158 
159 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C, StringRef Banner,
160              StringRef Extra = StringRef(), bool Brief = false) {
161   if (Brief) {
162     OS << *C << '\n';
163     return;
164   }
165 
166   bool BannerPrinted = false;
167   for (const LazyCallGraph::Node &N : *C) {
168     const Function &F = N.getFunction();
169     if (!F.isDeclaration() && llvm::isFunctionInPrintList(F.getName())) {
170       if (!BannerPrinted) {
171         OS << Banner << Extra << "\n";
172         BannerPrinted = true;
173       }
174       F.print(OS);
175     }
176   }
177 }
178 
179 void printIR(raw_ostream &OS, const Loop *L, StringRef Banner,
180              bool Brief = false) {
181   if (Brief) {
182     OS << *L;
183     return;
184   }
185 
186   const Function *F = L->getHeader()->getParent();
187   if (!llvm::isFunctionInPrintList(F->getName()))
188     return;
189   llvm::printLoop(const_cast<Loop &>(*L), OS, std::string(Banner));
190 }
191 
192 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
193 /// llvm::Any and does actual print job.
194 void unwrapAndPrint(raw_ostream &OS, Any IR, StringRef Banner,
195                     bool ForceModule = false, bool Brief = false,
196                     bool ShouldPreserveUseListOrder = false) {
197   if (ForceModule) {
198     if (auto UnwrappedModule = unwrapModule(IR))
199       printIR(OS, UnwrappedModule->first, Banner, UnwrappedModule->second,
200               Brief, ShouldPreserveUseListOrder);
201     return;
202   }
203 
204   if (any_isa<const Module *>(IR)) {
205     const Module *M = any_cast<const Module *>(IR);
206     assert(M && "module should be valid for printing");
207     printIR(OS, M, Banner, "", Brief, ShouldPreserveUseListOrder);
208     return;
209   }
210 
211   if (any_isa<const Function *>(IR)) {
212     const Function *F = any_cast<const Function *>(IR);
213     assert(F && "function should be valid for printing");
214     printIR(OS, F, Banner, "", Brief);
215     return;
216   }
217 
218   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
219     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
220     assert(C && "scc should be valid for printing");
221     std::string Extra = std::string(formatv(" (scc: {0})", C->getName()));
222     printIR(OS, C, Banner, Extra, Brief);
223     return;
224   }
225 
226   if (any_isa<const Loop *>(IR)) {
227     const Loop *L = any_cast<const Loop *>(IR);
228     assert(L && "Loop should be valid for printing");
229     printIR(OS, L, Banner, Brief);
230     return;
231   }
232   llvm_unreachable("Unknown wrapped IR type");
233 }
234 
235 // Return true when this is a pass for which changes should be ignored
236 inline bool isIgnored(StringRef PassID) {
237   return isSpecialPass(PassID,
238                        {"PassManager", "PassAdaptor", "AnalysisManagerProxy"});
239 }
240 
241 // Return true when this is a defined function for which printing
242 // of changes is desired.
243 inline bool isInterestingFunction(const Function &F) {
244   return llvm::isFunctionInPrintList(F.getName());
245 }
246 
247 // Return true when this is a pass for which printing of changes is desired.
248 inline bool isInterestingPass(StringRef PassID) {
249   if (isIgnored(PassID))
250     return false;
251 
252   static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
253                                                         PrintPassesList.end());
254   return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
255 }
256 
257 // Return true when this is a pass on IR for which printing
258 // of changes is desired.
259 bool isInteresting(Any IR, StringRef PassID) {
260   if (!isInterestingPass(PassID))
261     return false;
262   if (any_isa<const Function *>(IR))
263     return isInterestingFunction(*any_cast<const Function *>(IR));
264   return true;
265 }
266 
267 } // namespace
268 
269 template <typename IRUnitT>
270 void ChangePrinter<IRUnitT>::saveIRBeforePass(Any IR, StringRef PassID) {
271   // Always need to place something on the stack because invalidated passes
272   // are not given the IR so it cannot be determined whether the pass was for
273   // something that was filtered out.
274   BeforeStack.emplace_back();
275 
276   if (!isInteresting(IR, PassID))
277     return;
278   // Is this the initial IR?
279   if (InitialIR) {
280     InitialIR = false;
281     handleInitialIR(IR);
282   }
283 
284   // Save the IR representation on the stack.
285   IRUnitT &Data = BeforeStack.back();
286   generateIRRepresentation(IR, PassID, Data);
287 }
288 
289 template <typename IRUnitT>
290 void ChangePrinter<IRUnitT>::handleIRAfterPass(Any IR, StringRef PassID) {
291   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
292   std::string Name;
293 
294   // unwrapModule has inconsistent handling of names for function IRs.
295   if (any_isa<const Function *>(IR)) {
296     const Function *F = any_cast<const Function *>(IR);
297     Name = formatv(" (function: {0})", F->getName()).str();
298   } else {
299     if (auto UM = unwrapModule(IR))
300       Name = UM->second;
301   }
302   if (Name.empty())
303     Name = " (module)";
304 
305   if (isIgnored(PassID))
306     handleIgnored(PassID, Name);
307   else if (!isInteresting(IR, PassID))
308     handleFiltered(PassID, Name);
309   else {
310     // Get the before rep from the stack
311     IRUnitT &Before = BeforeStack.back();
312     // Create the after rep
313     IRUnitT After;
314     generateIRRepresentation(IR, PassID, After);
315 
316     // Was there a change in IR?
317     if (same(Before, After))
318       omitAfter(PassID, Name);
319     else
320       handleAfter(PassID, Name, Before, After, IR);
321   }
322   BeforeStack.pop_back();
323 }
324 
325 template <typename IRUnitT>
326 void ChangePrinter<IRUnitT>::handleInvalidatedPass(StringRef PassID) {
327   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
328 
329   // Always flag it as invalidated as we cannot determine when
330   // a pass for a filtered function is invalidated since we do not
331   // get the IR in the call.  Also, the output is just alternate
332   // forms of the banner anyway.
333   handleInvalidated(PassID);
334   BeforeStack.pop_back();
335 }
336 
337 template <typename IRUnitT> ChangePrinter<IRUnitT>::~ChangePrinter<IRUnitT>() {
338   assert(BeforeStack.empty() && "Problem with Change Printer stack.");
339 }
340 
341 IRChangePrinter::IRChangePrinter() : Out(dbgs()) {}
342 
343 IRChangePrinter::~IRChangePrinter() {}
344 
345 void IRChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
346   if (!PrintChanged)
347     return;
348 
349   PIC.registerBeforePassCallback([this](StringRef P, Any IR) {
350     saveIRBeforePass(IR, P);
351     return true;
352   });
353 
354   PIC.registerAfterPassCallback(
355       [this](StringRef P, Any IR, const PreservedAnalyses &) {
356         handleIRAfterPass(IR, P);
357       });
358   PIC.registerAfterPassInvalidatedCallback(
359       [this](StringRef P, const PreservedAnalyses &) {
360         handleInvalidatedPass(P);
361       });
362 }
363 
364 void IRChangePrinter::handleInitialIR(Any IR) {
365   // Always print the module.
366   // Unwrap and print directly to avoid filtering problems in general routines.
367   auto UnwrappedModule = unwrapModule(IR, /*Force=*/true);
368   assert(UnwrappedModule && "Expected module to be unwrapped when forced.");
369   Out << "*** IR Dump At Start: ***" << UnwrappedModule->second << "\n";
370   UnwrappedModule->first->print(Out, nullptr,
371                                 /*ShouldPreserveUseListOrder=*/true);
372 }
373 
374 void IRChangePrinter::generateIRRepresentation(Any IR, StringRef PassID,
375                                                std::string &Output) {
376   raw_string_ostream OS(Output);
377   // use the after banner for all cases so it will match
378   SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
379   unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR(),
380                  /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true);
381   OS.str();
382 }
383 
384 void IRChangePrinter::omitAfter(StringRef PassID, std::string &Name) {
385   Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n",
386                  PassID, Name);
387 }
388 
389 void IRChangePrinter::handleAfter(StringRef PassID, std::string &Name,
390                                   const std::string &Before,
391                                   const std::string &After, Any) {
392   assert(After.find("*** IR Dump") == 0 && "Unexpected banner format.");
393   StringRef AfterRef = After;
394   StringRef Banner =
395       AfterRef.take_until([](char C) -> bool { return C == '\n'; });
396   Out << Banner;
397 
398   // LazyCallGraph::SCC already has "(scc:..." in banner so only add
399   // in the name if it isn't already there.
400   if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR())
401     Out << Name;
402 
403   Out << After.substr(Banner.size());
404 }
405 
406 void IRChangePrinter::handleInvalidated(StringRef PassID) {
407   Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
408 }
409 
410 void IRChangePrinter::handleFiltered(StringRef PassID, std::string &Name) {
411   SmallString<20> Banner =
412       formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name);
413   Out << Banner;
414 }
415 
416 void IRChangePrinter::handleIgnored(StringRef PassID, std::string &Name) {
417   Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name);
418 }
419 
420 bool IRChangePrinter::same(const std::string &Before,
421                            const std::string &After) {
422   return Before == After;
423 }
424 
425 PrintIRInstrumentation::~PrintIRInstrumentation() {
426   assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
427 }
428 
429 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
430   assert(StoreModuleDesc);
431   const Module *M = nullptr;
432   std::string Extra;
433   if (auto UnwrappedModule = unwrapModule(IR))
434     std::tie(M, Extra) = UnwrappedModule.getValue();
435   ModuleDescStack.emplace_back(M, Extra, PassID);
436 }
437 
438 PrintIRInstrumentation::PrintModuleDesc
439 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
440   assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
441   PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
442   assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
443   return ModuleDesc;
444 }
445 
446 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
447   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
448     return;
449 
450   // Saving Module for AfterPassInvalidated operations.
451   // Note: here we rely on a fact that we do not change modules while
452   // traversing the pipeline, so the latest captured module is good
453   // for all print operations that has not happen yet.
454   if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID))
455     pushModuleDesc(PassID, IR);
456 
457   if (!llvm::shouldPrintBeforePass(PassID))
458     return;
459 
460   SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
461   unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR());
462   return;
463 }
464 
465 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
466   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
467     return;
468 
469   if (!llvm::shouldPrintAfterPass(PassID))
470     return;
471 
472   if (StoreModuleDesc)
473     popModuleDesc(PassID);
474 
475   SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
476   unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR());
477 }
478 
479 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
480   if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID))
481     return;
482 
483   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
484     return;
485 
486   const Module *M;
487   std::string Extra;
488   StringRef StoredPassID;
489   std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
490   // Additional filtering (e.g. -filter-print-func) can lead to module
491   // printing being skipped.
492   if (!M)
493     return;
494 
495   SmallString<20> Banner =
496       formatv("*** IR Dump After {0} *** invalidated: ", PassID);
497   printIR(dbgs(), M, Banner, Extra);
498 }
499 
500 void PrintIRInstrumentation::registerCallbacks(
501     PassInstrumentationCallbacks &PIC) {
502   // BeforePass callback is not just for printing, it also saves a Module
503   // for later use in AfterPassInvalidated.
504   StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass();
505   if (llvm::shouldPrintBeforePass() || StoreModuleDesc)
506     PIC.registerBeforeNonSkippedPassCallback(
507         [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
508 
509   if (llvm::shouldPrintAfterPass()) {
510     PIC.registerAfterPassCallback(
511         [this](StringRef P, Any IR, const PreservedAnalyses &) {
512           this->printAfterPass(P, IR);
513         });
514     PIC.registerAfterPassInvalidatedCallback(
515         [this](StringRef P, const PreservedAnalyses &) {
516           this->printAfterPassInvalidated(P);
517         });
518   }
519 }
520 
521 void OptNoneInstrumentation::registerCallbacks(
522     PassInstrumentationCallbacks &PIC) {
523   PIC.registerBeforePassCallback(
524       [this](StringRef P, Any IR) { return this->skip(P, IR); });
525 }
526 
527 bool OptNoneInstrumentation::skip(StringRef PassID, Any IR) {
528   if (!EnableOptnone)
529     return true;
530   const Function *F = nullptr;
531   if (any_isa<const Function *>(IR)) {
532     F = any_cast<const Function *>(IR);
533   } else if (any_isa<const Loop *>(IR)) {
534     F = any_cast<const Loop *>(IR)->getHeader()->getParent();
535   }
536   return !(F && F->hasOptNone());
537 }
538 
539 void PrintPassInstrumentation::registerCallbacks(
540     PassInstrumentationCallbacks &PIC) {
541   if (!DebugLogging)
542     return;
543 
544   std::vector<StringRef> SpecialPasses = {"PassManager"};
545   if (!DebugPMVerbose)
546     SpecialPasses.emplace_back("PassAdaptor");
547 
548   PIC.registerBeforeSkippedPassCallback(
549       [SpecialPasses](StringRef PassID, Any IR) {
550         assert(!isSpecialPass(PassID, SpecialPasses) &&
551                "Unexpectedly skipping special pass");
552 
553         dbgs() << "Skipping pass: " << PassID << " on ";
554         unwrapAndPrint(dbgs(), IR, "", false, true);
555       });
556 
557   PIC.registerBeforeNonSkippedPassCallback(
558       [SpecialPasses](StringRef PassID, Any IR) {
559         if (isSpecialPass(PassID, SpecialPasses))
560           return;
561 
562         dbgs() << "Running pass: " << PassID << " on ";
563         unwrapAndPrint(dbgs(), IR, "", false, true);
564       });
565 
566   PIC.registerBeforeAnalysisCallback([](StringRef PassID, Any IR) {
567     dbgs() << "Running analysis: " << PassID << " on ";
568     unwrapAndPrint(dbgs(), IR, "", false, true);
569   });
570 }
571 
572 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
573                                              bool TrackBBLifetime) {
574   if (TrackBBLifetime)
575     BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
576   for (const auto &BB : *F) {
577     if (BBGuards)
578       BBGuards->try_emplace(intptr_t(&BB), &BB);
579     for (auto *Succ : successors(&BB)) {
580       Graph[&BB][Succ]++;
581       if (BBGuards)
582         BBGuards->try_emplace(intptr_t(Succ), Succ);
583     }
584   }
585 }
586 
587 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
588   if (BB->hasName()) {
589     out << BB->getName() << "<" << BB << ">";
590     return;
591   }
592 
593   if (!BB->getParent()) {
594     out << "unnamed_removed<" << BB << ">";
595     return;
596   }
597 
598   if (BB == &BB->getParent()->getEntryBlock()) {
599     out << "entry"
600         << "<" << BB << ">";
601     return;
602   }
603 
604   unsigned FuncOrderBlockNum = 0;
605   for (auto &FuncBB : *BB->getParent()) {
606     if (&FuncBB == BB)
607       break;
608     FuncOrderBlockNum++;
609   }
610   out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
611 }
612 
613 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
614                                                         const CFG &Before,
615                                                         const CFG &After) {
616   assert(!After.isPoisoned());
617 
618   // Print function name.
619   const CFG *FuncGraph = nullptr;
620   if (!After.Graph.empty())
621     FuncGraph = &After;
622   else if (!Before.isPoisoned() && !Before.Graph.empty())
623     FuncGraph = &Before;
624 
625   if (FuncGraph)
626     out << "In function @"
627         << FuncGraph->Graph.begin()->first->getParent()->getName() << "\n";
628 
629   if (Before.isPoisoned()) {
630     out << "Some blocks were deleted\n";
631     return;
632   }
633 
634   // Find and print graph differences.
635   if (Before.Graph.size() != After.Graph.size())
636     out << "Different number of non-leaf basic blocks: before="
637         << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
638 
639   for (auto &BB : Before.Graph) {
640     auto BA = After.Graph.find(BB.first);
641     if (BA == After.Graph.end()) {
642       out << "Non-leaf block ";
643       printBBName(out, BB.first);
644       out << " is removed (" << BB.second.size() << " successors)\n";
645     }
646   }
647 
648   for (auto &BA : After.Graph) {
649     auto BB = Before.Graph.find(BA.first);
650     if (BB == Before.Graph.end()) {
651       out << "Non-leaf block ";
652       printBBName(out, BA.first);
653       out << " is added (" << BA.second.size() << " successors)\n";
654       continue;
655     }
656 
657     if (BB->second == BA.second)
658       continue;
659 
660     out << "Different successors of block ";
661     printBBName(out, BA.first);
662     out << " (unordered):\n";
663     out << "- before (" << BB->second.size() << "): ";
664     for (auto &SuccB : BB->second) {
665       printBBName(out, SuccB.first);
666       if (SuccB.second != 1)
667         out << "(" << SuccB.second << "), ";
668       else
669         out << ", ";
670     }
671     out << "\n";
672     out << "- after (" << BA.second.size() << "): ";
673     for (auto &SuccA : BA.second) {
674       printBBName(out, SuccA.first);
675       if (SuccA.second != 1)
676         out << "(" << SuccA.second << "), ";
677       else
678         out << ", ";
679     }
680     out << "\n";
681   }
682 }
683 
684 void PreservedCFGCheckerInstrumentation::registerCallbacks(
685     PassInstrumentationCallbacks &PIC) {
686   if (!VerifyPreservedCFG)
687     return;
688 
689   PIC.registerBeforeNonSkippedPassCallback([this](StringRef P, Any IR) {
690     if (any_isa<const Function *>(IR))
691       GraphStackBefore.emplace_back(P, CFG(any_cast<const Function *>(IR)));
692     else
693       GraphStackBefore.emplace_back(P, None);
694   });
695 
696   PIC.registerAfterPassInvalidatedCallback(
697       [this](StringRef P, const PreservedAnalyses &PassPA) {
698         auto Before = GraphStackBefore.pop_back_val();
699         assert(Before.first == P &&
700                "Before and After callbacks must correspond");
701         (void)Before;
702       });
703 
704   PIC.registerAfterPassCallback([this](StringRef P, Any IR,
705                                        const PreservedAnalyses &PassPA) {
706     auto Before = GraphStackBefore.pop_back_val();
707     assert(Before.first == P && "Before and After callbacks must correspond");
708     auto &GraphBefore = Before.second;
709 
710     if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>())
711       return;
712 
713     if (any_isa<const Function *>(IR)) {
714       assert(GraphBefore && "Must be built in BeforePassCallback");
715       CFG GraphAfter(any_cast<const Function *>(IR), false /* NeedsGuard */);
716       if (GraphAfter == *GraphBefore)
717         return;
718 
719       dbgs() << "Error: " << P
720              << " reported it preserved CFG, but changes detected:\n";
721       CFG::printDiff(dbgs(), *GraphBefore, GraphAfter);
722       report_fatal_error(Twine("Preserved CFG changed by ", P));
723     }
724   });
725 }
726 
727 void StandardInstrumentations::registerCallbacks(
728     PassInstrumentationCallbacks &PIC) {
729   PrintIR.registerCallbacks(PIC);
730   PrintPass.registerCallbacks(PIC);
731   TimePasses.registerCallbacks(PIC);
732   OptNone.registerCallbacks(PIC);
733   PreservedCFGChecker.registerCallbacks(PIC);
734   PrintChangedIR.registerCallbacks(PIC);
735 }
736