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