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;
880   if (!DebugPMVerbose) {
881     SpecialPasses.emplace_back("PassManager");
882     SpecialPasses.emplace_back("PassAdaptor");
883   }
884 
885   PIC.registerBeforeSkippedPassCallback(
886       [SpecialPasses](StringRef PassID, Any IR) {
887         assert(!isSpecialPass(PassID, SpecialPasses) &&
888                "Unexpectedly skipping special pass");
889 
890         dbgs() << "Skipping pass: " << PassID << " on " << getIRName(IR)
891                << "\n";
892       });
893 
894   PIC.registerBeforeNonSkippedPassCallback(
895       [SpecialPasses](StringRef PassID, Any IR) {
896         if (isSpecialPass(PassID, SpecialPasses))
897           return;
898 
899         dbgs() << "Running pass: " << PassID << " on " << getIRName(IR) << "\n";
900       });
901 
902   PIC.registerBeforeAnalysisCallback([](StringRef PassID, Any IR) {
903     dbgs() << "Running analysis: " << PassID << " on " << getIRName(IR) << "\n";
904   });
905 
906   PIC.registerAnalysisInvalidatedCallback([](StringRef PassID, Any IR) {
907     dbgs() << "Invalidating analysis: " << PassID << " on " << getIRName(IR)
908            << "\n";
909   });
910   PIC.registerAnalysesClearedCallback([](StringRef IRName) {
911     dbgs() << "Clearing all analysis results for: " << IRName << "\n";
912   });
913 }
914 
915 void PassStructurePrinter::printWithIdent(bool Expand, const Twine &Msg) {
916   if (!Msg.isTriviallyEmpty())
917     dbgs().indent(Ident) << Msg << "\n";
918   Ident = Expand ? Ident + 2 : Ident - 2;
919   assert(Ident >= 0);
920 }
921 
922 void PassStructurePrinter::registerCallbacks(
923     PassInstrumentationCallbacks &PIC) {
924   if (!DebugPassStructure)
925     return;
926 
927   PIC.registerBeforeNonSkippedPassCallback([this](StringRef PassID, Any IR) {
928     printWithIdent(true, PassID + " on " + getIRName(IR));
929   });
930   PIC.registerAfterPassCallback(
931       [this](StringRef PassID, Any IR, const PreservedAnalyses &) {
932         printWithIdent(false, Twine());
933       });
934 
935   PIC.registerAfterPassInvalidatedCallback(
936       [this](StringRef PassID, const PreservedAnalyses &) {
937         printWithIdent(false, Twine());
938       });
939 
940   PIC.registerBeforeAnalysisCallback([this](StringRef PassID, Any IR) {
941     printWithIdent(true, PassID + " analysis on " + getIRName(IR));
942   });
943   PIC.registerAfterAnalysisCallback(
944       [this](StringRef PassID, Any IR) { printWithIdent(false, Twine()); });
945 }
946 
947 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
948                                              bool TrackBBLifetime) {
949   if (TrackBBLifetime)
950     BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
951   for (const auto &BB : *F) {
952     if (BBGuards)
953       BBGuards->try_emplace(intptr_t(&BB), &BB);
954     for (auto *Succ : successors(&BB)) {
955       Graph[&BB][Succ]++;
956       if (BBGuards)
957         BBGuards->try_emplace(intptr_t(Succ), Succ);
958     }
959   }
960 }
961 
962 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
963   if (BB->hasName()) {
964     out << BB->getName() << "<" << BB << ">";
965     return;
966   }
967 
968   if (!BB->getParent()) {
969     out << "unnamed_removed<" << BB << ">";
970     return;
971   }
972 
973   if (BB == &BB->getParent()->getEntryBlock()) {
974     out << "entry"
975         << "<" << BB << ">";
976     return;
977   }
978 
979   unsigned FuncOrderBlockNum = 0;
980   for (auto &FuncBB : *BB->getParent()) {
981     if (&FuncBB == BB)
982       break;
983     FuncOrderBlockNum++;
984   }
985   out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
986 }
987 
988 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
989                                                         const CFG &Before,
990                                                         const CFG &After) {
991   assert(!After.isPoisoned());
992   if (Before.isPoisoned()) {
993     out << "Some blocks were deleted\n";
994     return;
995   }
996 
997   // Find and print graph differences.
998   if (Before.Graph.size() != After.Graph.size())
999     out << "Different number of non-leaf basic blocks: before="
1000         << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
1001 
1002   for (auto &BB : Before.Graph) {
1003     auto BA = After.Graph.find(BB.first);
1004     if (BA == After.Graph.end()) {
1005       out << "Non-leaf block ";
1006       printBBName(out, BB.first);
1007       out << " is removed (" << BB.second.size() << " successors)\n";
1008     }
1009   }
1010 
1011   for (auto &BA : After.Graph) {
1012     auto BB = Before.Graph.find(BA.first);
1013     if (BB == Before.Graph.end()) {
1014       out << "Non-leaf block ";
1015       printBBName(out, BA.first);
1016       out << " is added (" << BA.second.size() << " successors)\n";
1017       continue;
1018     }
1019 
1020     if (BB->second == BA.second)
1021       continue;
1022 
1023     out << "Different successors of block ";
1024     printBBName(out, BA.first);
1025     out << " (unordered):\n";
1026     out << "- before (" << BB->second.size() << "): ";
1027     for (auto &SuccB : BB->second) {
1028       printBBName(out, SuccB.first);
1029       if (SuccB.second != 1)
1030         out << "(" << SuccB.second << "), ";
1031       else
1032         out << ", ";
1033     }
1034     out << "\n";
1035     out << "- after (" << BA.second.size() << "): ";
1036     for (auto &SuccA : BA.second) {
1037       printBBName(out, SuccA.first);
1038       if (SuccA.second != 1)
1039         out << "(" << SuccA.second << "), ";
1040       else
1041         out << ", ";
1042     }
1043     out << "\n";
1044   }
1045 }
1046 
1047 // PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
1048 // passes, that reported they kept CFG analyses up-to-date, did not actually
1049 // change CFG. This check is done as follows. Before every functional pass in
1050 // BeforeNonSkippedPassCallback a CFG snapshot (an instance of
1051 // PreservedCFGCheckerInstrumentation::CFG) is requested from
1052 // FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
1053 // functional pass finishes and reports that CFGAnalyses or AllAnalyses are
1054 // up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
1055 // available) is checked to be equal to a freshly created CFG snapshot.
1056 struct PreservedCFGCheckerAnalysis
1057     : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {
1058   friend AnalysisInfoMixin<PreservedCFGCheckerAnalysis>;
1059 
1060   static AnalysisKey Key;
1061 
1062 public:
1063   /// Provide the result type for this analysis pass.
1064   using Result = PreservedCFGCheckerInstrumentation::CFG;
1065 
1066   /// Run the analysis pass over a function and produce CFG.
1067   Result run(Function &F, FunctionAnalysisManager &FAM) {
1068     return Result(&F, /* TrackBBLifetime */ true);
1069   }
1070 };
1071 
1072 AnalysisKey PreservedCFGCheckerAnalysis::Key;
1073 
1074 bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
1075     Function &F, const PreservedAnalyses &PA,
1076     FunctionAnalysisManager::Invalidator &) {
1077   auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>();
1078   return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
1079            PAC.preservedSet<CFGAnalyses>());
1080 }
1081 
1082 void PreservedCFGCheckerInstrumentation::registerCallbacks(
1083     PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM) {
1084   if (!VerifyPreservedCFG)
1085     return;
1086 
1087   FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); });
1088 
1089   auto checkCFG = [](StringRef Pass, StringRef FuncName, const CFG &GraphBefore,
1090                      const CFG &GraphAfter) {
1091     if (GraphAfter == GraphBefore)
1092       return;
1093 
1094     dbgs() << "Error: " << Pass
1095            << " does not invalidate CFG analyses but CFG changes detected in "
1096               "function @"
1097            << FuncName << ":\n";
1098     CFG::printDiff(dbgs(), GraphBefore, GraphAfter);
1099     report_fatal_error(Twine("CFG unexpectedly changed by ", Pass));
1100   };
1101 
1102   PIC.registerBeforeNonSkippedPassCallback(
1103       [this, &FAM](StringRef P, Any IR) {
1104         assert(&PassStack.emplace_back(P));
1105         (void)this;
1106         if (!any_isa<const Function *>(IR))
1107           return;
1108 
1109         const auto *F = any_cast<const Function *>(IR);
1110         // Make sure a fresh CFG snapshot is available before the pass.
1111         FAM.getResult<PreservedCFGCheckerAnalysis>(*const_cast<Function *>(F));
1112       });
1113 
1114   PIC.registerAfterPassInvalidatedCallback(
1115       [this](StringRef P, const PreservedAnalyses &PassPA) {
1116         assert(PassStack.pop_back_val() == P &&
1117                "Before and After callbacks must correspond");
1118         (void)this;
1119       });
1120 
1121   PIC.registerAfterPassCallback([this, &FAM,
1122                                  checkCFG](StringRef P, Any IR,
1123                                            const PreservedAnalyses &PassPA) {
1124     assert(PassStack.pop_back_val() == P &&
1125            "Before and After callbacks must correspond");
1126     (void)this;
1127 
1128     if (!any_isa<const Function *>(IR))
1129       return;
1130 
1131     if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>() &&
1132         !PassPA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>())
1133       return;
1134 
1135     const auto *F = any_cast<const Function *>(IR);
1136     if (auto *GraphBefore = FAM.getCachedResult<PreservedCFGCheckerAnalysis>(
1137             *const_cast<Function *>(F)))
1138       checkCFG(P, F->getName(), *GraphBefore,
1139                CFG(F, /* TrackBBLifetime */ false));
1140   });
1141 }
1142 
1143 void VerifyInstrumentation::registerCallbacks(
1144     PassInstrumentationCallbacks &PIC) {
1145   PIC.registerAfterPassCallback(
1146       [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
1147         if (isIgnored(P) || P == "VerifierPass")
1148           return;
1149         if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
1150           const Function *F;
1151           if (any_isa<const Loop *>(IR))
1152             F = any_cast<const Loop *>(IR)->getHeader()->getParent();
1153           else
1154             F = any_cast<const Function *>(IR);
1155           if (DebugLogging)
1156             dbgs() << "Verifying function " << F->getName() << "\n";
1157 
1158           if (verifyFunction(*F))
1159             report_fatal_error("Broken function found, compilation aborted!");
1160         } else if (any_isa<const Module *>(IR) ||
1161                    any_isa<const LazyCallGraph::SCC *>(IR)) {
1162           const Module *M;
1163           if (any_isa<const LazyCallGraph::SCC *>(IR))
1164             M = any_cast<const LazyCallGraph::SCC *>(IR)
1165                     ->begin()
1166                     ->getFunction()
1167                     .getParent();
1168           else
1169             M = any_cast<const Module *>(IR);
1170           if (DebugLogging)
1171             dbgs() << "Verifying module " << M->getName() << "\n";
1172 
1173           if (verifyModule(*M))
1174             report_fatal_error("Broken module found, compilation aborted!");
1175         }
1176       });
1177 }
1178 
1179 InLineChangePrinter::~InLineChangePrinter() {}
1180 
1181 void InLineChangePrinter::generateIRRepresentation(Any IR, StringRef PassID,
1182                                                    ChangedIRData &D) {
1183   ChangedIRComparer::analyzeIR(IR, D);
1184 }
1185 
1186 void InLineChangePrinter::handleAfter(StringRef PassID, std::string &Name,
1187                                       const ChangedIRData &Before,
1188                                       const ChangedIRData &After, Any IR) {
1189   SmallString<20> Banner =
1190       formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);
1191   Out << Banner;
1192   ChangedIRComparer(Out, Before, After, UseColour)
1193       .compare(IR, "", PassID, Name);
1194   Out << "\n";
1195 }
1196 
1197 bool InLineChangePrinter::same(const ChangedIRData &D1,
1198                                const ChangedIRData &D2) {
1199   return D1 == D2;
1200 }
1201 
1202 void ChangedIRComparer::handleFunctionCompare(StringRef Name, StringRef Prefix,
1203                                               StringRef PassID, bool InModule,
1204                                               const ChangedFuncData &Before,
1205                                               const ChangedFuncData &After) {
1206   // Print a banner when this is being shown in the context of a module
1207   if (InModule)
1208     Out << "\n*** IR for function " << Name << " ***\n";
1209 
1210   ChangedFuncData::report(
1211       Before, After, [&](const ChangedBlockData *B, const ChangedBlockData *A) {
1212         StringRef BStr = B ? B->getBody() : "\n";
1213         StringRef AStr = A ? A->getBody() : "\n";
1214         const std::string Removed =
1215             UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";
1216         const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";
1217         const std::string NoChange = " %l\n";
1218         Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1219       });
1220 }
1221 
1222 void InLineChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
1223   if (PrintChanged == ChangePrinter::PrintChangedDiffVerbose ||
1224       PrintChanged == ChangePrinter::PrintChangedDiffQuiet ||
1225       PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose ||
1226       PrintChanged == ChangePrinter::PrintChangedColourDiffQuiet)
1227     TextChangeReporter<ChangedIRData>::registerRequiredCallbacks(PIC);
1228 }
1229 
1230 StandardInstrumentations::StandardInstrumentations(bool DebugLogging,
1231                                                    bool VerifyEach)
1232     : PrintPass(DebugLogging), OptNone(DebugLogging),
1233       PrintChangedIR(PrintChanged == ChangePrinter::PrintChangedVerbose),
1234       PrintChangedDiff(
1235           PrintChanged == ChangePrinter::PrintChangedDiffVerbose ||
1236               PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose,
1237           PrintChanged == ChangePrinter::PrintChangedColourDiffVerbose ||
1238               PrintChanged == ChangePrinter::PrintChangedColourDiffQuiet),
1239       Verify(DebugLogging), VerifyEach(VerifyEach) {}
1240 
1241 void StandardInstrumentations::registerCallbacks(
1242     PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM) {
1243   PrintIR.registerCallbacks(PIC);
1244   PrintPass.registerCallbacks(PIC);
1245   StructurePrinter.registerCallbacks(PIC);
1246   TimePasses.registerCallbacks(PIC);
1247   OptNone.registerCallbacks(PIC);
1248   OptBisect.registerCallbacks(PIC);
1249   if (FAM)
1250     PreservedCFGChecker.registerCallbacks(PIC, *FAM);
1251   PrintChangedIR.registerCallbacks(PIC);
1252   PseudoProbeVerification.registerCallbacks(PIC);
1253   if (VerifyEach)
1254     Verify.registerCallbacks(PIC);
1255   PrintChangedDiff.registerCallbacks(PIC);
1256 }
1257 
1258 namespace llvm {
1259 
1260 template class ChangeReporter<std::string>;
1261 template class TextChangeReporter<std::string>;
1262 
1263 template class ChangeReporter<ChangedIRData>;
1264 template class TextChangeReporter<ChangedIRData>;
1265 
1266 } // namespace llvm
1267