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