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/LegacyPassManager.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/IR/PassInstrumentation.h"
26 #include "llvm/IR/PassManager.h"
27 #include "llvm/IR/PrintPasses.h"
28 #include "llvm/IR/Verifier.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/FormatVariadic.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/Program.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <unordered_set>
36 #include <vector>
37 
38 using namespace llvm;
39 
40 cl::opt<bool> PreservedCFGCheckerInstrumentation::VerifyPreservedCFG(
41     "verify-cfg-preserved", cl::Hidden,
42 #ifdef NDEBUG
43     cl::init(false));
44 #else
45     cl::init(true));
46 #endif
47 
48 // FIXME: Change `-debug-pass-manager` from boolean to enum type. Similar to
49 // `-debug-pass` in legacy PM.
50 static cl::opt<bool>
51     DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false),
52                    cl::desc("Print all pass management debugging information. "
53                             "`-debug-pass-manager` must also be specified"));
54 
55 static cl::opt<bool>
56     DebugPassStructure("debug-pass-structure", cl::Hidden, cl::init(false),
57                        cl::desc("Print pass structure information."));
58 
59 // An option that prints out the IR after passes, similar to
60 // -print-after-all except that it only prints the IR after passes that
61 // change the IR.  Those passes that do not make changes to the IR are
62 // reported as not making any changes.  In addition, the initial IR is
63 // also reported.  Other hidden options affect the output from this
64 // option.  -filter-passes will limit the output to the named passes
65 // that actually change the IR and other passes are reported as filtered out.
66 // The specified passes will either be reported as making no changes (with
67 // no IR reported) or the changed IR will be reported.  Also, the
68 // -filter-print-funcs and -print-module-scope options will do similar
69 // filtering based on function name, reporting changed IRs as functions(or
70 // modules if -print-module-scope is specified) for a particular function
71 // or indicating that the IR has been filtered out.  The extra options
72 // can be combined, allowing only changed IRs for certain passes on certain
73 // functions to be reported in different formats, with the rest being
74 // reported as filtered out.  The -print-before-changed option will print
75 // the IR as it was before each pass that changed it.  The optional
76 // value of quiet will only report when the IR changes, suppressing
77 // all other messages, including the initial IR.  The values "diff" and
78 // "diff-quiet" will present the changes in a form similar to a patch, in
79 // either verbose or quiet mode, respectively.  The lines that are removed
80 // and added are prefixed with '-' and '+', respectively.  The
81 // -filter-print-funcs and -filter-passes can be used to filter the output.
82 // This reporter relies on the linux diff utility to do comparisons and
83 // insert the prefixes.  For systems that do not have the necessary
84 // facilities, the error message will be shown in place of the expected output.
85 //
86 enum class ChangePrinter {
87   NoChangePrinter,
88   PrintChangedVerbose,
89   PrintChangedQuiet,
90   PrintChangedDiffVerbose,
91   PrintChangedDiffQuiet,
92   PrintChangedColourDiffVerbose,
93   PrintChangedColourDiffQuiet
94 };
95 static cl::opt<ChangePrinter> PrintChanged(
96     "print-changed", cl::desc("Print changed IRs"), cl::Hidden,
97     cl::ValueOptional, cl::init(ChangePrinter::NoChangePrinter),
98     cl::values(
99         clEnumValN(ChangePrinter::PrintChangedQuiet, "quiet",
100                    "Run in quiet mode"),
101         clEnumValN(ChangePrinter::PrintChangedDiffVerbose, "diff",
102                    "Display patch-like changes"),
103         clEnumValN(ChangePrinter::PrintChangedDiffQuiet, "diff-quiet",
104                    "Display patch-like changes in quiet mode"),
105         clEnumValN(ChangePrinter::PrintChangedColourDiffVerbose, "cdiff",
106                    "Display patch-like changes with color"),
107         clEnumValN(ChangePrinter::PrintChangedColourDiffQuiet, "cdiff-quiet",
108                    "Display patch-like changes in quiet mode with color"),
109         // Sentinel value for unspecified option.
110         clEnumValN(ChangePrinter::PrintChangedVerbose, "", "")));
111 
112 // An option that supports the -print-changed option.  See
113 // the description for -print-changed for an explanation of the use
114 // of this option.  Note that this option has no effect without -print-changed.
115 static cl::list<std::string>
116     PrintPassesList("filter-passes", cl::value_desc("pass names"),
117                     cl::desc("Only consider IR changes for passes whose names "
118                              "match for the print-changed option"),
119                     cl::CommaSeparated, cl::Hidden);
120 // An option that supports the -print-changed option.  See
121 // the description for -print-changed for an explanation of the use
122 // of this option.  Note that this option has no effect without -print-changed.
123 static cl::opt<bool>
124     PrintChangedBefore("print-before-changed",
125                        cl::desc("Print before passes that change them"),
126                        cl::init(false), cl::Hidden);
127 
128 // An option for specifying the diff used by print-changed=[diff | diff-quiet]
129 static cl::opt<std::string>
130     DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
131                cl::desc("system diff used by change reporters"));
132 
133 namespace {
134 
135 // Perform a system based diff between \p Before and \p After, using
136 // \p OldLineFormat, \p NewLineFormat, and \p UnchangedLineFormat
137 // to control the formatting of the output.  Return an error message
138 // for any failures instead of the diff.
139 std::string doSystemDiff(StringRef Before, StringRef After,
140                          StringRef OldLineFormat, StringRef NewLineFormat,
141                          StringRef UnchangedLineFormat) {
142   StringRef SR[2]{Before, After};
143   // Store the 2 bodies into temporary files and call diff on them
144   // to get the body of the node.
145   const unsigned NumFiles = 3;
146   std::string FileName[NumFiles];
147   int FD[NumFiles]{-1, -1, -1};
148   for (unsigned I = 0; I < NumFiles; ++I) {
149     if (FD[I] == -1) {
150       SmallVector<char, 200> SV;
151       std::error_code EC =
152           sys::fs::createTemporaryFile("tmpdiff", "txt", FD[I], SV);
153       if (EC)
154         return "Unable to create temporary file.";
155       FileName[I] = Twine(SV).str();
156     }
157     // The third file is used as the result of the diff.
158     if (I == NumFiles - 1)
159       break;
160 
161     std::error_code EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
162     if (EC)
163       return "Unable to open temporary file for writing.";
164 
165     raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
166     if (FD[I] == -1)
167       return "Error opening file for writing.";
168     OutStream << SR[I];
169   }
170 
171   static ErrorOr<std::string> DiffExe = sys::findProgramByName(DiffBinary);
172   if (!DiffExe)
173     return "Unable to find diff executable.";
174 
175   SmallString<128> OLF = formatv("--old-line-format={0}", OldLineFormat);
176   SmallString<128> NLF = formatv("--new-line-format={0}", NewLineFormat);
177   SmallString<128> ULF =
178       formatv("--unchanged-line-format={0}", UnchangedLineFormat);
179 
180   StringRef Args[] = {"-w", "-d", OLF, NLF, ULF, FileName[0], FileName[1]};
181   Optional<StringRef> Redirects[] = {None, StringRef(FileName[2]), None};
182   int Result = sys::ExecuteAndWait(*DiffExe, Args, None, Redirects);
183   if (Result < 0)
184     return "Error executing system diff.";
185   std::string Diff;
186   auto B = MemoryBuffer::getFile(FileName[2]);
187   if (B && *B)
188     Diff = (*B)->getBuffer().str();
189   else
190     return "Unable to read result.";
191 
192   // Clean up.
193   for (unsigned I = 0; I < NumFiles; ++I) {
194     std::error_code EC = sys::fs::remove(FileName[I]);
195     if (EC)
196       return "Unable to remove temporary file.";
197   }
198   return Diff;
199 }
200 
201 /// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
202 /// certain global filters. Will never return nullptr if \p Force is true.
203 const Module *unwrapModule(Any IR, bool Force = false) {
204   if (any_isa<const Module *>(IR))
205     return any_cast<const Module *>(IR);
206 
207   if (any_isa<const Function *>(IR)) {
208     const Function *F = any_cast<const Function *>(IR);
209     if (!Force && !isFunctionInPrintList(F->getName()))
210       return nullptr;
211 
212     return F->getParent();
213   }
214 
215   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
216     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
217     for (const LazyCallGraph::Node &N : *C) {
218       const Function &F = N.getFunction();
219       if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
220         return F.getParent();
221       }
222     }
223     assert(!Force && "Expected a module");
224     return nullptr;
225   }
226 
227   if (any_isa<const Loop *>(IR)) {
228     const Loop *L = any_cast<const Loop *>(IR);
229     const Function *F = L->getHeader()->getParent();
230     if (!Force && !isFunctionInPrintList(F->getName()))
231       return nullptr;
232     return F->getParent();
233   }
234 
235   llvm_unreachable("Unknown IR unit");
236 }
237 
238 void printIR(raw_ostream &OS, const Function *F) {
239   if (!isFunctionInPrintList(F->getName()))
240     return;
241   OS << *F;
242 }
243 
244 void printIR(raw_ostream &OS, const Module *M,
245              bool ShouldPreserveUseListOrder = false) {
246   if (isFunctionInPrintList("*") || forcePrintModuleIR()) {
247     M->print(OS, nullptr, ShouldPreserveUseListOrder);
248   } else {
249     for (const auto &F : M->functions()) {
250       printIR(OS, &F);
251     }
252   }
253 }
254 
255 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C) {
256   for (const LazyCallGraph::Node &N : *C) {
257     const Function &F = N.getFunction();
258     if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
259       F.print(OS);
260     }
261   }
262 }
263 
264 void printIR(raw_ostream &OS, const Loop *L) {
265   const Function *F = L->getHeader()->getParent();
266   if (!isFunctionInPrintList(F->getName()))
267     return;
268   printLoop(const_cast<Loop &>(*L), OS);
269 }
270 
271 std::string getIRName(Any IR) {
272   if (any_isa<const Module *>(IR))
273     return "[module]";
274 
275   if (any_isa<const Function *>(IR)) {
276     const Function *F = any_cast<const Function *>(IR);
277     return F->getName().str();
278   }
279 
280   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
281     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
282     return C->getName();
283   }
284 
285   if (any_isa<const Loop *>(IR)) {
286     const Loop *L = any_cast<const Loop *>(IR);
287     std::string S;
288     raw_string_ostream OS(S);
289     L->print(OS, /*Verbose*/ false, /*PrintNested*/ false);
290     return OS.str();
291   }
292 
293   llvm_unreachable("Unknown wrapped IR type");
294 }
295 
296 bool moduleContainsFilterPrintFunc(const Module &M) {
297   return any_of(M.functions(),
298                 [](const Function &F) {
299                   return isFunctionInPrintList(F.getName());
300                 }) ||
301          isFunctionInPrintList("*");
302 }
303 
304 bool sccContainsFilterPrintFunc(const LazyCallGraph::SCC &C) {
305   return any_of(C,
306                 [](const LazyCallGraph::Node &N) {
307                   return isFunctionInPrintList(N.getName());
308                 }) ||
309          isFunctionInPrintList("*");
310 }
311 
312 bool shouldPrintIR(Any IR) {
313   if (any_isa<const Module *>(IR)) {
314     const Module *M = any_cast<const Module *>(IR);
315     return moduleContainsFilterPrintFunc(*M);
316   }
317 
318   if (any_isa<const Function *>(IR)) {
319     const Function *F = any_cast<const Function *>(IR);
320     return isFunctionInPrintList(F->getName());
321   }
322 
323   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
324     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
325     return sccContainsFilterPrintFunc(*C);
326   }
327 
328   if (any_isa<const Loop *>(IR)) {
329     const Loop *L = any_cast<const Loop *>(IR);
330     return isFunctionInPrintList(L->getHeader()->getParent()->getName());
331   }
332   llvm_unreachable("Unknown wrapped IR type");
333 }
334 
335 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
336 /// llvm::Any and does actual print job.
337 void unwrapAndPrint(raw_ostream &OS, Any IR,
338                     bool ShouldPreserveUseListOrder = false) {
339   if (!shouldPrintIR(IR))
340     return;
341 
342   if (forcePrintModuleIR()) {
343     auto *M = unwrapModule(IR);
344     assert(M && "should have unwrapped module");
345     printIR(OS, M, ShouldPreserveUseListOrder);
346     return;
347   }
348 
349   if (any_isa<const Module *>(IR)) {
350     const Module *M = any_cast<const Module *>(IR);
351     printIR(OS, M, ShouldPreserveUseListOrder);
352     return;
353   }
354 
355   if (any_isa<const Function *>(IR)) {
356     const Function *F = any_cast<const Function *>(IR);
357     printIR(OS, F);
358     return;
359   }
360 
361   if (any_isa<const LazyCallGraph::SCC *>(IR)) {
362     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
363     printIR(OS, C);
364     return;
365   }
366 
367   if (any_isa<const Loop *>(IR)) {
368     const Loop *L = any_cast<const Loop *>(IR);
369     printIR(OS, L);
370     return;
371   }
372   llvm_unreachable("Unknown wrapped IR type");
373 }
374 
375 // Return true when this is a pass for which changes should be ignored
376 bool isIgnored(StringRef PassID) {
377   return isSpecialPass(PassID,
378                        {"PassManager", "PassAdaptor", "AnalysisManagerProxy",
379                         "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass"});
380 }
381 
382 } // namespace
383 
384 template <typename IRUnitT>
385 ChangeReporter<IRUnitT>::~ChangeReporter<IRUnitT>() {
386   assert(BeforeStack.empty() && "Problem with Change Printer stack.");
387 }
388 
389 template <typename IRUnitT>
390 bool ChangeReporter<IRUnitT>::isInterestingFunction(const Function &F) {
391   return isFunctionInPrintList(F.getName());
392 }
393 
394 template <typename IRUnitT>
395 bool ChangeReporter<IRUnitT>::isInterestingPass(StringRef PassID) {
396   if (isIgnored(PassID))
397     return false;
398 
399   static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
400                                                         PrintPassesList.end());
401   return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
402 }
403 
404 // Return true when this is a pass on IR for which printing
405 // of changes is desired.
406 template <typename IRUnitT>
407 bool ChangeReporter<IRUnitT>::isInteresting(Any IR, StringRef PassID) {
408   if (!isInterestingPass(PassID))
409     return false;
410   if (any_isa<const Function *>(IR))
411     return isInterestingFunction(*any_cast<const Function *>(IR));
412   return true;
413 }
414 
415 template <typename IRUnitT>
416 void ChangeReporter<IRUnitT>::saveIRBeforePass(Any IR, StringRef PassID) {
417   // Always need to place something on the stack because invalidated passes
418   // are not given the IR so it cannot be determined whether the pass was for
419   // something that was filtered out.
420   BeforeStack.emplace_back();
421 
422   if (!isInteresting(IR, PassID))
423     return;
424   // Is this the initial IR?
425   if (InitialIR) {
426     InitialIR = false;
427     if (VerboseMode)
428       handleInitialIR(IR);
429   }
430 
431   // Save the IR representation on the stack.
432   IRUnitT &Data = BeforeStack.back();
433   generateIRRepresentation(IR, PassID, Data);
434 }
435 
436 template <typename IRUnitT>
437 void ChangeReporter<IRUnitT>::handleIRAfterPass(Any IR, StringRef PassID) {
438   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
439 
440   std::string Name = getIRName(IR);
441 
442   if (isIgnored(PassID)) {
443     if (VerboseMode)
444       handleIgnored(PassID, Name);
445   } else if (!isInteresting(IR, PassID)) {
446     if (VerboseMode)
447       handleFiltered(PassID, Name);
448   } else {
449     // Get the before rep from the stack
450     IRUnitT &Before = BeforeStack.back();
451     // Create the after rep
452     IRUnitT After;
453     generateIRRepresentation(IR, PassID, After);
454 
455     // Was there a change in IR?
456     if (same(Before, After)) {
457       if (VerboseMode)
458         omitAfter(PassID, Name);
459     } else
460       handleAfter(PassID, Name, Before, After, IR);
461   }
462   BeforeStack.pop_back();
463 }
464 
465 template <typename IRUnitT>
466 void ChangeReporter<IRUnitT>::handleInvalidatedPass(StringRef PassID) {
467   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
468 
469   // Always flag it as invalidated as we cannot determine when
470   // a pass for a filtered function is invalidated since we do not
471   // get the IR in the call.  Also, the output is just alternate
472   // forms of the banner anyway.
473   if (VerboseMode)
474     handleInvalidated(PassID);
475   BeforeStack.pop_back();
476 }
477 
478 template <typename IRUnitT>
479 void ChangeReporter<IRUnitT>::registerRequiredCallbacks(
480     PassInstrumentationCallbacks &PIC) {
481   PIC.registerBeforeNonSkippedPassCallback(
482       [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); });
483 
484   PIC.registerAfterPassCallback(
485       [this](StringRef P, Any IR, const PreservedAnalyses &) {
486         handleIRAfterPass(IR, P);
487       });
488   PIC.registerAfterPassInvalidatedCallback(
489       [this](StringRef P, const PreservedAnalyses &) {
490         handleInvalidatedPass(P);
491       });
492 }
493 
494 ChangedBlockData::ChangedBlockData(const BasicBlock &B)
495     : Label(B.getName().str()) {
496   raw_string_ostream SS(Body);
497   B.print(SS, nullptr, true, true);
498 }
499 
500 template <typename IRUnitT>
501 TextChangeReporter<IRUnitT>::TextChangeReporter(bool Verbose)
502     : ChangeReporter<IRUnitT>(Verbose), Out(dbgs()) {}
503 
504 template <typename IRUnitT>
505 void TextChangeReporter<IRUnitT>::handleInitialIR(Any IR) {
506   // Always print the module.
507   // Unwrap and print directly to avoid filtering problems in general routines.
508   auto *M = unwrapModule(IR, /*Force=*/true);
509   assert(M && "Expected module to be unwrapped when forced.");
510   Out << "*** IR Dump At Start ***\n";
511   M->print(Out, nullptr,
512            /*ShouldPreserveUseListOrder=*/true);
513 }
514 
515 template <typename IRUnitT>
516 void TextChangeReporter<IRUnitT>::omitAfter(StringRef PassID,
517                                             std::string &Name) {
518   Out << formatv("*** IR Dump After {0} on {1} omitted because no change ***\n",
519                  PassID, Name);
520 }
521 
522 template <typename IRUnitT>
523 void TextChangeReporter<IRUnitT>::handleInvalidated(StringRef PassID) {
524   Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
525 }
526 
527 template <typename IRUnitT>
528 void TextChangeReporter<IRUnitT>::handleFiltered(StringRef PassID,
529                                                  std::string &Name) {
530   SmallString<20> Banner =
531       formatv("*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
532   Out << Banner;
533 }
534 
535 template <typename IRUnitT>
536 void TextChangeReporter<IRUnitT>::handleIgnored(StringRef PassID,
537                                                 std::string &Name) {
538   Out << formatv("*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
539 }
540 
541 IRChangedPrinter::~IRChangedPrinter() {}
542 
543 void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
544   if (PrintChanged == ChangePrinter::PrintChangedVerbose ||
545       PrintChanged == ChangePrinter::PrintChangedQuiet)
546     TextChangeReporter<std::string>::registerRequiredCallbacks(PIC);
547 }
548 
549 void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID,
550                                                 std::string &Output) {
551   raw_string_ostream OS(Output);
552   unwrapAndPrint(OS, IR,
553                  /*ShouldPreserveUseListOrder=*/true);
554   OS.str();
555 }
556 
557 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
558                                    const std::string &Before,
559                                    const std::string &After, Any) {
560   // Report the IR before the changes when requested.
561   if (PrintChangedBefore)
562     Out << "*** IR Dump Before " << PassID << " on " << Name << " ***\n"
563         << Before;
564 
565   // We might not get anything to print if we only want to print a specific
566   // function but it gets deleted.
567   if (After.empty()) {
568     Out << "*** IR Deleted After " << PassID << " on " << Name << " ***\n";
569     return;
570   }
571 
572   Out << "*** IR Dump After " << PassID << " on " << Name << " ***\n" << After;
573 }
574 
575 bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) {
576   return S1 == S2;
577 }
578 
579 template <typename IRData>
580 void OrderedChangedData<IRData>::report(
581     const OrderedChangedData &Before, const OrderedChangedData &After,
582     function_ref<void(const IRData *, const IRData *)> HandlePair) {
583   const auto &BFD = Before.getData();
584   const auto &AFD = After.getData();
585   std::vector<std::string>::const_iterator BI = Before.getOrder().begin();
586   std::vector<std::string>::const_iterator BE = Before.getOrder().end();
587   std::vector<std::string>::const_iterator AI = After.getOrder().begin();
588   std::vector<std::string>::const_iterator AE = After.getOrder().end();
589 
590   auto handlePotentiallyRemovedIRData = [&](std::string S) {
591     // The order in LLVM may have changed so check if still exists.
592     if (!AFD.count(S)) {
593       // This has been removed.
594       HandlePair(&BFD.find(*BI)->getValue(), nullptr);
595     }
596   };
597   auto handleNewIRData = [&](std::vector<const IRData *> &Q) {
598     // Print out any queued up new sections
599     for (const IRData *NBI : Q)
600       HandlePair(nullptr, NBI);
601     Q.clear();
602   };
603 
604   // Print out the IRData in the after order, with before ones interspersed
605   // appropriately (ie, somewhere near where they were in the before list).
606   // Start at the beginning of both lists.  Loop through the
607   // after list.  If an element is common, then advance in the before list
608   // reporting the removed ones until the common one is reached.  Report any
609   // queued up new ones and then report the common one.  If an element is not
610   // common, then enqueue it for reporting.  When the after list is exhausted,
611   // loop through the before list, reporting any removed ones.  Finally,
612   // report the rest of the enqueued new ones.
613   std::vector<const IRData *> NewIRDataQueue;
614   while (AI != AE) {
615     if (!BFD.count(*AI)) {
616       // This section is new so place it in the queue.  This will cause it
617       // to be reported after deleted sections.
618       NewIRDataQueue.emplace_back(&AFD.find(*AI)->getValue());
619       ++AI;
620       continue;
621     }
622     // This section is in both; advance and print out any before-only
623     // until we get to it.
624     while (*BI != *AI) {
625       handlePotentiallyRemovedIRData(*BI);
626       ++BI;
627     }
628     // Report any new sections that were queued up and waiting.
629     handleNewIRData(NewIRDataQueue);
630 
631     const IRData &AData = AFD.find(*AI)->getValue();
632     const IRData &BData = BFD.find(*AI)->getValue();
633     HandlePair(&BData, &AData);
634     ++BI;
635     ++AI;
636   }
637 
638   // Check any remaining before sections to see if they have been removed
639   while (BI != BE) {
640     handlePotentiallyRemovedIRData(*BI);
641     ++BI;
642   }
643 
644   handleNewIRData(NewIRDataQueue);
645 }
646 
647 void ChangedIRComparer::compare(Any IR, StringRef Prefix, StringRef PassID,
648                                 StringRef Name) {
649   if (!getModuleForComparison(IR)) {
650     // Not a module so just handle the single function.
651     assert(Before.getData().size() == 1 && "Expected only one function.");
652     assert(After.getData().size() == 1 && "Expected only one function.");
653     handleFunctionCompare(Name, Prefix, PassID, false,
654                           Before.getData().begin()->getValue(),
655                           After.getData().begin()->getValue());
656     return;
657   }
658 
659   ChangedIRData::report(
660       Before, After, [&](const ChangedFuncData *B, const ChangedFuncData *A) {
661         ChangedFuncData Missing;
662         if (!B)
663           B = &Missing;
664         else if (!A)
665           A = &Missing;
666         assert(B != &Missing && A != &Missing &&
667                "Both functions cannot be missing.");
668         handleFunctionCompare(Name, Prefix, PassID, true, *B, *A);
669       });
670 }
671 
672 void ChangedIRComparer::analyzeIR(Any IR, ChangedIRData &Data) {
673   if (const Module *M = getModuleForComparison(IR)) {
674     // Create data for each existing/interesting function in the module.
675     for (const Function &F : *M)
676       generateFunctionData(Data, F);
677     return;
678   }
679 
680   const Function *F = nullptr;
681   if (any_isa<const Function *>(IR))
682     F = any_cast<const Function *>(IR);
683   else {
684     assert(any_isa<const Loop *>(IR) && "Unknown IR unit.");
685     const Loop *L = any_cast<const Loop *>(IR);
686     F = L->getHeader()->getParent();
687   }
688   assert(F && "Unknown IR unit.");
689   generateFunctionData(Data, *F);
690 }
691 
692 const Module *ChangedIRComparer::getModuleForComparison(Any IR) {
693   if (any_isa<const Module *>(IR))
694     return any_cast<const Module *>(IR);
695   if (any_isa<const LazyCallGraph::SCC *>(IR))
696     return any_cast<const LazyCallGraph::SCC *>(IR)
697         ->begin()
698         ->getFunction()
699         .getParent();
700   return nullptr;
701 }
702 
703 bool ChangedIRComparer::generateFunctionData(ChangedIRData &Data,
704                                              const Function &F) {
705   if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
706     ChangedFuncData CFD;
707     for (const auto &B : F) {
708       CFD.getOrder().emplace_back(B.getName());
709       CFD.getData().insert({B.getName(), B});
710     }
711     Data.getOrder().emplace_back(F.getName());
712     Data.getData().insert({F.getName(), CFD});
713     return true;
714   }
715   return false;
716 }
717 
718 PrintIRInstrumentation::~PrintIRInstrumentation() {
719   assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
720 }
721 
722 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
723   assert(StoreModuleDesc);
724   const Module *M = unwrapModule(IR);
725   ModuleDescStack.emplace_back(M, getIRName(IR), PassID);
726 }
727 
728 PrintIRInstrumentation::PrintModuleDesc
729 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
730   assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
731   PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
732   assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
733   return ModuleDesc;
734 }
735 
736 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
737   if (isIgnored(PassID))
738     return;
739 
740   // Saving Module for AfterPassInvalidated operations.
741   // Note: here we rely on a fact that we do not change modules while
742   // traversing the pipeline, so the latest captured module is good
743   // for all print operations that has not happen yet.
744   if (StoreModuleDesc && shouldPrintAfterPass(PassID))
745     pushModuleDesc(PassID, IR);
746 
747   if (!shouldPrintBeforePass(PassID))
748     return;
749 
750   if (!shouldPrintIR(IR))
751     return;
752 
753   dbgs() << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
754          << " ***\n";
755   unwrapAndPrint(dbgs(), IR);
756 }
757 
758 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
759   if (isIgnored(PassID))
760     return;
761 
762   if (!shouldPrintAfterPass(PassID))
763     return;
764 
765   if (StoreModuleDesc) {
766     const Module *M;
767     std::string IRName;
768     StringRef StoredPassID;
769     std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
770     assert(StoredPassID == PassID && "mismatched PassID");
771   }
772 
773   if (!shouldPrintIR(IR))
774     return;
775 
776   dbgs() << "*** IR Dump After " << PassID << " on " << getIRName(IR)
777          << " ***\n";
778   unwrapAndPrint(dbgs(), IR);
779 }
780 
781 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
782   StringRef PassName = PIC->getPassNameForClassName(PassID);
783   if (!StoreModuleDesc || !shouldPrintAfterPass(PassName))
784     return;
785 
786   if (isIgnored(PassID))
787     return;
788 
789   const Module *M;
790   std::string IRName;
791   StringRef StoredPassID;
792   std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
793   assert(StoredPassID == PassID && "mismatched PassID");
794   // Additional filtering (e.g. -filter-print-func) can lead to module
795   // printing being skipped.
796   if (!M)
797     return;
798 
799   SmallString<20> Banner =
800       formatv("*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
801   dbgs() << Banner << "\n";
802   printIR(dbgs(), M);
803 }
804 
805 bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
806   if (shouldPrintBeforeAll())
807     return true;
808 
809   StringRef PassName = PIC->getPassNameForClassName(PassID);
810   return llvm::is_contained(printBeforePasses(), PassName);
811 }
812 
813 bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
814   if (shouldPrintAfterAll())
815     return true;
816 
817   StringRef PassName = PIC->getPassNameForClassName(PassID);
818   return llvm::is_contained(printAfterPasses(), PassName);
819 }
820 
821 void PrintIRInstrumentation::registerCallbacks(
822     PassInstrumentationCallbacks &PIC) {
823   this->PIC = &PIC;
824 
825   // BeforePass callback is not just for printing, it also saves a Module
826   // for later use in AfterPassInvalidated.
827   StoreModuleDesc = forcePrintModuleIR() && shouldPrintAfterSomePass();
828   if (shouldPrintBeforeSomePass() || StoreModuleDesc)
829     PIC.registerBeforeNonSkippedPassCallback(
830         [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
831 
832   if (shouldPrintAfterSomePass()) {
833     PIC.registerAfterPassCallback(
834         [this](StringRef P, Any IR, const PreservedAnalyses &) {
835           this->printAfterPass(P, IR);
836         });
837     PIC.registerAfterPassInvalidatedCallback(
838         [this](StringRef P, const PreservedAnalyses &) {
839           this->printAfterPassInvalidated(P);
840         });
841   }
842 }
843 
844 void OptNoneInstrumentation::registerCallbacks(
845     PassInstrumentationCallbacks &PIC) {
846   PIC.registerShouldRunOptionalPassCallback(
847       [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
848 }
849 
850 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
851   const Function *F = nullptr;
852   if (any_isa<const Function *>(IR)) {
853     F = any_cast<const Function *>(IR);
854   } else if (any_isa<const Loop *>(IR)) {
855     F = any_cast<const Loop *>(IR)->getHeader()->getParent();
856   }
857   bool ShouldRun = !(F && F->hasOptNone());
858   if (!ShouldRun && DebugLogging) {
859     errs() << "Skipping pass " << PassID << " on " << F->getName()
860            << " due to optnone attribute\n";
861   }
862   return ShouldRun;
863 }
864 
865 void OptBisectInstrumentation::registerCallbacks(
866     PassInstrumentationCallbacks &PIC) {
867   if (!OptBisector->isEnabled())
868     return;
869   PIC.registerShouldRunOptionalPassCallback([](StringRef PassID, Any IR) {
870     return isIgnored(PassID) || OptBisector->checkPass(PassID, getIRName(IR));
871   });
872 }
873 
874 void PrintPassInstrumentation::registerCallbacks(
875     PassInstrumentationCallbacks &PIC) {
876   if (!DebugLogging)
877     return;
878 
879   std::vector<StringRef> SpecialPasses = {"PassManager"};
880   if (!DebugPMVerbose)
881     SpecialPasses.emplace_back("PassAdaptor");
882 
883   PIC.registerBeforeSkippedPassCallback(
884       [SpecialPasses](StringRef PassID, Any IR) {
885         assert(!isSpecialPass(PassID, SpecialPasses) &&
886                "Unexpectedly skipping special pass");
887 
888         dbgs() << "Skipping pass: " << PassID << " on " << getIRName(IR)
889                << "\n";
890       });
891 
892   PIC.registerBeforeNonSkippedPassCallback(
893       [SpecialPasses](StringRef PassID, Any IR) {
894         if (isSpecialPass(PassID, SpecialPasses))
895           return;
896 
897         dbgs() << "Running pass: " << PassID << " on " << getIRName(IR) << "\n";
898       });
899 
900   PIC.registerBeforeAnalysisCallback([](StringRef PassID, Any IR) {
901     dbgs() << "Running analysis: " << PassID << " on " << getIRName(IR) << "\n";
902   });
903 }
904 
905 void PassStructurePrinter::printWithIdent(bool Expand, const Twine &Msg) {
906   if (!Msg.isTriviallyEmpty())
907     dbgs().indent(Ident) << Msg << "\n";
908   Ident = Expand ? Ident + 2 : Ident - 2;
909   assert(Ident >= 0);
910 }
911 
912 void PassStructurePrinter::registerCallbacks(
913     PassInstrumentationCallbacks &PIC) {
914   if (!DebugPassStructure)
915     return;
916 
917   PIC.registerBeforeNonSkippedPassCallback([this](StringRef PassID, Any IR) {
918     printWithIdent(true, PassID + " on " + getIRName(IR));
919   });
920   PIC.registerAfterPassCallback(
921       [this](StringRef PassID, Any IR, const PreservedAnalyses &) {
922         printWithIdent(false, Twine());
923       });
924 
925   PIC.registerAfterPassInvalidatedCallback(
926       [this](StringRef PassID, const PreservedAnalyses &) {
927         printWithIdent(false, Twine());
928       });
929 
930   PIC.registerBeforeAnalysisCallback([this](StringRef PassID, Any IR) {
931     printWithIdent(true, PassID + " analysis on " + getIRName(IR));
932   });
933   PIC.registerAfterAnalysisCallback(
934       [this](StringRef PassID, Any IR) { printWithIdent(false, Twine()); });
935 }
936 
937 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
938                                              bool TrackBBLifetime) {
939   if (TrackBBLifetime)
940     BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
941   for (const auto &BB : *F) {
942     if (BBGuards)
943       BBGuards->try_emplace(intptr_t(&BB), &BB);
944     for (auto *Succ : successors(&BB)) {
945       Graph[&BB][Succ]++;
946       if (BBGuards)
947         BBGuards->try_emplace(intptr_t(Succ), Succ);
948     }
949   }
950 }
951 
952 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
953   if (BB->hasName()) {
954     out << BB->getName() << "<" << BB << ">";
955     return;
956   }
957 
958   if (!BB->getParent()) {
959     out << "unnamed_removed<" << BB << ">";
960     return;
961   }
962 
963   if (BB == &BB->getParent()->getEntryBlock()) {
964     out << "entry"
965         << "<" << BB << ">";
966     return;
967   }
968 
969   unsigned FuncOrderBlockNum = 0;
970   for (auto &FuncBB : *BB->getParent()) {
971     if (&FuncBB == BB)
972       break;
973     FuncOrderBlockNum++;
974   }
975   out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
976 }
977 
978 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
979                                                         const CFG &Before,
980                                                         const CFG &After) {
981   assert(!After.isPoisoned());
982   if (Before.isPoisoned()) {
983     out << "Some blocks were deleted\n";
984     return;
985   }
986 
987   // Find and print graph differences.
988   if (Before.Graph.size() != After.Graph.size())
989     out << "Different number of non-leaf basic blocks: before="
990         << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
991 
992   for (auto &BB : Before.Graph) {
993     auto BA = After.Graph.find(BB.first);
994     if (BA == After.Graph.end()) {
995       out << "Non-leaf block ";
996       printBBName(out, BB.first);
997       out << " is removed (" << BB.second.size() << " successors)\n";
998     }
999   }
1000 
1001   for (auto &BA : After.Graph) {
1002     auto BB = Before.Graph.find(BA.first);
1003     if (BB == Before.Graph.end()) {
1004       out << "Non-leaf block ";
1005       printBBName(out, BA.first);
1006       out << " is added (" << BA.second.size() << " successors)\n";
1007       continue;
1008     }
1009 
1010     if (BB->second == BA.second)
1011       continue;
1012 
1013     out << "Different successors of block ";
1014     printBBName(out, BA.first);
1015     out << " (unordered):\n";
1016     out << "- before (" << BB->second.size() << "): ";
1017     for (auto &SuccB : BB->second) {
1018       printBBName(out, SuccB.first);
1019       if (SuccB.second != 1)
1020         out << "(" << SuccB.second << "), ";
1021       else
1022         out << ", ";
1023     }
1024     out << "\n";
1025     out << "- after (" << BA.second.size() << "): ";
1026     for (auto &SuccA : BA.second) {
1027       printBBName(out, SuccA.first);
1028       if (SuccA.second != 1)
1029         out << "(" << SuccA.second << "), ";
1030       else
1031         out << ", ";
1032     }
1033     out << "\n";
1034   }
1035 }
1036 
1037 // PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
1038 // passes, that reported they kept CFG analyses up-to-date, did not actually
1039 // change CFG. This check is done as follows. Before every functional pass in
1040 // BeforeNonSkippedPassCallback a CFG snapshot (an instance of
1041 // PreservedCFGCheckerInstrumentation::CFG) is requested from
1042 // FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
1043 // functional pass finishes and reports that CFGAnalyses or AllAnalyses are
1044 // up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
1045 // available) is checked to be equal to a freshly created CFG snapshot.
1046 struct PreservedCFGCheckerAnalysis
1047     : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {
1048   friend AnalysisInfoMixin<PreservedCFGCheckerAnalysis>;
1049 
1050   static AnalysisKey Key;
1051 
1052 public:
1053   /// Provide the result type for this analysis pass.
1054   using Result = PreservedCFGCheckerInstrumentation::CFG;
1055 
1056   /// Run the analysis pass over a function and produce CFG.
1057   Result run(Function &F, FunctionAnalysisManager &FAM) {
1058     return Result(&F, /* TrackBBLifetime */ true);
1059   }
1060 };
1061 
1062 AnalysisKey PreservedCFGCheckerAnalysis::Key;
1063 
1064 bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
1065     Function &F, const PreservedAnalyses &PA,
1066     FunctionAnalysisManager::Invalidator &) {
1067   auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>();
1068   return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
1069            PAC.preservedSet<CFGAnalyses>());
1070 }
1071 
1072 void PreservedCFGCheckerInstrumentation::registerCallbacks(
1073     PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM) {
1074   if (!VerifyPreservedCFG)
1075     return;
1076 
1077   FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); });
1078 
1079   auto checkCFG = [](StringRef Pass, StringRef FuncName, const CFG &GraphBefore,
1080                      const CFG &GraphAfter) {
1081     if (GraphAfter == GraphBefore)
1082       return;
1083 
1084     dbgs() << "Error: " << Pass
1085            << " does not invalidate CFG analyses but CFG changes detected in "
1086               "function @"
1087            << FuncName << ":\n";
1088     CFG::printDiff(dbgs(), GraphBefore, GraphAfter);
1089     report_fatal_error(Twine("CFG unexpectedly changed by ", Pass));
1090   };
1091 
1092   PIC.registerBeforeNonSkippedPassCallback(
1093       [this, &FAM](StringRef P, Any IR) {
1094         assert(&PassStack.emplace_back(P));
1095         (void)this;
1096         if (!any_isa<const Function *>(IR))
1097           return;
1098 
1099         const auto *F = any_cast<const Function *>(IR);
1100         // Make sure a fresh CFG snapshot is available before the pass.
1101         FAM.getResult<PreservedCFGCheckerAnalysis>(*const_cast<Function *>(F));
1102       });
1103 
1104   PIC.registerAfterPassInvalidatedCallback(
1105       [this](StringRef P, const PreservedAnalyses &PassPA) {
1106         assert(PassStack.pop_back_val() == P &&
1107                "Before and After callbacks must correspond");
1108         (void)this;
1109       });
1110 
1111   PIC.registerAfterPassCallback([this, &FAM,
1112                                  checkCFG](StringRef P, Any IR,
1113                                            const PreservedAnalyses &PassPA) {
1114     assert(PassStack.pop_back_val() == P &&
1115            "Before and After callbacks must correspond");
1116     (void)this;
1117 
1118     if (!any_isa<const Function *>(IR))
1119       return;
1120 
1121     if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>() &&
1122         !PassPA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>())
1123       return;
1124 
1125     const auto *F = any_cast<const Function *>(IR);
1126     if (auto *GraphBefore = FAM.getCachedResult<PreservedCFGCheckerAnalysis>(
1127             *const_cast<Function *>(F)))
1128       checkCFG(P, F->getName(), *GraphBefore,
1129                CFG(F, /* TrackBBLifetime */ false));
1130   });
1131 }
1132 
1133 void VerifyInstrumentation::registerCallbacks(
1134     PassInstrumentationCallbacks &PIC) {
1135   PIC.registerAfterPassCallback(
1136       [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
1137         if (isIgnored(P) || P == "VerifierPass")
1138           return;
1139         if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
1140           const Function *F;
1141           if (any_isa<const Loop *>(IR))
1142             F = any_cast<const Loop *>(IR)->getHeader()->getParent();
1143           else
1144             F = any_cast<const Function *>(IR);
1145           if (DebugLogging)
1146             dbgs() << "Verifying function " << F->getName() << "\n";
1147 
1148           if (verifyFunction(*F))
1149             report_fatal_error("Broken function found, compilation aborted!");
1150         } else if (any_isa<const Module *>(IR) ||
1151                    any_isa<const LazyCallGraph::SCC *>(IR)) {
1152           const Module *M;
1153           if (any_isa<const LazyCallGraph::SCC *>(IR))
1154             M = any_cast<const LazyCallGraph::SCC *>(IR)
1155                     ->begin()
1156                     ->getFunction()
1157                     .getParent();
1158           else
1159             M = any_cast<const Module *>(IR);
1160           if (DebugLogging)
1161             dbgs() << "Verifying module " << M->getName() << "\n";
1162 
1163           if (verifyModule(*M))
1164             report_fatal_error("Broken module found, compilation aborted!");
1165         }
1166       });
1167 }
1168 
1169 InLineChangePrinter::~InLineChangePrinter() {}
1170 
1171 void InLineChangePrinter::generateIRRepresentation(Any IR, StringRef PassID,
1172                                                    ChangedIRData &D) {
1173   ChangedIRComparer::analyzeIR(IR, D);
1174 }
1175 
1176 void InLineChangePrinter::handleAfter(StringRef PassID, std::string &Name,
1177                                       const ChangedIRData &Before,
1178                                       const ChangedIRData &After, Any IR) {
1179   SmallString<20> Banner =
1180       formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);
1181   Out << Banner;
1182   ChangedIRComparer(Out, Before, After, UseColour)
1183       .compare(IR, "", PassID, Name);
1184   Out << "\n";
1185 }
1186 
1187 bool InLineChangePrinter::same(const ChangedIRData &D1,
1188                                const ChangedIRData &D2) {
1189   return D1 == D2;
1190 }
1191 
1192 void ChangedIRComparer::handleFunctionCompare(StringRef Name, StringRef Prefix,
1193                                               StringRef PassID, bool InModule,
1194                                               const ChangedFuncData &Before,
1195                                               const ChangedFuncData &After) {
1196   // Print a banner when this is being shown in the context of a module
1197   if (InModule)
1198     Out << "\n*** IR for function " << Name << " ***\n";
1199 
1200   ChangedFuncData::report(
1201       Before, After, [&](const ChangedBlockData *B, const ChangedBlockData *A) {
1202         StringRef BStr = B ? B->getBody() : "\n";
1203         StringRef AStr = A ? A->getBody() : "\n";
1204         const std::string Removed =
1205             UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";
1206         const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";
1207         const std::string NoChange = " %l\n";
1208         Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1209       });
1210 }
1211 
1212 void InLineChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
1213   if (PrintChanged == ChangePrinter::PrintChangedDiffVerbose ||
1214       PrintChanged == ChangePrinter::PrintChangedDiffQuiet ||
1215       PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose ||
1216       PrintChanged == ChangePrinter::PrintChangedColourDiffQuiet)
1217     TextChangeReporter<ChangedIRData>::registerRequiredCallbacks(PIC);
1218 }
1219 
1220 StandardInstrumentations::StandardInstrumentations(bool DebugLogging,
1221                                                    bool VerifyEach)
1222     : PrintPass(DebugLogging), OptNone(DebugLogging),
1223       PrintChangedIR(PrintChanged == ChangePrinter::PrintChangedVerbose),
1224       PrintChangedDiff(
1225           PrintChanged == ChangePrinter::PrintChangedDiffVerbose ||
1226               PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose,
1227           PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose ||
1228               PrintChanged == ChangePrinter::PrintChangedColourDiffQuiet),
1229       Verify(DebugLogging), VerifyEach(VerifyEach) {}
1230 
1231 void StandardInstrumentations::registerCallbacks(
1232     PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM) {
1233   PrintIR.registerCallbacks(PIC);
1234   PrintPass.registerCallbacks(PIC);
1235   StructurePrinter.registerCallbacks(PIC);
1236   TimePasses.registerCallbacks(PIC);
1237   OptNone.registerCallbacks(PIC);
1238   OptBisect.registerCallbacks(PIC);
1239   if (FAM)
1240     PreservedCFGChecker.registerCallbacks(PIC, *FAM);
1241   PrintChangedIR.registerCallbacks(PIC);
1242   PseudoProbeVerification.registerCallbacks(PIC);
1243   if (VerifyEach)
1244     Verify.registerCallbacks(PIC);
1245   PrintChangedDiff.registerCallbacks(PIC);
1246 }
1247 
1248 namespace llvm {
1249 
1250 template class ChangeReporter<std::string>;
1251 template class TextChangeReporter<std::string>;
1252 
1253 template class ChangeReporter<ChangedIRData>;
1254 template class TextChangeReporter<ChangedIRData>;
1255 
1256 } // namespace llvm
1257