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