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 } // namespace
245 
246 template <typename IRUnitT>
247 ChangeReporter<IRUnitT>::~ChangeReporter<IRUnitT>() {
248   assert(BeforeStack.empty() && "Problem with Change Printer stack.");
249 }
250 
251 template <typename IRUnitT>
252 bool ChangeReporter<IRUnitT>::isInterestingFunction(const Function &F) {
253   return llvm::isFunctionInPrintList(F.getName());
254 }
255 
256 template <typename IRUnitT>
257 bool ChangeReporter<IRUnitT>::isInterestingPass(StringRef PassID) {
258   if (isIgnored(PassID))
259     return false;
260 
261   static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
262                                                         PrintPassesList.end());
263   return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
264 }
265 
266 // Return true when this is a pass on IR for which printing
267 // of changes is desired.
268 template <typename IRUnitT>
269 bool ChangeReporter<IRUnitT>::isInteresting(Any IR, StringRef PassID) {
270   if (!isInterestingPass(PassID))
271     return false;
272   if (any_isa<const Function *>(IR))
273     return isInterestingFunction(*any_cast<const Function *>(IR));
274   return true;
275 }
276 
277 template <typename IRUnitT>
278 void ChangeReporter<IRUnitT>::saveIRBeforePass(Any IR, StringRef PassID) {
279   // Always need to place something on the stack because invalidated passes
280   // are not given the IR so it cannot be determined whether the pass was for
281   // something that was filtered out.
282   BeforeStack.emplace_back();
283 
284   if (!isInteresting(IR, PassID))
285     return;
286   // Is this the initial IR?
287   if (InitialIR) {
288     InitialIR = false;
289     handleInitialIR(IR);
290   }
291 
292   // Save the IR representation on the stack.
293   IRUnitT &Data = BeforeStack.back();
294   generateIRRepresentation(IR, PassID, Data);
295 }
296 
297 template <typename IRUnitT>
298 void ChangeReporter<IRUnitT>::handleIRAfterPass(Any IR, StringRef PassID) {
299   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
300   std::string Name;
301 
302   // unwrapModule has inconsistent handling of names for function IRs.
303   if (any_isa<const Function *>(IR)) {
304     const Function *F = any_cast<const Function *>(IR);
305     Name = formatv(" (function: {0})", F->getName()).str();
306   } else {
307     if (auto UM = unwrapModule(IR))
308       Name = UM->second;
309   }
310   if (Name == "")
311     Name = " (module)";
312 
313   if (isIgnored(PassID))
314     handleIgnored(PassID, Name);
315   else if (!isInteresting(IR, PassID))
316     handleFiltered(PassID, Name);
317   else {
318     // Get the before rep from the stack
319     IRUnitT &Before = BeforeStack.back();
320     // Create the after rep
321     IRUnitT After;
322     generateIRRepresentation(IR, PassID, After);
323 
324     // Was there a change in IR?
325     if (same(Before, After))
326       omitAfter(PassID, Name);
327     else
328       handleAfter(PassID, Name, Before, After, IR);
329   }
330   BeforeStack.pop_back();
331 }
332 
333 template <typename IRUnitT>
334 void ChangeReporter<IRUnitT>::handleInvalidatedPass(StringRef PassID) {
335   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
336 
337   // Always flag it as invalidated as we cannot determine when
338   // a pass for a filtered function is invalidated since we do not
339   // get the IR in the call.  Also, the output is just alternate
340   // forms of the banner anyway.
341   handleInvalidated(PassID);
342   BeforeStack.pop_back();
343 }
344 
345 template <typename IRUnitT>
346 void ChangeReporter<IRUnitT>::registerRequiredCallbacks(
347     PassInstrumentationCallbacks &PIC) {
348   PIC.registerBeforeNonSkippedPassCallback(
349       [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); });
350 
351   PIC.registerAfterPassCallback(
352       [this](StringRef P, Any IR, const PreservedAnalyses &) {
353         handleIRAfterPass(IR, P);
354       });
355   PIC.registerAfterPassInvalidatedCallback(
356       [this](StringRef P, const PreservedAnalyses &) {
357         handleInvalidatedPass(P);
358       });
359 }
360 
361 template <typename IRUnitT>
362 TextChangeReporter<IRUnitT>::TextChangeReporter()
363     : ChangeReporter<IRUnitT>(), Out(dbgs()) {}
364 
365 template <typename IRUnitT>
366 void TextChangeReporter<IRUnitT>::handleInitialIR(Any IR) {
367   // Always print the module.
368   // Unwrap and print directly to avoid filtering problems in general routines.
369   auto UnwrappedModule = unwrapModule(IR, /*Force=*/true);
370   assert(UnwrappedModule && "Expected module to be unwrapped when forced.");
371   Out << "*** IR Dump At Start: ***" << UnwrappedModule->second << "\n";
372   UnwrappedModule->first->print(Out, nullptr,
373                                 /*ShouldPreserveUseListOrder=*/true);
374 }
375 
376 template <typename IRUnitT>
377 void TextChangeReporter<IRUnitT>::omitAfter(StringRef PassID,
378                                             std::string &Name) {
379   Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n",
380                  PassID, Name);
381 }
382 
383 template <typename IRUnitT>
384 void TextChangeReporter<IRUnitT>::handleInvalidated(StringRef PassID) {
385   Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
386 }
387 
388 template <typename IRUnitT>
389 void TextChangeReporter<IRUnitT>::handleFiltered(StringRef PassID,
390                                                  std::string &Name) {
391   SmallString<20> Banner =
392       formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name);
393   Out << Banner;
394 }
395 
396 template <typename IRUnitT>
397 void TextChangeReporter<IRUnitT>::handleIgnored(StringRef PassID,
398                                                 std::string &Name) {
399   Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name);
400 }
401 
402 IRChangedPrinter::~IRChangedPrinter() {}
403 
404 void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
405   if (PrintChanged)
406     TextChangeReporter<std::string>::registerRequiredCallbacks(PIC);
407 }
408 
409 void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID,
410                                                 std::string &Output) {
411   raw_string_ostream OS(Output);
412   // use the after banner for all cases so it will match
413   SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
414   unwrapAndPrint(OS, IR, Banner, forcePrintModuleIR(),
415                  /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true);
416 
417   OS.str();
418 }
419 
420 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
421                                    const std::string &Before,
422                                    const std::string &After, Any) {
423   assert(After.find("*** IR Dump") == 0 && "Unexpected banner format.");
424   StringRef AfterRef = After;
425   StringRef Banner =
426       AfterRef.take_until([](char C) -> bool { return C == '\n'; });
427 
428   // Report the IR before the changes when requested.
429   if (PrintChangedBefore) {
430     Out << "*** IR Dump Before" << Banner.substr(17);
431     // LazyCallGraph::SCC already has "(scc:..." in banner so only add
432     // in the name if it isn't already there.
433     if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR())
434       Out << Name;
435 
436     StringRef BeforeRef = Before;
437     Out << BeforeRef.substr(Banner.size());
438   }
439 
440   Out << Banner;
441 
442   // LazyCallGraph::SCC already has "(scc:..." in banner so only add
443   // in the name if it isn't already there.
444   if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR())
445     Out << Name;
446 
447   Out << After.substr(Banner.size());
448 }
449 
450 bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) {
451   return S1 == S2;
452 }
453 
454 PrintIRInstrumentation::~PrintIRInstrumentation() {
455   assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
456 }
457 
458 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
459   assert(StoreModuleDesc);
460   const Module *M = nullptr;
461   std::string Extra;
462   if (auto UnwrappedModule = unwrapModule(IR))
463     std::tie(M, Extra) = UnwrappedModule.getValue();
464   ModuleDescStack.emplace_back(M, Extra, PassID);
465 }
466 
467 PrintIRInstrumentation::PrintModuleDesc
468 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
469   assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
470   PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
471   assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
472   return ModuleDesc;
473 }
474 
475 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
476   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
477     return;
478 
479   // Saving Module for AfterPassInvalidated operations.
480   // Note: here we rely on a fact that we do not change modules while
481   // traversing the pipeline, so the latest captured module is good
482   // for all print operations that has not happen yet.
483   if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID))
484     pushModuleDesc(PassID, IR);
485 
486   if (!llvm::shouldPrintBeforePass(PassID))
487     return;
488 
489   SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
490   unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR());
491   return;
492 }
493 
494 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
495   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
496     return;
497 
498   if (!llvm::shouldPrintAfterPass(PassID))
499     return;
500 
501   if (StoreModuleDesc)
502     popModuleDesc(PassID);
503 
504   SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
505   unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR());
506 }
507 
508 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
509   if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID))
510     return;
511 
512   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
513     return;
514 
515   const Module *M;
516   std::string Extra;
517   StringRef StoredPassID;
518   std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
519   // Additional filtering (e.g. -filter-print-func) can lead to module
520   // printing being skipped.
521   if (!M)
522     return;
523 
524   SmallString<20> Banner =
525       formatv("*** IR Dump After {0} *** invalidated: ", PassID);
526   printIR(dbgs(), M, Banner, Extra);
527 }
528 
529 void PrintIRInstrumentation::registerCallbacks(
530     PassInstrumentationCallbacks &PIC) {
531   // BeforePass callback is not just for printing, it also saves a Module
532   // for later use in AfterPassInvalidated.
533   StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass();
534   if (llvm::shouldPrintBeforePass() || StoreModuleDesc)
535     PIC.registerBeforeNonSkippedPassCallback(
536         [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
537 
538   if (llvm::shouldPrintAfterPass()) {
539     PIC.registerAfterPassCallback(
540         [this](StringRef P, Any IR, const PreservedAnalyses &) {
541           this->printAfterPass(P, IR);
542         });
543     PIC.registerAfterPassInvalidatedCallback(
544         [this](StringRef P, const PreservedAnalyses &) {
545           this->printAfterPassInvalidated(P);
546         });
547   }
548 }
549 
550 void OptNoneInstrumentation::registerCallbacks(
551     PassInstrumentationCallbacks &PIC) {
552   PIC.registerShouldRunOptionalPassCallback(
553       [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
554 }
555 
556 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
557   const Function *F = nullptr;
558   if (any_isa<const Function *>(IR)) {
559     F = any_cast<const Function *>(IR);
560   } else if (any_isa<const Loop *>(IR)) {
561     F = any_cast<const Loop *>(IR)->getHeader()->getParent();
562   }
563   bool ShouldRun = !(F && F->hasOptNone());
564   if (!ShouldRun && DebugLogging) {
565     errs() << "Skipping pass " << PassID << " on " << F->getName()
566            << " due to optnone attribute\n";
567   }
568   return ShouldRun;
569 }
570 
571 static std::string getBisectDescription(Any IR) {
572   if (any_isa<const Module *>(IR)) {
573     const Module *M = any_cast<const Module *>(IR);
574     assert(M && "module should be valid for printing");
575     return "module (" + M->getName().str() + ")";
576   }
577 
578   if (any_isa<const Function *>(IR)) {
579     const Function *F = any_cast<const Function *>(IR);
580     assert(F && "function should be valid for printing");
581     return "function (" + F->getName().str() + ")";
582   }
583 
584   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
585     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
586     assert(C && "scc should be valid for printing");
587     return "SCC " + C->getName();
588   }
589 
590   if (any_isa<const Loop *>(IR)) {
591     return "loop";
592   }
593 
594   llvm_unreachable("Unknown wrapped IR type");
595 }
596 
597 void OptBisectInstrumentation::registerCallbacks(
598     PassInstrumentationCallbacks &PIC) {
599   if (!isEnabled())
600     return;
601 
602   std::vector<StringRef> SpecialPasses = {"PassManager", "PassAdaptor"};
603 
604   PIC.registerShouldRunOptionalPassCallback(
605       [this, SpecialPasses](StringRef PassID, Any IR) {
606         return isSpecialPass(PassID, SpecialPasses) ||
607                checkPass(PassID, getBisectDescription(IR));
608       });
609 }
610 
611 void PrintPassInstrumentation::registerCallbacks(
612     PassInstrumentationCallbacks &PIC) {
613   if (!DebugLogging)
614     return;
615 
616   std::vector<StringRef> SpecialPasses = {"PassManager"};
617   if (!DebugPMVerbose)
618     SpecialPasses.emplace_back("PassAdaptor");
619 
620   PIC.registerBeforeSkippedPassCallback(
621       [SpecialPasses](StringRef PassID, Any IR) {
622         assert(!isSpecialPass(PassID, SpecialPasses) &&
623                "Unexpectedly skipping special pass");
624 
625         dbgs() << "Skipping pass: " << PassID << " on ";
626         unwrapAndPrint(dbgs(), IR, "", false, true);
627       });
628 
629   PIC.registerBeforeNonSkippedPassCallback(
630       [SpecialPasses](StringRef PassID, Any IR) {
631         if (isSpecialPass(PassID, SpecialPasses))
632           return;
633 
634         dbgs() << "Running pass: " << PassID << " on ";
635         unwrapAndPrint(dbgs(), IR, "", false, true);
636       });
637 
638   PIC.registerBeforeAnalysisCallback([](StringRef PassID, Any IR) {
639     dbgs() << "Running analysis: " << PassID << " on ";
640     unwrapAndPrint(dbgs(), IR, "", false, true);
641   });
642 }
643 
644 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
645                                              bool TrackBBLifetime) {
646   if (TrackBBLifetime)
647     BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
648   for (const auto &BB : *F) {
649     if (BBGuards)
650       BBGuards->try_emplace(intptr_t(&BB), &BB);
651     for (auto *Succ : successors(&BB)) {
652       Graph[&BB][Succ]++;
653       if (BBGuards)
654         BBGuards->try_emplace(intptr_t(Succ), Succ);
655     }
656   }
657 }
658 
659 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
660   if (BB->hasName()) {
661     out << BB->getName() << "<" << BB << ">";
662     return;
663   }
664 
665   if (!BB->getParent()) {
666     out << "unnamed_removed<" << BB << ">";
667     return;
668   }
669 
670   if (BB == &BB->getParent()->getEntryBlock()) {
671     out << "entry"
672         << "<" << BB << ">";
673     return;
674   }
675 
676   unsigned FuncOrderBlockNum = 0;
677   for (auto &FuncBB : *BB->getParent()) {
678     if (&FuncBB == BB)
679       break;
680     FuncOrderBlockNum++;
681   }
682   out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
683 }
684 
685 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
686                                                         const CFG &Before,
687                                                         const CFG &After) {
688   assert(!After.isPoisoned());
689 
690   // Print function name.
691   const CFG *FuncGraph = nullptr;
692   if (!After.Graph.empty())
693     FuncGraph = &After;
694   else if (!Before.isPoisoned() && !Before.Graph.empty())
695     FuncGraph = &Before;
696 
697   if (FuncGraph)
698     out << "In function @"
699         << FuncGraph->Graph.begin()->first->getParent()->getName() << "\n";
700 
701   if (Before.isPoisoned()) {
702     out << "Some blocks were deleted\n";
703     return;
704   }
705 
706   // Find and print graph differences.
707   if (Before.Graph.size() != After.Graph.size())
708     out << "Different number of non-leaf basic blocks: before="
709         << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
710 
711   for (auto &BB : Before.Graph) {
712     auto BA = After.Graph.find(BB.first);
713     if (BA == After.Graph.end()) {
714       out << "Non-leaf block ";
715       printBBName(out, BB.first);
716       out << " is removed (" << BB.second.size() << " successors)\n";
717     }
718   }
719 
720   for (auto &BA : After.Graph) {
721     auto BB = Before.Graph.find(BA.first);
722     if (BB == Before.Graph.end()) {
723       out << "Non-leaf block ";
724       printBBName(out, BA.first);
725       out << " is added (" << BA.second.size() << " successors)\n";
726       continue;
727     }
728 
729     if (BB->second == BA.second)
730       continue;
731 
732     out << "Different successors of block ";
733     printBBName(out, BA.first);
734     out << " (unordered):\n";
735     out << "- before (" << BB->second.size() << "): ";
736     for (auto &SuccB : BB->second) {
737       printBBName(out, SuccB.first);
738       if (SuccB.second != 1)
739         out << "(" << SuccB.second << "), ";
740       else
741         out << ", ";
742     }
743     out << "\n";
744     out << "- after (" << BA.second.size() << "): ";
745     for (auto &SuccA : BA.second) {
746       printBBName(out, SuccA.first);
747       if (SuccA.second != 1)
748         out << "(" << SuccA.second << "), ";
749       else
750         out << ", ";
751     }
752     out << "\n";
753   }
754 }
755 
756 void PreservedCFGCheckerInstrumentation::registerCallbacks(
757     PassInstrumentationCallbacks &PIC) {
758   if (!VerifyPreservedCFG)
759     return;
760 
761   PIC.registerBeforeNonSkippedPassCallback([this](StringRef P, Any IR) {
762     if (any_isa<const Function *>(IR))
763       GraphStackBefore.emplace_back(P, CFG(any_cast<const Function *>(IR)));
764     else
765       GraphStackBefore.emplace_back(P, None);
766   });
767 
768   PIC.registerAfterPassInvalidatedCallback(
769       [this](StringRef P, const PreservedAnalyses &PassPA) {
770         auto Before = GraphStackBefore.pop_back_val();
771         assert(Before.first == P &&
772                "Before and After callbacks must correspond");
773         (void)Before;
774       });
775 
776   PIC.registerAfterPassCallback([this](StringRef P, Any IR,
777                                        const PreservedAnalyses &PassPA) {
778     auto Before = GraphStackBefore.pop_back_val();
779     assert(Before.first == P && "Before and After callbacks must correspond");
780     auto &GraphBefore = Before.second;
781 
782     if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>())
783       return;
784 
785     if (any_isa<const Function *>(IR)) {
786       assert(GraphBefore && "Must be built in BeforePassCallback");
787       CFG GraphAfter(any_cast<const Function *>(IR), false /* NeedsGuard */);
788       if (GraphAfter == *GraphBefore)
789         return;
790 
791       dbgs() << "Error: " << P
792              << " reported it preserved CFG, but changes detected:\n";
793       CFG::printDiff(dbgs(), *GraphBefore, GraphAfter);
794       report_fatal_error(Twine("Preserved CFG changed by ", P));
795     }
796   });
797 }
798 
799 void VerifyInstrumentation::registerCallbacks(
800     PassInstrumentationCallbacks &PIC) {
801   PIC.registerAfterPassCallback(
802       [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
803         if (isIgnored(P) || P == "VerifierPass")
804           return;
805         if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
806           const Function *F;
807           if (any_isa<const Loop *>(IR))
808             F = any_cast<const Loop *>(IR)->getHeader()->getParent();
809           else
810             F = any_cast<const Function *>(IR);
811           if (DebugLogging)
812             dbgs() << "Verifying function " << F->getName() << "\n";
813 
814           if (verifyFunction(*F))
815             report_fatal_error("Broken function found, compilation aborted!");
816         } else if (any_isa<const Module *>(IR) ||
817                    any_isa<const LazyCallGraph::SCC *>(IR)) {
818           const Module *M;
819           if (any_isa<const LazyCallGraph::SCC *>(IR))
820             M = any_cast<const LazyCallGraph::SCC *>(IR)
821                     ->begin()
822                     ->getFunction()
823                     .getParent();
824           else
825             M = any_cast<const Module *>(IR);
826           if (DebugLogging)
827             dbgs() << "Verifying module " << M->getName() << "\n";
828 
829           if (verifyModule(*M))
830             report_fatal_error("Broken module found, compilation aborted!");
831         }
832       });
833 }
834 
835 void StandardInstrumentations::registerCallbacks(
836     PassInstrumentationCallbacks &PIC) {
837   PrintIR.registerCallbacks(PIC);
838   PrintPass.registerCallbacks(PIC);
839   TimePasses.registerCallbacks(PIC);
840   OptNone.registerCallbacks(PIC);
841   OptBisect.registerCallbacks(PIC);
842   PreservedCFGChecker.registerCallbacks(PIC);
843   PrintChangedIR.registerCallbacks(PIC);
844   if (VerifyEach)
845     Verify.registerCallbacks(PIC);
846 }
847 
848 namespace llvm {
849 
850 template class ChangeReporter<std::string>;
851 template class TextChangeReporter<std::string>;
852 
853 } // namespace llvm
854