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