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/StringRef.h"
18 #include "llvm/Analysis/CallGraphSCCPass.h"
19 #include "llvm/Analysis/LazyCallGraph.h"
20 #include "llvm/Analysis/LoopInfo.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/IR/PassInstrumentation.h"
25 #include "llvm/IR/PassManager.h"
26 #include "llvm/IR/PrintPasses.h"
27 #include "llvm/IR/StructuralHash.h"
28 #include "llvm/IR/Verifier.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/CrashRecoveryContext.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Support/FormatVariadic.h"
34 #include "llvm/Support/GraphWriter.h"
35 #include "llvm/Support/MemoryBuffer.h"
36 #include "llvm/Support/Program.h"
37 #include "llvm/Support/Regex.h"
38 #include "llvm/Support/Signals.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include <unordered_map>
41 #include <unordered_set>
42 #include <utility>
43 #include <vector>
44 
45 using namespace llvm;
46 
47 static cl::opt<bool> VerifyAnalysisInvalidation("verify-analysis-invalidation",
48                                                 cl::Hidden,
49 #ifdef EXPENSIVE_CHECKS
50                                                 cl::init(true)
51 #else
52                                                 cl::init(false)
53 #endif
54 );
55 
56 // An option that supports the -print-changed option.  See
57 // the description for -print-changed for an explanation of the use
58 // of this option.  Note that this option has no effect without -print-changed.
59 static cl::opt<bool>
60     PrintChangedBefore("print-before-changed",
61                        cl::desc("Print before passes that change them"),
62                        cl::init(false), cl::Hidden);
63 
64 // An option for specifying the dot used by
65 // print-changed=[dot-cfg | dot-cfg-quiet]
66 static cl::opt<std::string>
67     DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"),
68               cl::desc("system dot used by change reporters"));
69 
70 // An option that determines the colour used for elements that are only
71 // in the before part.  Must be a colour named in appendix J of
72 // https://graphviz.org/pdf/dotguide.pdf
73 static cl::opt<std::string>
74     BeforeColour("dot-cfg-before-color",
75                  cl::desc("Color for dot-cfg before elements"), cl::Hidden,
76                  cl::init("red"));
77 // An option that determines the colour used for elements that are only
78 // in the after part.  Must be a colour named in appendix J of
79 // https://graphviz.org/pdf/dotguide.pdf
80 static cl::opt<std::string>
81     AfterColour("dot-cfg-after-color",
82                 cl::desc("Color for dot-cfg after elements"), cl::Hidden,
83                 cl::init("forestgreen"));
84 // An option that determines the colour used for elements that are in both
85 // the before and after parts.  Must be a colour named in appendix J of
86 // https://graphviz.org/pdf/dotguide.pdf
87 static cl::opt<std::string>
88     CommonColour("dot-cfg-common-color",
89                  cl::desc("Color for dot-cfg common elements"), cl::Hidden,
90                  cl::init("black"));
91 
92 // An option that determines where the generated website file (named
93 // passes.html) and the associated pdf files (named diff_*.pdf) are saved.
94 static cl::opt<std::string> DotCfgDir(
95     "dot-cfg-dir",
96     cl::desc("Generate dot files into specified directory for changed IRs"),
97     cl::Hidden, cl::init("./"));
98 
99 // Options to print the IR that was being processed when a pass crashes.
100 static cl::opt<std::string> PrintOnCrashPath(
101     "print-on-crash-path",
102     cl::desc("Print the last form of the IR before crash to a file"),
103     cl::Hidden);
104 
105 static cl::opt<bool> PrintOnCrash(
106     "print-on-crash",
107     cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
108     cl::Hidden);
109 
110 static cl::opt<std::string> OptBisectPrintIRPath(
111     "opt-bisect-print-ir-path",
112     cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden);
113 
114 static cl::opt<bool> PrintPassNumbers(
115     "print-pass-numbers", cl::init(false), cl::Hidden,
116     cl::desc("Print pass names and their ordinals"));
117 
118 static cl::opt<unsigned>
119     PrintAtPassNumber("print-at-pass-number", cl::init(0), cl::Hidden,
120                 cl::desc("Print IR at pass with this number as "
121                          "reported by print-passes-names"));
122 
123 namespace {
124 
125 // An option for specifying an executable that will be called with the IR
126 // everytime it changes in the opt pipeline.  It will also be called on
127 // the initial IR as it enters the pipeline.  The executable will be passed
128 // the name of a temporary file containing the IR and the PassID.  This may
129 // be used, for example, to call llc on the IR and run a test to determine
130 // which pass makes a change that changes the functioning of the IR.
131 // The usual modifier options work as expected.
132 static cl::opt<std::string>
133     TestChanged("exec-on-ir-change", cl::Hidden, cl::init(""),
134                 cl::desc("exe called with module IR after each pass that "
135                          "changes it"));
136 
137 /// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
138 /// certain global filters. Will never return nullptr if \p Force is true.
139 const Module *unwrapModule(Any IR, bool Force = false) {
140   if (const auto **M = any_cast<const Module *>(&IR))
141     return *M;
142 
143   if (const auto **F = any_cast<const Function *>(&IR)) {
144     if (!Force && !isFunctionInPrintList((*F)->getName()))
145       return nullptr;
146 
147     return (*F)->getParent();
148   }
149 
150   if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR)) {
151     for (const LazyCallGraph::Node &N : **C) {
152       const Function &F = N.getFunction();
153       if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
154         return F.getParent();
155       }
156     }
157     assert(!Force && "Expected a module");
158     return nullptr;
159   }
160 
161   if (const auto **L = any_cast<const Loop *>(&IR)) {
162     const Function *F = (*L)->getHeader()->getParent();
163     if (!Force && !isFunctionInPrintList(F->getName()))
164       return nullptr;
165     return F->getParent();
166   }
167 
168   llvm_unreachable("Unknown IR unit");
169 }
170 
171 void printIR(raw_ostream &OS, const Function *F) {
172   if (!isFunctionInPrintList(F->getName()))
173     return;
174   OS << *F;
175 }
176 
177 void printIR(raw_ostream &OS, const Module *M) {
178   if (isFunctionInPrintList("*") || forcePrintModuleIR()) {
179     M->print(OS, nullptr);
180   } else {
181     for (const auto &F : M->functions()) {
182       printIR(OS, &F);
183     }
184   }
185 }
186 
187 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C) {
188   for (const LazyCallGraph::Node &N : *C) {
189     const Function &F = N.getFunction();
190     if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
191       F.print(OS);
192     }
193   }
194 }
195 
196 void printIR(raw_ostream &OS, const Loop *L) {
197   const Function *F = L->getHeader()->getParent();
198   if (!isFunctionInPrintList(F->getName()))
199     return;
200   printLoop(const_cast<Loop &>(*L), OS);
201 }
202 
203 std::string getIRName(Any IR) {
204   if (any_cast<const Module *>(&IR))
205     return "[module]";
206 
207   if (const auto **F = any_cast<const Function *>(&IR))
208     return (*F)->getName().str();
209 
210   if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR))
211     return (*C)->getName();
212 
213   if (const auto **L = any_cast<const Loop *>(&IR))
214     return (*L)->getName().str();
215 
216   llvm_unreachable("Unknown wrapped IR type");
217 }
218 
219 bool moduleContainsFilterPrintFunc(const Module &M) {
220   return any_of(M.functions(),
221                 [](const Function &F) {
222                   return isFunctionInPrintList(F.getName());
223                 }) ||
224          isFunctionInPrintList("*");
225 }
226 
227 bool sccContainsFilterPrintFunc(const LazyCallGraph::SCC &C) {
228   return any_of(C,
229                 [](const LazyCallGraph::Node &N) {
230                   return isFunctionInPrintList(N.getName());
231                 }) ||
232          isFunctionInPrintList("*");
233 }
234 
235 bool shouldPrintIR(Any IR) {
236   if (const auto **M = any_cast<const Module *>(&IR))
237     return moduleContainsFilterPrintFunc(**M);
238 
239   if (const auto **F = any_cast<const Function *>(&IR))
240     return isFunctionInPrintList((*F)->getName());
241 
242   if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR))
243     return sccContainsFilterPrintFunc(**C);
244 
245   if (const auto **L = any_cast<const Loop *>(&IR))
246     return isFunctionInPrintList((*L)->getHeader()->getParent()->getName());
247   llvm_unreachable("Unknown wrapped IR type");
248 }
249 
250 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
251 /// Any and does actual print job.
252 void unwrapAndPrint(raw_ostream &OS, Any IR) {
253   if (!shouldPrintIR(IR))
254     return;
255 
256   if (forcePrintModuleIR()) {
257     auto *M = unwrapModule(IR);
258     assert(M && "should have unwrapped module");
259     printIR(OS, M);
260     return;
261   }
262 
263   if (const auto **M = any_cast<const Module *>(&IR)) {
264     printIR(OS, *M);
265     return;
266   }
267 
268   if (const auto **F = any_cast<const Function *>(&IR)) {
269     printIR(OS, *F);
270     return;
271   }
272 
273   if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR)) {
274     printIR(OS, *C);
275     return;
276   }
277 
278   if (const auto **L = any_cast<const Loop *>(&IR)) {
279     printIR(OS, *L);
280     return;
281   }
282   llvm_unreachable("Unknown wrapped IR type");
283 }
284 
285 // Return true when this is a pass for which changes should be ignored
286 bool isIgnored(StringRef PassID) {
287   return isSpecialPass(PassID,
288                        {"PassManager", "PassAdaptor", "AnalysisManagerProxy",
289                         "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass"});
290 }
291 
292 std::string makeHTMLReady(StringRef SR) {
293   std::string S;
294   while (true) {
295     StringRef Clean =
296         SR.take_until([](char C) { return C == '<' || C == '>'; });
297     S.append(Clean.str());
298     SR = SR.drop_front(Clean.size());
299     if (SR.size() == 0)
300       return S;
301     S.append(SR[0] == '<' ? "&lt;" : "&gt;");
302     SR = SR.drop_front();
303   }
304   llvm_unreachable("problems converting string to HTML");
305 }
306 
307 // Return the module when that is the appropriate level of comparison for \p IR.
308 const Module *getModuleForComparison(Any IR) {
309   if (const auto **M = any_cast<const Module *>(&IR))
310     return *M;
311   if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR))
312     return (*C)
313         ->begin()
314         ->getFunction()
315         .getParent();
316   return nullptr;
317 }
318 
319 bool isInterestingFunction(const Function &F) {
320   return isFunctionInPrintList(F.getName());
321 }
322 
323 // Return true when this is a pass on IR for which printing
324 // of changes is desired.
325 bool isInteresting(Any IR, StringRef PassID, StringRef PassName) {
326   if (isIgnored(PassID) || !isPassInPrintList(PassName))
327     return false;
328   if (const auto **F = any_cast<const Function *>(&IR))
329     return isInterestingFunction(**F);
330   return true;
331 }
332 
333 } // namespace
334 
335 template <typename T> ChangeReporter<T>::~ChangeReporter() {
336   assert(BeforeStack.empty() && "Problem with Change Printer stack.");
337 }
338 
339 template <typename T>
340 void ChangeReporter<T>::saveIRBeforePass(Any IR, StringRef PassID,
341                                          StringRef PassName) {
342   // Is this the initial IR?
343   if (InitialIR) {
344     InitialIR = false;
345     if (VerboseMode)
346       handleInitialIR(IR);
347   }
348 
349   // Always need to place something on the stack because invalidated passes
350   // are not given the IR so it cannot be determined whether the pass was for
351   // something that was filtered out.
352   BeforeStack.emplace_back();
353 
354   if (!isInteresting(IR, PassID, PassName))
355     return;
356 
357   // Save the IR representation on the stack.
358   T &Data = BeforeStack.back();
359   generateIRRepresentation(IR, PassID, Data);
360 }
361 
362 template <typename T>
363 void ChangeReporter<T>::handleIRAfterPass(Any IR, StringRef PassID,
364                                           StringRef PassName) {
365   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
366 
367   std::string Name = getIRName(IR);
368 
369   if (isIgnored(PassID)) {
370     if (VerboseMode)
371       handleIgnored(PassID, Name);
372   } else if (!isInteresting(IR, PassID, PassName)) {
373     if (VerboseMode)
374       handleFiltered(PassID, Name);
375   } else {
376     // Get the before rep from the stack
377     T &Before = BeforeStack.back();
378     // Create the after rep
379     T After;
380     generateIRRepresentation(IR, PassID, After);
381 
382     // Was there a change in IR?
383     if (Before == After) {
384       if (VerboseMode)
385         omitAfter(PassID, Name);
386     } else
387       handleAfter(PassID, Name, Before, After, IR);
388   }
389   BeforeStack.pop_back();
390 }
391 
392 template <typename T>
393 void ChangeReporter<T>::handleInvalidatedPass(StringRef PassID) {
394   assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
395 
396   // Always flag it as invalidated as we cannot determine when
397   // a pass for a filtered function is invalidated since we do not
398   // get the IR in the call.  Also, the output is just alternate
399   // forms of the banner anyway.
400   if (VerboseMode)
401     handleInvalidated(PassID);
402   BeforeStack.pop_back();
403 }
404 
405 template <typename T>
406 void ChangeReporter<T>::registerRequiredCallbacks(
407     PassInstrumentationCallbacks &PIC) {
408   PIC.registerBeforeNonSkippedPassCallback([&PIC, this](StringRef P, Any IR) {
409     saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P));
410   });
411 
412   PIC.registerAfterPassCallback(
413       [&PIC, this](StringRef P, Any IR, const PreservedAnalyses &) {
414         handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P));
415       });
416   PIC.registerAfterPassInvalidatedCallback(
417       [this](StringRef P, const PreservedAnalyses &) {
418         handleInvalidatedPass(P);
419       });
420 }
421 
422 template <typename T>
423 TextChangeReporter<T>::TextChangeReporter(bool Verbose)
424     : ChangeReporter<T>(Verbose), Out(dbgs()) {}
425 
426 template <typename T> void TextChangeReporter<T>::handleInitialIR(Any IR) {
427   // Always print the module.
428   // Unwrap and print directly to avoid filtering problems in general routines.
429   auto *M = unwrapModule(IR, /*Force=*/true);
430   assert(M && "Expected module to be unwrapped when forced.");
431   Out << "*** IR Dump At Start ***\n";
432   M->print(Out, nullptr);
433 }
434 
435 template <typename T>
436 void TextChangeReporter<T>::omitAfter(StringRef PassID, std::string &Name) {
437   Out << formatv("*** IR Dump After {0} on {1} omitted because no change ***\n",
438                  PassID, Name);
439 }
440 
441 template <typename T>
442 void TextChangeReporter<T>::handleInvalidated(StringRef PassID) {
443   Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
444 }
445 
446 template <typename T>
447 void TextChangeReporter<T>::handleFiltered(StringRef PassID,
448                                            std::string &Name) {
449   SmallString<20> Banner =
450       formatv("*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
451   Out << Banner;
452 }
453 
454 template <typename T>
455 void TextChangeReporter<T>::handleIgnored(StringRef PassID, std::string &Name) {
456   Out << formatv("*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
457 }
458 
459 IRChangedPrinter::~IRChangedPrinter() = default;
460 
461 void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
462   if (PrintChanged == ChangePrinter::Verbose ||
463       PrintChanged == ChangePrinter::Quiet)
464     TextChangeReporter<std::string>::registerRequiredCallbacks(PIC);
465 }
466 
467 void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID,
468                                                 std::string &Output) {
469   raw_string_ostream OS(Output);
470   unwrapAndPrint(OS, IR);
471   OS.str();
472 }
473 
474 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
475                                    const std::string &Before,
476                                    const std::string &After, Any) {
477   // Report the IR before the changes when requested.
478   if (PrintChangedBefore)
479     Out << "*** IR Dump Before " << PassID << " on " << Name << " ***\n"
480         << Before;
481 
482   // We might not get anything to print if we only want to print a specific
483   // function but it gets deleted.
484   if (After.empty()) {
485     Out << "*** IR Deleted After " << PassID << " on " << Name << " ***\n";
486     return;
487   }
488 
489   Out << "*** IR Dump After " << PassID << " on " << Name << " ***\n" << After;
490 }
491 
492 IRChangedTester::~IRChangedTester() {}
493 
494 void IRChangedTester::registerCallbacks(PassInstrumentationCallbacks &PIC) {
495   if (TestChanged != "")
496     TextChangeReporter<std::string>::registerRequiredCallbacks(PIC);
497 }
498 
499 void IRChangedTester::handleIR(const std::string &S, StringRef PassID) {
500   // Store the body into a temporary file
501   static SmallVector<int> FD{-1};
502   SmallVector<StringRef> SR{S};
503   static SmallVector<std::string> FileName{""};
504   if (auto Err = prepareTempFiles(FD, SR, FileName)) {
505     dbgs() << "Unable to create temporary file.";
506     return;
507   }
508   static ErrorOr<std::string> Exe = sys::findProgramByName(TestChanged);
509   if (!Exe) {
510     dbgs() << "Unable to find test-changed executable.";
511     return;
512   }
513 
514   StringRef Args[] = {TestChanged, FileName[0], PassID};
515   int Result = sys::ExecuteAndWait(*Exe, Args);
516   if (Result < 0) {
517     dbgs() << "Error executing test-changed executable.";
518     return;
519   }
520 
521   if (auto Err = cleanUpTempFiles(FileName))
522     dbgs() << "Unable to remove temporary file.";
523 }
524 
525 void IRChangedTester::handleInitialIR(Any IR) {
526   // Always test the initial module.
527   // Unwrap and print directly to avoid filtering problems in general routines.
528   std::string S;
529   generateIRRepresentation(IR, "Initial IR", S);
530   handleIR(S, "Initial IR");
531 }
532 
533 void IRChangedTester::omitAfter(StringRef PassID, std::string &Name) {}
534 void IRChangedTester::handleInvalidated(StringRef PassID) {}
535 void IRChangedTester::handleFiltered(StringRef PassID, std::string &Name) {}
536 void IRChangedTester::handleIgnored(StringRef PassID, std::string &Name) {}
537 void IRChangedTester::handleAfter(StringRef PassID, std::string &Name,
538                                   const std::string &Before,
539                                   const std::string &After, Any) {
540   handleIR(After, PassID);
541 }
542 
543 template <typename T>
544 void OrderedChangedData<T>::report(
545     const OrderedChangedData &Before, const OrderedChangedData &After,
546     function_ref<void(const T *, const T *)> HandlePair) {
547   const auto &BFD = Before.getData();
548   const auto &AFD = After.getData();
549   std::vector<std::string>::const_iterator BI = Before.getOrder().begin();
550   std::vector<std::string>::const_iterator BE = Before.getOrder().end();
551   std::vector<std::string>::const_iterator AI = After.getOrder().begin();
552   std::vector<std::string>::const_iterator AE = After.getOrder().end();
553 
554   auto HandlePotentiallyRemovedData = [&](std::string S) {
555     // The order in LLVM may have changed so check if still exists.
556     if (!AFD.count(S)) {
557       // This has been removed.
558       HandlePair(&BFD.find(*BI)->getValue(), nullptr);
559     }
560   };
561   auto HandleNewData = [&](std::vector<const T *> &Q) {
562     // Print out any queued up new sections
563     for (const T *NBI : Q)
564       HandlePair(nullptr, NBI);
565     Q.clear();
566   };
567 
568   // Print out the data in the after order, with before ones interspersed
569   // appropriately (ie, somewhere near where they were in the before list).
570   // Start at the beginning of both lists.  Loop through the
571   // after list.  If an element is common, then advance in the before list
572   // reporting the removed ones until the common one is reached.  Report any
573   // queued up new ones and then report the common one.  If an element is not
574   // common, then enqueue it for reporting.  When the after list is exhausted,
575   // loop through the before list, reporting any removed ones.  Finally,
576   // report the rest of the enqueued new ones.
577   std::vector<const T *> NewDataQueue;
578   while (AI != AE) {
579     if (!BFD.count(*AI)) {
580       // This section is new so place it in the queue.  This will cause it
581       // to be reported after deleted sections.
582       NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
583       ++AI;
584       continue;
585     }
586     // This section is in both; advance and print out any before-only
587     // until we get to it.
588     // It's possible that this section has moved to be later than before. This
589     // will mess up printing most blocks side by side, but it's a rare case and
590     // it's better than crashing.
591     while (BI != BE && *BI != *AI) {
592       HandlePotentiallyRemovedData(*BI);
593       ++BI;
594     }
595     // Report any new sections that were queued up and waiting.
596     HandleNewData(NewDataQueue);
597 
598     const T &AData = AFD.find(*AI)->getValue();
599     const T &BData = BFD.find(*AI)->getValue();
600     HandlePair(&BData, &AData);
601     if (BI != BE)
602       ++BI;
603     ++AI;
604   }
605 
606   // Check any remaining before sections to see if they have been removed
607   while (BI != BE) {
608     HandlePotentiallyRemovedData(*BI);
609     ++BI;
610   }
611 
612   HandleNewData(NewDataQueue);
613 }
614 
615 template <typename T>
616 void IRComparer<T>::compare(
617     bool CompareModule,
618     std::function<void(bool InModule, unsigned Minor,
619                        const FuncDataT<T> &Before, const FuncDataT<T> &After)>
620         CompareFunc) {
621   if (!CompareModule) {
622     // Just handle the single function.
623     assert(Before.getData().size() == 1 && After.getData().size() == 1 &&
624            "Expected only one function.");
625     CompareFunc(false, 0, Before.getData().begin()->getValue(),
626                 After.getData().begin()->getValue());
627     return;
628   }
629 
630   unsigned Minor = 0;
631   FuncDataT<T> Missing("");
632   IRDataT<T>::report(Before, After,
633                      [&](const FuncDataT<T> *B, const FuncDataT<T> *A) {
634                        assert((B || A) && "Both functions cannot be missing.");
635                        if (!B)
636                          B = &Missing;
637                        else if (!A)
638                          A = &Missing;
639                        CompareFunc(true, Minor++, *B, *A);
640                      });
641 }
642 
643 template <typename T> void IRComparer<T>::analyzeIR(Any IR, IRDataT<T> &Data) {
644   if (const Module *M = getModuleForComparison(IR)) {
645     // Create data for each existing/interesting function in the module.
646     for (const Function &F : *M)
647       generateFunctionData(Data, F);
648     return;
649   }
650 
651   const Function **FPtr = any_cast<const Function *>(&IR);
652   const Function *F = FPtr ? *FPtr : nullptr;
653   if (!F) {
654     const Loop **L = any_cast<const Loop *>(&IR);
655     assert(L && "Unknown IR unit.");
656     F = (*L)->getHeader()->getParent();
657   }
658   assert(F && "Unknown IR unit.");
659   generateFunctionData(Data, *F);
660 }
661 
662 template <typename T>
663 bool IRComparer<T>::generateFunctionData(IRDataT<T> &Data, const Function &F) {
664   if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
665     FuncDataT<T> FD(F.getEntryBlock().getName().str());
666     int I = 0;
667     for (const auto &B : F) {
668       std::string BBName = B.getName().str();
669       if (BBName.empty()) {
670         BBName = formatv("{0}", I);
671         ++I;
672       }
673       FD.getOrder().emplace_back(BBName);
674       FD.getData().insert({BBName, B});
675     }
676     Data.getOrder().emplace_back(F.getName());
677     Data.getData().insert({F.getName(), FD});
678     return true;
679   }
680   return false;
681 }
682 
683 PrintIRInstrumentation::~PrintIRInstrumentation() {
684   assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
685 }
686 
687 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
688   const Module *M = unwrapModule(IR);
689   ModuleDescStack.emplace_back(M, getIRName(IR), PassID);
690 }
691 
692 PrintIRInstrumentation::PrintModuleDesc
693 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
694   assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
695   PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
696   assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
697   return ModuleDesc;
698 }
699 
700 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
701   if (isIgnored(PassID))
702     return;
703 
704   // Saving Module for AfterPassInvalidated operations.
705   // Note: here we rely on a fact that we do not change modules while
706   // traversing the pipeline, so the latest captured module is good
707   // for all print operations that has not happen yet.
708   if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
709       shouldPrintAfterPass(PassID))
710     pushModuleDesc(PassID, IR);
711 
712   if (!shouldPrintIR(IR))
713     return;
714 
715   ++CurrentPassNumber;
716 
717   if (shouldPrintPassNumbers())
718     dbgs() << " Running pass " << CurrentPassNumber << " " << PassID << "\n";
719 
720   if (!shouldPrintBeforePass(PassID))
721     return;
722 
723   dbgs() << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
724          << " ***\n";
725   unwrapAndPrint(dbgs(), IR);
726 }
727 
728 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
729   if (isIgnored(PassID))
730     return;
731 
732   if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
733       !shouldPrintAtPassNumber())
734     return;
735 
736   const Module *M;
737   std::string IRName;
738   StringRef StoredPassID;
739   std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
740   assert(StoredPassID == PassID && "mismatched PassID");
741 
742   if (!shouldPrintIR(IR) || !shouldPrintAfterPass(PassID))
743     return;
744 
745   dbgs() << "*** IR Dump "
746          << (shouldPrintAtPassNumber()
747                  ? StringRef(formatv("At {0}-{1}", CurrentPassNumber, PassID))
748                  : StringRef(formatv("After {0}", PassID)))
749          << " on " << IRName << " ***\n";
750   unwrapAndPrint(dbgs(), IR);
751 }
752 
753 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
754   if (isIgnored(PassID))
755     return;
756 
757   if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
758       !shouldPrintAtPassNumber())
759     return;
760 
761   const Module *M;
762   std::string IRName;
763   StringRef StoredPassID;
764   std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
765   assert(StoredPassID == PassID && "mismatched PassID");
766   // Additional filtering (e.g. -filter-print-func) can lead to module
767   // printing being skipped.
768   if (!M || !shouldPrintAfterPass(PassID))
769     return;
770 
771   SmallString<20> Banner;
772   if (shouldPrintAtPassNumber())
773     Banner = formatv("*** IR Dump At {0}-{1} on {2} (invalidated) ***",
774                      CurrentPassNumber, PassID, IRName);
775   else
776     Banner = formatv("*** IR Dump After {0} on {1} (invalidated) ***",
777                      PassID, IRName);
778   dbgs() << Banner << "\n";
779   printIR(dbgs(), M);
780 }
781 
782 bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
783   if (shouldPrintBeforeAll())
784     return true;
785 
786   StringRef PassName = PIC->getPassNameForClassName(PassID);
787   return is_contained(printBeforePasses(), PassName);
788 }
789 
790 bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
791   if (shouldPrintAfterAll())
792     return true;
793 
794   if (shouldPrintAtPassNumber() && CurrentPassNumber == PrintAtPassNumber)
795     return true;
796 
797   StringRef PassName = PIC->getPassNameForClassName(PassID);
798   return is_contained(printAfterPasses(), PassName);
799 }
800 
801 bool PrintIRInstrumentation::shouldPrintPassNumbers() {
802   return PrintPassNumbers;
803 }
804 
805 bool PrintIRInstrumentation::shouldPrintAtPassNumber() {
806   return PrintAtPassNumber > 0;
807 }
808 
809 void PrintIRInstrumentation::registerCallbacks(
810     PassInstrumentationCallbacks &PIC) {
811   this->PIC = &PIC;
812 
813   // BeforePass callback is not just for printing, it also saves a Module
814   // for later use in AfterPassInvalidated.
815   if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
816       shouldPrintBeforeSomePass() || shouldPrintAfterSomePass())
817     PIC.registerBeforeNonSkippedPassCallback(
818         [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
819 
820   if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
821       shouldPrintAfterSomePass()) {
822     PIC.registerAfterPassCallback(
823         [this](StringRef P, Any IR, const PreservedAnalyses &) {
824           this->printAfterPass(P, IR);
825         });
826     PIC.registerAfterPassInvalidatedCallback(
827         [this](StringRef P, const PreservedAnalyses &) {
828           this->printAfterPassInvalidated(P);
829         });
830   }
831 }
832 
833 void OptNoneInstrumentation::registerCallbacks(
834     PassInstrumentationCallbacks &PIC) {
835   PIC.registerShouldRunOptionalPassCallback(
836       [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
837 }
838 
839 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
840   const Function **FPtr = any_cast<const Function *>(&IR);
841   const Function *F = FPtr ? *FPtr : nullptr;
842   if (!F) {
843     if (const auto **L = any_cast<const Loop *>(&IR))
844       F = (*L)->getHeader()->getParent();
845   }
846   bool ShouldRun = !(F && F->hasOptNone());
847   if (!ShouldRun && DebugLogging) {
848     errs() << "Skipping pass " << PassID << " on " << F->getName()
849            << " due to optnone attribute\n";
850   }
851   return ShouldRun;
852 }
853 
854 bool OptPassGateInstrumentation::shouldRun(StringRef PassName, Any IR) {
855   if (isIgnored(PassName))
856     return true;
857 
858   bool ShouldRun =
859       Context.getOptPassGate().shouldRunPass(PassName, getIRName(IR));
860   if (!ShouldRun && !this->HasWrittenIR && !OptBisectPrintIRPath.empty()) {
861     // FIXME: print IR if limit is higher than number of opt-bisect
862     // invocations
863     this->HasWrittenIR = true;
864     const Module *M = unwrapModule(IR, /*Force=*/true);
865     assert((M && &M->getContext() == &Context) && "Missing/Mismatching Module");
866     std::error_code EC;
867     raw_fd_ostream OS(OptBisectPrintIRPath, EC);
868     if (EC)
869       report_fatal_error(errorCodeToError(EC));
870     M->print(OS, nullptr);
871   }
872   return ShouldRun;
873 }
874 
875 void OptPassGateInstrumentation::registerCallbacks(
876     PassInstrumentationCallbacks &PIC) {
877   OptPassGate &PassGate = Context.getOptPassGate();
878   if (!PassGate.isEnabled())
879     return;
880 
881   PIC.registerShouldRunOptionalPassCallback([this](StringRef PassName, Any IR) {
882     return this->shouldRun(PassName, IR);
883   });
884 }
885 
886 raw_ostream &PrintPassInstrumentation::print() {
887   if (Opts.Indent) {
888     assert(Indent >= 0);
889     dbgs().indent(Indent);
890   }
891   return dbgs();
892 }
893 
894 void PrintPassInstrumentation::registerCallbacks(
895     PassInstrumentationCallbacks &PIC) {
896   if (!Enabled)
897     return;
898 
899   std::vector<StringRef> SpecialPasses;
900   if (!Opts.Verbose) {
901     SpecialPasses.emplace_back("PassManager");
902     SpecialPasses.emplace_back("PassAdaptor");
903   }
904 
905   PIC.registerBeforeSkippedPassCallback([this, SpecialPasses](StringRef PassID,
906                                                               Any IR) {
907     assert(!isSpecialPass(PassID, SpecialPasses) &&
908            "Unexpectedly skipping special pass");
909 
910     print() << "Skipping pass: " << PassID << " on " << getIRName(IR) << "\n";
911   });
912   PIC.registerBeforeNonSkippedPassCallback([this, SpecialPasses](
913                                                StringRef PassID, Any IR) {
914     if (isSpecialPass(PassID, SpecialPasses))
915       return;
916 
917     auto &OS = print();
918     OS << "Running pass: " << PassID << " on " << getIRName(IR);
919     if (const auto **F = any_cast<const Function *>(&IR)) {
920       unsigned Count = (*F)->getInstructionCount();
921       OS << " (" << Count << " instruction";
922       if (Count != 1)
923         OS << 's';
924       OS << ')';
925     } else if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR)) {
926       int Count = (*C)->size();
927       OS << " (" << Count << " node";
928       if (Count != 1)
929         OS << 's';
930       OS << ')';
931     }
932     OS << "\n";
933     Indent += 2;
934   });
935   PIC.registerAfterPassCallback(
936       [this, SpecialPasses](StringRef PassID, Any IR,
937                             const PreservedAnalyses &) {
938         if (isSpecialPass(PassID, SpecialPasses))
939           return;
940 
941         Indent -= 2;
942       });
943   PIC.registerAfterPassInvalidatedCallback(
944       [this, SpecialPasses](StringRef PassID, Any IR) {
945         if (isSpecialPass(PassID, SpecialPasses))
946           return;
947 
948         Indent -= 2;
949       });
950 
951   if (!Opts.SkipAnalyses) {
952     PIC.registerBeforeAnalysisCallback([this](StringRef PassID, Any IR) {
953       print() << "Running analysis: " << PassID << " on " << getIRName(IR)
954               << "\n";
955       Indent += 2;
956     });
957     PIC.registerAfterAnalysisCallback(
958         [this](StringRef PassID, Any IR) { Indent -= 2; });
959     PIC.registerAnalysisInvalidatedCallback([this](StringRef PassID, Any IR) {
960       print() << "Invalidating analysis: " << PassID << " on " << getIRName(IR)
961               << "\n";
962     });
963     PIC.registerAnalysesClearedCallback([this](StringRef IRName) {
964       print() << "Clearing all analysis results for: " << IRName << "\n";
965     });
966   }
967 }
968 
969 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
970                                              bool TrackBBLifetime) {
971   if (TrackBBLifetime)
972     BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
973   for (const auto &BB : *F) {
974     if (BBGuards)
975       BBGuards->try_emplace(intptr_t(&BB), &BB);
976     for (const auto *Succ : successors(&BB)) {
977       Graph[&BB][Succ]++;
978       if (BBGuards)
979         BBGuards->try_emplace(intptr_t(Succ), Succ);
980     }
981   }
982 }
983 
984 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
985   if (BB->hasName()) {
986     out << BB->getName() << "<" << BB << ">";
987     return;
988   }
989 
990   if (!BB->getParent()) {
991     out << "unnamed_removed<" << BB << ">";
992     return;
993   }
994 
995   if (BB->isEntryBlock()) {
996     out << "entry"
997         << "<" << BB << ">";
998     return;
999   }
1000 
1001   unsigned FuncOrderBlockNum = 0;
1002   for (auto &FuncBB : *BB->getParent()) {
1003     if (&FuncBB == BB)
1004       break;
1005     FuncOrderBlockNum++;
1006   }
1007   out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
1008 }
1009 
1010 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
1011                                                         const CFG &Before,
1012                                                         const CFG &After) {
1013   assert(!After.isPoisoned());
1014   if (Before.isPoisoned()) {
1015     out << "Some blocks were deleted\n";
1016     return;
1017   }
1018 
1019   // Find and print graph differences.
1020   if (Before.Graph.size() != After.Graph.size())
1021     out << "Different number of non-leaf basic blocks: before="
1022         << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
1023 
1024   for (auto &BB : Before.Graph) {
1025     auto BA = After.Graph.find(BB.first);
1026     if (BA == After.Graph.end()) {
1027       out << "Non-leaf block ";
1028       printBBName(out, BB.first);
1029       out << " is removed (" << BB.second.size() << " successors)\n";
1030     }
1031   }
1032 
1033   for (auto &BA : After.Graph) {
1034     auto BB = Before.Graph.find(BA.first);
1035     if (BB == Before.Graph.end()) {
1036       out << "Non-leaf block ";
1037       printBBName(out, BA.first);
1038       out << " is added (" << BA.second.size() << " successors)\n";
1039       continue;
1040     }
1041 
1042     if (BB->second == BA.second)
1043       continue;
1044 
1045     out << "Different successors of block ";
1046     printBBName(out, BA.first);
1047     out << " (unordered):\n";
1048     out << "- before (" << BB->second.size() << "): ";
1049     for (auto &SuccB : BB->second) {
1050       printBBName(out, SuccB.first);
1051       if (SuccB.second != 1)
1052         out << "(" << SuccB.second << "), ";
1053       else
1054         out << ", ";
1055     }
1056     out << "\n";
1057     out << "- after (" << BA.second.size() << "): ";
1058     for (auto &SuccA : BA.second) {
1059       printBBName(out, SuccA.first);
1060       if (SuccA.second != 1)
1061         out << "(" << SuccA.second << "), ";
1062       else
1063         out << ", ";
1064     }
1065     out << "\n";
1066   }
1067 }
1068 
1069 // PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
1070 // passes, that reported they kept CFG analyses up-to-date, did not actually
1071 // change CFG. This check is done as follows. Before every functional pass in
1072 // BeforeNonSkippedPassCallback a CFG snapshot (an instance of
1073 // PreservedCFGCheckerInstrumentation::CFG) is requested from
1074 // FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
1075 // functional pass finishes and reports that CFGAnalyses or AllAnalyses are
1076 // up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
1077 // available) is checked to be equal to a freshly created CFG snapshot.
1078 struct PreservedCFGCheckerAnalysis
1079     : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {
1080   friend AnalysisInfoMixin<PreservedCFGCheckerAnalysis>;
1081 
1082   static AnalysisKey Key;
1083 
1084 public:
1085   /// Provide the result type for this analysis pass.
1086   using Result = PreservedCFGCheckerInstrumentation::CFG;
1087 
1088   /// Run the analysis pass over a function and produce CFG.
1089   Result run(Function &F, FunctionAnalysisManager &FAM) {
1090     return Result(&F, /* TrackBBLifetime */ true);
1091   }
1092 };
1093 
1094 AnalysisKey PreservedCFGCheckerAnalysis::Key;
1095 
1096 struct PreservedFunctionHashAnalysis
1097     : public AnalysisInfoMixin<PreservedFunctionHashAnalysis> {
1098   static AnalysisKey Key;
1099 
1100   struct FunctionHash {
1101     uint64_t Hash;
1102   };
1103 
1104   using Result = FunctionHash;
1105 
1106   Result run(Function &F, FunctionAnalysisManager &FAM) {
1107     return Result{StructuralHash(F)};
1108   }
1109 };
1110 
1111 AnalysisKey PreservedFunctionHashAnalysis::Key;
1112 
1113 struct PreservedModuleHashAnalysis
1114     : public AnalysisInfoMixin<PreservedModuleHashAnalysis> {
1115   static AnalysisKey Key;
1116 
1117   struct ModuleHash {
1118     uint64_t Hash;
1119   };
1120 
1121   using Result = ModuleHash;
1122 
1123   Result run(Module &F, ModuleAnalysisManager &FAM) {
1124     return Result{StructuralHash(F)};
1125   }
1126 };
1127 
1128 AnalysisKey PreservedModuleHashAnalysis::Key;
1129 
1130 bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
1131     Function &F, const PreservedAnalyses &PA,
1132     FunctionAnalysisManager::Invalidator &) {
1133   auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>();
1134   return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
1135            PAC.preservedSet<CFGAnalyses>());
1136 }
1137 
1138 static SmallVector<Function *, 1> GetFunctions(Any IR) {
1139   SmallVector<Function *, 1> Functions;
1140 
1141   if (const auto **MaybeF = any_cast<const Function *>(&IR)) {
1142     Functions.push_back(*const_cast<Function **>(MaybeF));
1143   } else if (const auto **MaybeM = any_cast<const Module *>(&IR)) {
1144     for (Function &F : **const_cast<Module **>(MaybeM))
1145       Functions.push_back(&F);
1146   }
1147   return Functions;
1148 }
1149 
1150 void PreservedCFGCheckerInstrumentation::registerCallbacks(
1151     PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM) {
1152   if (!VerifyAnalysisInvalidation)
1153     return;
1154 
1155   bool Registered = false;
1156   PIC.registerBeforeNonSkippedPassCallback([this, &MAM, Registered](
1157                                                StringRef P, Any IR) mutable {
1158 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1159     assert(&PassStack.emplace_back(P));
1160 #endif
1161     (void)this;
1162 
1163     auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(
1164                        *const_cast<Module *>(unwrapModule(IR, /*Force=*/true)))
1165                     .getManager();
1166     if (!Registered) {
1167       FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); });
1168       FAM.registerPass([&] { return PreservedFunctionHashAnalysis(); });
1169       MAM.registerPass([&] { return PreservedModuleHashAnalysis(); });
1170       Registered = true;
1171     }
1172 
1173     for (Function *F : GetFunctions(IR)) {
1174       // Make sure a fresh CFG snapshot is available before the pass.
1175       FAM.getResult<PreservedCFGCheckerAnalysis>(*F);
1176       FAM.getResult<PreservedFunctionHashAnalysis>(*F);
1177     }
1178 
1179     if (auto *MaybeM = any_cast<const Module *>(&IR)) {
1180       Module &M = **const_cast<Module **>(MaybeM);
1181       MAM.getResult<PreservedModuleHashAnalysis>(M);
1182     }
1183   });
1184 
1185   PIC.registerAfterPassInvalidatedCallback(
1186       [this](StringRef P, const PreservedAnalyses &PassPA) {
1187 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1188         assert(PassStack.pop_back_val() == P &&
1189                "Before and After callbacks must correspond");
1190 #endif
1191         (void)this;
1192       });
1193 
1194   PIC.registerAfterPassCallback([this, &MAM](StringRef P, Any IR,
1195                                              const PreservedAnalyses &PassPA) {
1196 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1197     assert(PassStack.pop_back_val() == P &&
1198            "Before and After callbacks must correspond");
1199 #endif
1200     (void)this;
1201 
1202     // We have to get the FAM via the MAM, rather than directly use a passed in
1203     // FAM because if MAM has not cached the FAM, it won't invalidate function
1204     // analyses in FAM.
1205     auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(
1206                        *const_cast<Module *>(unwrapModule(IR, /*Force=*/true)))
1207                     .getManager();
1208 
1209     for (Function *F : GetFunctions(IR)) {
1210       if (auto *HashBefore =
1211               FAM.getCachedResult<PreservedFunctionHashAnalysis>(*F)) {
1212         if (HashBefore->Hash != StructuralHash(*F)) {
1213           report_fatal_error(formatv(
1214               "Function @{0} changed by {1} without invalidating analyses",
1215               F->getName(), P));
1216         }
1217       }
1218 
1219       auto CheckCFG = [](StringRef Pass, StringRef FuncName,
1220                          const CFG &GraphBefore, const CFG &GraphAfter) {
1221         if (GraphAfter == GraphBefore)
1222           return;
1223 
1224         dbgs()
1225             << "Error: " << Pass
1226             << " does not invalidate CFG analyses but CFG changes detected in "
1227                "function @"
1228             << FuncName << ":\n";
1229         CFG::printDiff(dbgs(), GraphBefore, GraphAfter);
1230         report_fatal_error(Twine("CFG unexpectedly changed by ", Pass));
1231       };
1232 
1233       if (auto *GraphBefore =
1234               FAM.getCachedResult<PreservedCFGCheckerAnalysis>(*F))
1235         CheckCFG(P, F->getName(), *GraphBefore,
1236                  CFG(F, /* TrackBBLifetime */ false));
1237     }
1238     if (auto *MaybeM = any_cast<const Module *>(&IR)) {
1239       Module &M = **const_cast<Module **>(MaybeM);
1240       if (auto *HashBefore =
1241               MAM.getCachedResult<PreservedModuleHashAnalysis>(M)) {
1242         if (HashBefore->Hash != StructuralHash(M)) {
1243           report_fatal_error(formatv(
1244               "Module changed by {0} without invalidating analyses", P));
1245         }
1246       }
1247     }
1248   });
1249 }
1250 
1251 void VerifyInstrumentation::registerCallbacks(
1252     PassInstrumentationCallbacks &PIC) {
1253   PIC.registerAfterPassCallback(
1254       [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
1255         if (isIgnored(P) || P == "VerifierPass")
1256           return;
1257         const Function **FPtr = any_cast<const Function *>(&IR);
1258         const Function *F = FPtr ? *FPtr : nullptr;
1259         if (!F) {
1260           if (const auto **L = any_cast<const Loop *>(&IR))
1261             F = (*L)->getHeader()->getParent();
1262         }
1263 
1264         if (F) {
1265           if (DebugLogging)
1266             dbgs() << "Verifying function " << F->getName() << "\n";
1267 
1268           if (verifyFunction(*F, &errs()))
1269             report_fatal_error("Broken function found, compilation aborted!");
1270         } else {
1271           const Module **MPtr = any_cast<const Module *>(&IR);
1272           const Module *M = MPtr ? *MPtr : nullptr;
1273           if (!M) {
1274             if (const auto **C = any_cast<const LazyCallGraph::SCC *>(&IR))
1275               M = (*C)->begin()->getFunction().getParent();
1276           }
1277 
1278           if (M) {
1279             if (DebugLogging)
1280               dbgs() << "Verifying module " << M->getName() << "\n";
1281 
1282             if (verifyModule(*M, &errs()))
1283               report_fatal_error("Broken module found, compilation aborted!");
1284           }
1285         }
1286       });
1287 }
1288 
1289 InLineChangePrinter::~InLineChangePrinter() = default;
1290 
1291 void InLineChangePrinter::generateIRRepresentation(Any IR,
1292                                                    StringRef PassID,
1293                                                    IRDataT<EmptyData> &D) {
1294   IRComparer<EmptyData>::analyzeIR(IR, D);
1295 }
1296 
1297 void InLineChangePrinter::handleAfter(StringRef PassID, std::string &Name,
1298                                       const IRDataT<EmptyData> &Before,
1299                                       const IRDataT<EmptyData> &After,
1300                                       Any IR) {
1301   SmallString<20> Banner =
1302       formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);
1303   Out << Banner;
1304   IRComparer<EmptyData>(Before, After)
1305       .compare(getModuleForComparison(IR),
1306                [&](bool InModule, unsigned Minor,
1307                    const FuncDataT<EmptyData> &Before,
1308                    const FuncDataT<EmptyData> &After) -> void {
1309                  handleFunctionCompare(Name, "", PassID, " on ", InModule,
1310                                        Minor, Before, After);
1311                });
1312   Out << "\n";
1313 }
1314 
1315 void InLineChangePrinter::handleFunctionCompare(
1316     StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
1317     bool InModule, unsigned Minor, const FuncDataT<EmptyData> &Before,
1318     const FuncDataT<EmptyData> &After) {
1319   // Print a banner when this is being shown in the context of a module
1320   if (InModule)
1321     Out << "\n*** IR for function " << Name << " ***\n";
1322 
1323   FuncDataT<EmptyData>::report(
1324       Before, After,
1325       [&](const BlockDataT<EmptyData> *B, const BlockDataT<EmptyData> *A) {
1326         StringRef BStr = B ? B->getBody() : "\n";
1327         StringRef AStr = A ? A->getBody() : "\n";
1328         const std::string Removed =
1329             UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";
1330         const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";
1331         const std::string NoChange = " %l\n";
1332         Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1333       });
1334 }
1335 
1336 void InLineChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
1337   if (PrintChanged == ChangePrinter::DiffVerbose ||
1338       PrintChanged == ChangePrinter::DiffQuiet ||
1339       PrintChanged == ChangePrinter::ColourDiffVerbose ||
1340       PrintChanged == ChangePrinter::ColourDiffQuiet)
1341     TextChangeReporter<IRDataT<EmptyData>>::registerRequiredCallbacks(PIC);
1342 }
1343 
1344 TimeProfilingPassesHandler::TimeProfilingPassesHandler() {}
1345 
1346 void TimeProfilingPassesHandler::registerCallbacks(
1347     PassInstrumentationCallbacks &PIC) {
1348   if (!getTimeTraceProfilerInstance())
1349     return;
1350   PIC.registerBeforeNonSkippedPassCallback(
1351       [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
1352   PIC.registerAfterPassCallback(
1353       [this](StringRef P, Any IR, const PreservedAnalyses &) {
1354         this->runAfterPass();
1355       },
1356       true);
1357   PIC.registerAfterPassInvalidatedCallback(
1358       [this](StringRef P, const PreservedAnalyses &) { this->runAfterPass(); },
1359       true);
1360   PIC.registerBeforeAnalysisCallback(
1361       [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
1362   PIC.registerAfterAnalysisCallback(
1363       [this](StringRef P, Any IR) { this->runAfterPass(); }, true);
1364 }
1365 
1366 void TimeProfilingPassesHandler::runBeforePass(StringRef PassID, Any IR) {
1367   timeTraceProfilerBegin(PassID, getIRName(IR));
1368 }
1369 
1370 void TimeProfilingPassesHandler::runAfterPass() { timeTraceProfilerEnd(); }
1371 
1372 namespace {
1373 
1374 class DisplayNode;
1375 class DotCfgDiffDisplayGraph;
1376 
1377 // Base class for a node or edge in the dot-cfg-changes graph.
1378 class DisplayElement {
1379 public:
1380   // Is this in before, after, or both?
1381   StringRef getColour() const { return Colour; }
1382 
1383 protected:
1384   DisplayElement(StringRef Colour) : Colour(Colour) {}
1385   const StringRef Colour;
1386 };
1387 
1388 // An edge representing a transition between basic blocks in the
1389 // dot-cfg-changes graph.
1390 class DisplayEdge : public DisplayElement {
1391 public:
1392   DisplayEdge(std::string Value, DisplayNode &Node, StringRef Colour)
1393       : DisplayElement(Colour), Value(Value), Node(Node) {}
1394   // The value on which the transition is made.
1395   std::string getValue() const { return Value; }
1396   // The node (representing a basic block) reached by this transition.
1397   const DisplayNode &getDestinationNode() const { return Node; }
1398 
1399 protected:
1400   std::string Value;
1401   const DisplayNode &Node;
1402 };
1403 
1404 // A node in the dot-cfg-changes graph which represents a basic block.
1405 class DisplayNode : public DisplayElement {
1406 public:
1407   // \p C is the content for the node, \p T indicates the colour for the
1408   // outline of the node
1409   DisplayNode(std::string Content, StringRef Colour)
1410       : DisplayElement(Colour), Content(Content) {}
1411 
1412   // Iterator to the child nodes.  Required by GraphWriter.
1413   using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1414   ChildIterator children_begin() const { return Children.cbegin(); }
1415   ChildIterator children_end() const { return Children.cend(); }
1416 
1417   // Iterator for the edges.  Required by GraphWriter.
1418   using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1419   EdgeIterator edges_begin() const { return EdgePtrs.cbegin(); }
1420   EdgeIterator edges_end() const { return EdgePtrs.cend(); }
1421 
1422   // Create an edge to \p Node on value \p Value, with colour \p Colour.
1423   void createEdge(StringRef Value, DisplayNode &Node, StringRef Colour);
1424 
1425   // Return the content of this node.
1426   std::string getContent() const { return Content; }
1427 
1428   // Return the edge to node \p S.
1429   const DisplayEdge &getEdge(const DisplayNode &To) const {
1430     assert(EdgeMap.find(&To) != EdgeMap.end() && "Expected to find edge.");
1431     return *EdgeMap.find(&To)->second;
1432   }
1433 
1434   // Return the value for the transition to basic block \p S.
1435   // Required by GraphWriter.
1436   std::string getEdgeSourceLabel(const DisplayNode &Sink) const {
1437     return getEdge(Sink).getValue();
1438   }
1439 
1440   void createEdgeMap();
1441 
1442 protected:
1443   const std::string Content;
1444 
1445   // Place to collect all of the edges.  Once they are all in the vector,
1446   // the vector will not reallocate so then we can use pointers to them,
1447   // which are required by the graph writing routines.
1448   std::vector<DisplayEdge> Edges;
1449 
1450   std::vector<DisplayEdge *> EdgePtrs;
1451   std::unordered_set<DisplayNode *> Children;
1452   std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1453 
1454   // Safeguard adding of edges.
1455   bool AllEdgesCreated = false;
1456 };
1457 
1458 // Class representing a difference display (corresponds to a pdf file).
1459 class DotCfgDiffDisplayGraph {
1460 public:
1461   DotCfgDiffDisplayGraph(std::string Name) : GraphName(Name) {}
1462 
1463   // Generate the file into \p DotFile.
1464   void generateDotFile(StringRef DotFile);
1465 
1466   // Iterator to the nodes.  Required by GraphWriter.
1467   using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1468   NodeIterator nodes_begin() const {
1469     assert(NodeGenerationComplete && "Unexpected children iterator creation");
1470     return NodePtrs.cbegin();
1471   }
1472   NodeIterator nodes_end() const {
1473     assert(NodeGenerationComplete && "Unexpected children iterator creation");
1474     return NodePtrs.cend();
1475   }
1476 
1477   // Record the index of the entry node.  At this point, we can build up
1478   // vectors of pointers that are required by the graph routines.
1479   void setEntryNode(unsigned N) {
1480     // At this point, there will be no new nodes.
1481     assert(!NodeGenerationComplete && "Unexpected node creation");
1482     NodeGenerationComplete = true;
1483     for (auto &N : Nodes)
1484       NodePtrs.emplace_back(&N);
1485 
1486     EntryNode = NodePtrs[N];
1487   }
1488 
1489   // Create a node.
1490   void createNode(std::string C, StringRef Colour) {
1491     assert(!NodeGenerationComplete && "Unexpected node creation");
1492     Nodes.emplace_back(C, Colour);
1493   }
1494   // Return the node at index \p N to avoid problems with vectors reallocating.
1495   DisplayNode &getNode(unsigned N) {
1496     assert(N < Nodes.size() && "Node is out of bounds");
1497     return Nodes[N];
1498   }
1499   unsigned size() const {
1500     assert(NodeGenerationComplete && "Unexpected children iterator creation");
1501     return Nodes.size();
1502   }
1503 
1504   // Return the name of the graph.  Required by GraphWriter.
1505   std::string getGraphName() const { return GraphName; }
1506 
1507   // Return the string representing the differences for basic block \p Node.
1508   // Required by GraphWriter.
1509   std::string getNodeLabel(const DisplayNode &Node) const {
1510     return Node.getContent();
1511   }
1512 
1513   // Return a string with colour information for Dot.  Required by GraphWriter.
1514   std::string getNodeAttributes(const DisplayNode &Node) const {
1515     return attribute(Node.getColour());
1516   }
1517 
1518   // Return a string with colour information for Dot.  Required by GraphWriter.
1519   std::string getEdgeColorAttr(const DisplayNode &From,
1520                                const DisplayNode &To) const {
1521     return attribute(From.getEdge(To).getColour());
1522   }
1523 
1524   // Get the starting basic block.  Required by GraphWriter.
1525   DisplayNode *getEntryNode() const {
1526     assert(NodeGenerationComplete && "Unexpected children iterator creation");
1527     return EntryNode;
1528   }
1529 
1530 protected:
1531   // Return the string containing the colour to use as a Dot attribute.
1532   std::string attribute(StringRef Colour) const {
1533     return "color=" + Colour.str();
1534   }
1535 
1536   bool NodeGenerationComplete = false;
1537   const std::string GraphName;
1538   std::vector<DisplayNode> Nodes;
1539   std::vector<DisplayNode *> NodePtrs;
1540   DisplayNode *EntryNode = nullptr;
1541 };
1542 
1543 void DisplayNode::createEdge(StringRef Value, DisplayNode &Node,
1544                              StringRef Colour) {
1545   assert(!AllEdgesCreated && "Expected to be able to still create edges.");
1546   Edges.emplace_back(Value.str(), Node, Colour);
1547   Children.insert(&Node);
1548 }
1549 
1550 void DisplayNode::createEdgeMap() {
1551   // No more edges will be added so we can now use pointers to the edges
1552   // as the vector will not grow and reallocate.
1553   AllEdgesCreated = true;
1554   for (auto &E : Edges)
1555     EdgeMap.insert({&E.getDestinationNode(), &E});
1556 }
1557 
1558 class DotCfgDiffNode;
1559 class DotCfgDiff;
1560 
1561 // A class representing a basic block in the Dot difference graph.
1562 class DotCfgDiffNode {
1563 public:
1564   DotCfgDiffNode() = delete;
1565 
1566   // Create a node in Dot difference graph \p G representing the basic block
1567   // represented by \p BD with colour \p Colour (where it exists).
1568   DotCfgDiffNode(DotCfgDiff &G, unsigned N, const BlockDataT<DCData> &BD,
1569                  StringRef Colour)
1570       : Graph(G), N(N), Data{&BD, nullptr}, Colour(Colour) {}
1571   DotCfgDiffNode(const DotCfgDiffNode &DN)
1572       : Graph(DN.Graph), N(DN.N), Data{DN.Data[0], DN.Data[1]},
1573         Colour(DN.Colour), EdgesMap(DN.EdgesMap), Children(DN.Children),
1574         Edges(DN.Edges) {}
1575 
1576   unsigned getIndex() const { return N; }
1577 
1578   // The label of the basic block
1579   StringRef getLabel() const {
1580     assert(Data[0] && "Expected Data[0] to be set.");
1581     return Data[0]->getLabel();
1582   }
1583   // Return the colour for this block
1584   StringRef getColour() const { return Colour; }
1585   // Change this basic block from being only in before to being common.
1586   // Save the pointer to \p Other.
1587   void setCommon(const BlockDataT<DCData> &Other) {
1588     assert(!Data[1] && "Expected only one block datum");
1589     Data[1] = &Other;
1590     Colour = CommonColour;
1591   }
1592   // Add an edge to \p E of colour {\p Value, \p Colour}.
1593   void addEdge(unsigned E, StringRef Value, StringRef Colour) {
1594     // This is a new edge or it is an edge being made common.
1595     assert((EdgesMap.count(E) == 0 || Colour == CommonColour) &&
1596            "Unexpected edge count and color.");
1597     EdgesMap[E] = {Value.str(), Colour};
1598   }
1599   // Record the children and create edges.
1600   void finalize(DotCfgDiff &G);
1601 
1602   // Return the colour of the edge to node \p S.
1603   StringRef getEdgeColour(const unsigned S) const {
1604     assert(EdgesMap.count(S) == 1 && "Expected to find edge.");
1605     return EdgesMap.at(S).second;
1606   }
1607 
1608   // Return the string representing the basic block.
1609   std::string getBodyContent() const;
1610 
1611   void createDisplayEdges(DotCfgDiffDisplayGraph &Graph, unsigned DisplayNode,
1612                           std::map<const unsigned, unsigned> &NodeMap) const;
1613 
1614 protected:
1615   DotCfgDiff &Graph;
1616   const unsigned N;
1617   const BlockDataT<DCData> *Data[2];
1618   StringRef Colour;
1619   std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1620   std::vector<unsigned> Children;
1621   std::vector<unsigned> Edges;
1622 };
1623 
1624 // Class representing the difference graph between two functions.
1625 class DotCfgDiff {
1626 public:
1627   // \p Title is the title given to the graph.  \p EntryNodeName is the
1628   // entry node for the function.  \p Before and \p After are the before
1629   // after versions of the function, respectively.  \p Dir is the directory
1630   // in which to store the results.
1631   DotCfgDiff(StringRef Title, const FuncDataT<DCData> &Before,
1632              const FuncDataT<DCData> &After);
1633 
1634   DotCfgDiff(const DotCfgDiff &) = delete;
1635   DotCfgDiff &operator=(const DotCfgDiff &) = delete;
1636 
1637   DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1638                                             StringRef EntryNodeName);
1639 
1640   // Return a string consisting of the labels for the \p Source and \p Sink.
1641   // The combination allows distinguishing changing transitions on the
1642   // same value (ie, a transition went to X before and goes to Y after).
1643   // Required by GraphWriter.
1644   StringRef getEdgeSourceLabel(const unsigned &Source,
1645                                const unsigned &Sink) const {
1646     std::string S =
1647         getNode(Source).getLabel().str() + " " + getNode(Sink).getLabel().str();
1648     assert(EdgeLabels.count(S) == 1 && "Expected to find edge label.");
1649     return EdgeLabels.find(S)->getValue();
1650   }
1651 
1652   // Return the number of basic blocks (nodes).  Required by GraphWriter.
1653   unsigned size() const { return Nodes.size(); }
1654 
1655   const DotCfgDiffNode &getNode(unsigned N) const {
1656     assert(N < Nodes.size() && "Unexpected index for node reference");
1657     return Nodes[N];
1658   }
1659 
1660 protected:
1661   // Return the string surrounded by HTML to make it the appropriate colour.
1662   std::string colourize(std::string S, StringRef Colour) const;
1663 
1664   void createNode(StringRef Label, const BlockDataT<DCData> &BD, StringRef C) {
1665     unsigned Pos = Nodes.size();
1666     Nodes.emplace_back(*this, Pos, BD, C);
1667     NodePosition.insert({Label, Pos});
1668   }
1669 
1670   // TODO Nodes should probably be a StringMap<DotCfgDiffNode> after the
1671   // display graph is separated out, which would remove the need for
1672   // NodePosition.
1673   std::vector<DotCfgDiffNode> Nodes;
1674   StringMap<unsigned> NodePosition;
1675   const std::string GraphName;
1676 
1677   StringMap<std::string> EdgeLabels;
1678 };
1679 
1680 std::string DotCfgDiffNode::getBodyContent() const {
1681   if (Colour == CommonColour) {
1682     assert(Data[1] && "Expected Data[1] to be set.");
1683 
1684     StringRef SR[2];
1685     for (unsigned I = 0; I < 2; ++I) {
1686       SR[I] = Data[I]->getBody();
1687       // drop initial '\n' if present
1688       if (SR[I][0] == '\n')
1689         SR[I] = SR[I].drop_front();
1690       // drop predecessors as they can be big and are redundant
1691       SR[I] = SR[I].drop_until([](char C) { return C == '\n'; }).drop_front();
1692     }
1693 
1694     SmallString<80> OldLineFormat = formatv(
1695         "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", BeforeColour);
1696     SmallString<80> NewLineFormat = formatv(
1697         "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", AfterColour);
1698     SmallString<80> UnchangedLineFormat = formatv(
1699         "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", CommonColour);
1700     std::string Diff = Data[0]->getLabel().str();
1701     Diff += ":\n<BR align=\"left\"/>" +
1702             doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1703                          OldLineFormat, NewLineFormat, UnchangedLineFormat);
1704 
1705     // Diff adds in some empty colour changes which are not valid HTML
1706     // so remove them.  Colours are all lowercase alpha characters (as
1707     // listed in https://graphviz.org/pdf/dotguide.pdf).
1708     Regex R("<FONT COLOR=\"\\w+\"></FONT>");
1709     while (true) {
1710       std::string Error;
1711       std::string S = R.sub("", Diff, &Error);
1712       if (Error != "")
1713         return Error;
1714       if (S == Diff)
1715         return Diff;
1716       Diff = S;
1717     }
1718     llvm_unreachable("Should not get here");
1719   }
1720 
1721   // Put node out in the appropriate colour.
1722   assert(!Data[1] && "Data[1] is set unexpectedly.");
1723   std::string Body = makeHTMLReady(Data[0]->getBody());
1724   const StringRef BS = Body;
1725   StringRef BS1 = BS;
1726   // Drop leading newline, if present.
1727   if (BS.front() == '\n')
1728     BS1 = BS1.drop_front(1);
1729   // Get label.
1730   StringRef Label = BS1.take_until([](char C) { return C == ':'; });
1731   // drop predecessors as they can be big and are redundant
1732   BS1 = BS1.drop_until([](char C) { return C == '\n'; }).drop_front();
1733 
1734   std::string S = "<FONT COLOR=\"" + Colour.str() + "\">" + Label.str() + ":";
1735 
1736   // align each line to the left.
1737   while (BS1.size()) {
1738     S.append("<BR align=\"left\"/>");
1739     StringRef Line = BS1.take_until([](char C) { return C == '\n'; });
1740     S.append(Line.str());
1741     BS1 = BS1.drop_front(Line.size() + 1);
1742   }
1743   S.append("<BR align=\"left\"/></FONT>");
1744   return S;
1745 }
1746 
1747 std::string DotCfgDiff::colourize(std::string S, StringRef Colour) const {
1748   if (S.length() == 0)
1749     return S;
1750   return "<FONT COLOR=\"" + Colour.str() + "\">" + S + "</FONT>";
1751 }
1752 
1753 DotCfgDiff::DotCfgDiff(StringRef Title, const FuncDataT<DCData> &Before,
1754                        const FuncDataT<DCData> &After)
1755     : GraphName(Title.str()) {
1756   StringMap<StringRef> EdgesMap;
1757 
1758   // Handle each basic block in the before IR.
1759   for (auto &B : Before.getData()) {
1760     StringRef Label = B.getKey();
1761     const BlockDataT<DCData> &BD = B.getValue();
1762     createNode(Label, BD, BeforeColour);
1763 
1764     // Create transitions with names made up of the from block label, the value
1765     // on which the transition is made and the to block label.
1766     for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1767                                                 E = BD.getData().end();
1768          Sink != E; ++Sink) {
1769       std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +
1770                         BD.getData().getSuccessorLabel(Sink->getKey()).str();
1771       EdgesMap.insert({Key, BeforeColour});
1772     }
1773   }
1774 
1775   // Handle each basic block in the after IR
1776   for (auto &A : After.getData()) {
1777     StringRef Label = A.getKey();
1778     const BlockDataT<DCData> &BD = A.getValue();
1779     unsigned C = NodePosition.count(Label);
1780     if (C == 0)
1781       // This only exists in the after IR.  Create the node.
1782       createNode(Label, BD, AfterColour);
1783     else {
1784       assert(C == 1 && "Unexpected multiple nodes.");
1785       Nodes[NodePosition[Label]].setCommon(BD);
1786     }
1787     // Add in the edges between the nodes (as common or only in after).
1788     for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1789                                                 E = BD.getData().end();
1790          Sink != E; ++Sink) {
1791       std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +
1792                         BD.getData().getSuccessorLabel(Sink->getKey()).str();
1793       unsigned C = EdgesMap.count(Key);
1794       if (C == 0)
1795         EdgesMap.insert({Key, AfterColour});
1796       else {
1797         EdgesMap[Key] = CommonColour;
1798       }
1799     }
1800   }
1801 
1802   // Now go through the map of edges and add them to the node.
1803   for (auto &E : EdgesMap) {
1804     // Extract the source, sink and value from the edge key.
1805     StringRef S = E.getKey();
1806     auto SP1 = S.rsplit(' ');
1807     auto &SourceSink = SP1.first;
1808     auto SP2 = SourceSink.split(' ');
1809     StringRef Source = SP2.first;
1810     StringRef Sink = SP2.second;
1811     StringRef Value = SP1.second;
1812 
1813     assert(NodePosition.count(Source) == 1 && "Expected to find node.");
1814     DotCfgDiffNode &SourceNode = Nodes[NodePosition[Source]];
1815     assert(NodePosition.count(Sink) == 1 && "Expected to find node.");
1816     unsigned SinkNode = NodePosition[Sink];
1817     StringRef Colour = E.second;
1818 
1819     // Look for an edge from Source to Sink
1820     if (EdgeLabels.count(SourceSink) == 0)
1821       EdgeLabels.insert({SourceSink, colourize(Value.str(), Colour)});
1822     else {
1823       StringRef V = EdgeLabels.find(SourceSink)->getValue();
1824       std::string NV = colourize(V.str() + " " + Value.str(), Colour);
1825       Colour = CommonColour;
1826       EdgeLabels[SourceSink] = NV;
1827     }
1828     SourceNode.addEdge(SinkNode, Value, Colour);
1829   }
1830   for (auto &I : Nodes)
1831     I.finalize(*this);
1832 }
1833 
1834 DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(StringRef Title,
1835                                                       StringRef EntryNodeName) {
1836   assert(NodePosition.count(EntryNodeName) == 1 &&
1837          "Expected to find entry block in map.");
1838   unsigned Entry = NodePosition[EntryNodeName];
1839   assert(Entry < Nodes.size() && "Expected to find entry node");
1840   DotCfgDiffDisplayGraph G(Title.str());
1841 
1842   std::map<const unsigned, unsigned> NodeMap;
1843 
1844   int EntryIndex = -1;
1845   unsigned Index = 0;
1846   for (auto &I : Nodes) {
1847     if (I.getIndex() == Entry)
1848       EntryIndex = Index;
1849     G.createNode(I.getBodyContent(), I.getColour());
1850     NodeMap.insert({I.getIndex(), Index++});
1851   }
1852   assert(EntryIndex >= 0 && "Expected entry node index to be set.");
1853   G.setEntryNode(EntryIndex);
1854 
1855   for (auto &I : NodeMap) {
1856     unsigned SourceNode = I.first;
1857     unsigned DisplayNode = I.second;
1858     getNode(SourceNode).createDisplayEdges(G, DisplayNode, NodeMap);
1859   }
1860   return G;
1861 }
1862 
1863 void DotCfgDiffNode::createDisplayEdges(
1864     DotCfgDiffDisplayGraph &DisplayGraph, unsigned DisplayNodeIndex,
1865     std::map<const unsigned, unsigned> &NodeMap) const {
1866 
1867   DisplayNode &SourceDisplayNode = DisplayGraph.getNode(DisplayNodeIndex);
1868 
1869   for (auto I : Edges) {
1870     unsigned SinkNodeIndex = I;
1871     StringRef Colour = getEdgeColour(SinkNodeIndex);
1872     const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1873 
1874     StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1875     DisplayNode &SinkDisplayNode = DisplayGraph.getNode(SinkNode->getIndex());
1876     SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1877   }
1878   SourceDisplayNode.createEdgeMap();
1879 }
1880 
1881 void DotCfgDiffNode::finalize(DotCfgDiff &G) {
1882   for (auto E : EdgesMap) {
1883     Children.emplace_back(E.first);
1884     Edges.emplace_back(E.first);
1885   }
1886 }
1887 
1888 } // namespace
1889 
1890 namespace llvm {
1891 
1892 template <> struct GraphTraits<DotCfgDiffDisplayGraph *> {
1893   using NodeRef = const DisplayNode *;
1894   using ChildIteratorType = DisplayNode::ChildIterator;
1895   using nodes_iterator = DotCfgDiffDisplayGraph::NodeIterator;
1896   using EdgeRef = const DisplayEdge *;
1897   using ChildEdgeIterator = DisplayNode::EdgeIterator;
1898 
1899   static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G) {
1900     return G->getEntryNode();
1901   }
1902   static ChildIteratorType child_begin(NodeRef N) {
1903     return N->children_begin();
1904   }
1905   static ChildIteratorType child_end(NodeRef N) { return N->children_end(); }
1906   static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G) {
1907     return G->nodes_begin();
1908   }
1909   static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G) {
1910     return G->nodes_end();
1911   }
1912   static ChildEdgeIterator child_edge_begin(NodeRef N) {
1913     return N->edges_begin();
1914   }
1915   static ChildEdgeIterator child_edge_end(NodeRef N) { return N->edges_end(); }
1916   static NodeRef edge_dest(EdgeRef E) { return &E->getDestinationNode(); }
1917   static unsigned size(const DotCfgDiffDisplayGraph *G) { return G->size(); }
1918 };
1919 
1920 template <>
1921 struct DOTGraphTraits<DotCfgDiffDisplayGraph *> : public DefaultDOTGraphTraits {
1922   explicit DOTGraphTraits(bool Simple = false)
1923       : DefaultDOTGraphTraits(Simple) {}
1924 
1925   static bool renderNodesUsingHTML() { return true; }
1926   static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData) {
1927     return DiffData->getGraphName();
1928   }
1929   static std::string
1930   getGraphProperties(const DotCfgDiffDisplayGraph *DiffData) {
1931     return "\tsize=\"190, 190\";\n";
1932   }
1933   static std::string getNodeLabel(const DisplayNode *Node,
1934                                   const DotCfgDiffDisplayGraph *DiffData) {
1935     return DiffData->getNodeLabel(*Node);
1936   }
1937   static std::string getNodeAttributes(const DisplayNode *Node,
1938                                        const DotCfgDiffDisplayGraph *DiffData) {
1939     return DiffData->getNodeAttributes(*Node);
1940   }
1941   static std::string getEdgeSourceLabel(const DisplayNode *From,
1942                                         DisplayNode::ChildIterator &To) {
1943     return From->getEdgeSourceLabel(**To);
1944   }
1945   static std::string getEdgeAttributes(const DisplayNode *From,
1946                                        DisplayNode::ChildIterator &To,
1947                                        const DotCfgDiffDisplayGraph *DiffData) {
1948     return DiffData->getEdgeColorAttr(*From, **To);
1949   }
1950 };
1951 
1952 } // namespace llvm
1953 
1954 namespace {
1955 
1956 void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
1957   std::error_code EC;
1958   raw_fd_ostream OutStream(DotFile, EC);
1959   if (EC) {
1960     errs() << "Error: " << EC.message() << "\n";
1961     return;
1962   }
1963   WriteGraph(OutStream, this, false);
1964   OutStream.flush();
1965   OutStream.close();
1966 }
1967 
1968 } // namespace
1969 
1970 namespace llvm {
1971 
1972 DCData::DCData(const BasicBlock &B) {
1973   // Build up transition labels.
1974   const Instruction *Term = B.getTerminator();
1975   if (const BranchInst *Br = dyn_cast<const BranchInst>(Term))
1976     if (Br->isUnconditional())
1977       addSuccessorLabel(Br->getSuccessor(0)->getName().str(), "");
1978     else {
1979       addSuccessorLabel(Br->getSuccessor(0)->getName().str(), "true");
1980       addSuccessorLabel(Br->getSuccessor(1)->getName().str(), "false");
1981     }
1982   else if (const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
1983     addSuccessorLabel(Sw->case_default()->getCaseSuccessor()->getName().str(),
1984                       "default");
1985     for (auto &C : Sw->cases()) {
1986       assert(C.getCaseValue() && "Expected to find case value.");
1987       SmallString<20> Value = formatv("{0}", C.getCaseValue()->getSExtValue());
1988       addSuccessorLabel(C.getCaseSuccessor()->getName().str(), Value);
1989     }
1990   } else
1991     for (const_succ_iterator I = succ_begin(&B), E = succ_end(&B); I != E; ++I)
1992       addSuccessorLabel((*I)->getName().str(), "");
1993 }
1994 
1995 DotCfgChangeReporter::DotCfgChangeReporter(bool Verbose)
1996     : ChangeReporter<IRDataT<DCData>>(Verbose) {}
1997 
1998 void DotCfgChangeReporter::handleFunctionCompare(
1999     StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
2000     bool InModule, unsigned Minor, const FuncDataT<DCData> &Before,
2001     const FuncDataT<DCData> &After) {
2002   assert(HTML && "Expected outstream to be set");
2003   SmallString<8> Extender;
2004   SmallString<8> Number;
2005   // Handle numbering and file names.
2006   if (InModule) {
2007     Extender = formatv("{0}_{1}", N, Minor);
2008     Number = formatv("{0}.{1}", N, Minor);
2009   } else {
2010     Extender = formatv("{0}", N);
2011     Number = formatv("{0}", N);
2012   }
2013   // Create a temporary file name for the dot file.
2014   SmallVector<char, 128> SV;
2015   sys::fs::createUniquePath("cfgdot-%%%%%%.dot", SV, true);
2016   std::string DotFile = Twine(SV).str();
2017 
2018   SmallString<20> PDFFileName = formatv("diff_{0}.pdf", Extender);
2019   SmallString<200> Text;
2020 
2021   Text = formatv("{0}.{1}{2}{3}{4}", Number, Prefix, makeHTMLReady(PassID),
2022                  Divider, Name);
2023 
2024   DotCfgDiff Diff(Text, Before, After);
2025   std::string EntryBlockName = After.getEntryBlockName();
2026   // Use the before entry block if the after entry block was removed.
2027   if (EntryBlockName == "")
2028     EntryBlockName = Before.getEntryBlockName();
2029   assert(EntryBlockName != "" && "Expected to find entry block");
2030 
2031   DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2032   DG.generateDotFile(DotFile);
2033 
2034   *HTML << genHTML(Text, DotFile, PDFFileName);
2035   std::error_code EC = sys::fs::remove(DotFile);
2036   if (EC)
2037     errs() << "Error: " << EC.message() << "\n";
2038 }
2039 
2040 std::string DotCfgChangeReporter::genHTML(StringRef Text, StringRef DotFile,
2041                                           StringRef PDFFileName) {
2042   SmallString<20> PDFFile = formatv("{0}/{1}", DotCfgDir, PDFFileName);
2043   // Create the PDF file.
2044   static ErrorOr<std::string> DotExe = sys::findProgramByName(DotBinary);
2045   if (!DotExe)
2046     return "Unable to find dot executable.";
2047 
2048   StringRef Args[] = {DotBinary, "-Tpdf", "-o", PDFFile, DotFile};
2049   int Result = sys::ExecuteAndWait(*DotExe, Args, std::nullopt);
2050   if (Result < 0)
2051     return "Error executing system dot.";
2052 
2053   // Create the HTML tag refering to the PDF file.
2054   SmallString<200> S = formatv(
2055       "  <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2056   return S.c_str();
2057 }
2058 
2059 void DotCfgChangeReporter::handleInitialIR(Any IR) {
2060   assert(HTML && "Expected outstream to be set");
2061   *HTML << "<button type=\"button\" class=\"collapsible\">0. "
2062         << "Initial IR (by function)</button>\n"
2063         << "<div class=\"content\">\n"
2064         << "  <p>\n";
2065   // Create representation of IR
2066   IRDataT<DCData> Data;
2067   IRComparer<DCData>::analyzeIR(IR, Data);
2068   // Now compare it against itself, which will have everything the
2069   // same and will generate the files.
2070   IRComparer<DCData>(Data, Data)
2071       .compare(getModuleForComparison(IR),
2072                [&](bool InModule, unsigned Minor,
2073                    const FuncDataT<DCData> &Before,
2074                    const FuncDataT<DCData> &After) -> void {
2075                  handleFunctionCompare("", " ", "Initial IR", "", InModule,
2076                                        Minor, Before, After);
2077                });
2078   *HTML << "  </p>\n"
2079         << "</div><br/>\n";
2080   ++N;
2081 }
2082 
2083 void DotCfgChangeReporter::generateIRRepresentation(Any IR, StringRef PassID,
2084                                                     IRDataT<DCData> &Data) {
2085   IRComparer<DCData>::analyzeIR(IR, Data);
2086 }
2087 
2088 void DotCfgChangeReporter::omitAfter(StringRef PassID, std::string &Name) {
2089   assert(HTML && "Expected outstream to be set");
2090   SmallString<20> Banner =
2091       formatv("  <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2092               N, makeHTMLReady(PassID), Name);
2093   *HTML << Banner;
2094   ++N;
2095 }
2096 
2097 void DotCfgChangeReporter::handleAfter(StringRef PassID, std::string &Name,
2098                                        const IRDataT<DCData> &Before,
2099                                        const IRDataT<DCData> &After, Any IR) {
2100   assert(HTML && "Expected outstream to be set");
2101   IRComparer<DCData>(Before, After)
2102       .compare(getModuleForComparison(IR),
2103                [&](bool InModule, unsigned Minor,
2104                    const FuncDataT<DCData> &Before,
2105                    const FuncDataT<DCData> &After) -> void {
2106                  handleFunctionCompare(Name, " Pass ", PassID, " on ", InModule,
2107                                        Minor, Before, After);
2108                });
2109   *HTML << "    </p></div>\n";
2110   ++N;
2111 }
2112 
2113 void DotCfgChangeReporter::handleInvalidated(StringRef PassID) {
2114   assert(HTML && "Expected outstream to be set");
2115   SmallString<20> Banner =
2116       formatv("  <a>{0}. {1} invalidated</a><br/>\n", N, makeHTMLReady(PassID));
2117   *HTML << Banner;
2118   ++N;
2119 }
2120 
2121 void DotCfgChangeReporter::handleFiltered(StringRef PassID, std::string &Name) {
2122   assert(HTML && "Expected outstream to be set");
2123   SmallString<20> Banner =
2124       formatv("  <a>{0}. Pass {1} on {2} filtered out</a><br/>\n", N,
2125               makeHTMLReady(PassID), Name);
2126   *HTML << Banner;
2127   ++N;
2128 }
2129 
2130 void DotCfgChangeReporter::handleIgnored(StringRef PassID, std::string &Name) {
2131   assert(HTML && "Expected outstream to be set");
2132   SmallString<20> Banner = formatv("  <a>{0}. {1} on {2} ignored</a><br/>\n", N,
2133                                    makeHTMLReady(PassID), Name);
2134   *HTML << Banner;
2135   ++N;
2136 }
2137 
2138 bool DotCfgChangeReporter::initializeHTML() {
2139   std::error_code EC;
2140   HTML = std::make_unique<raw_fd_ostream>(DotCfgDir + "/passes.html", EC);
2141   if (EC) {
2142     HTML = nullptr;
2143     return false;
2144   }
2145 
2146   *HTML << "<!doctype html>"
2147         << "<html>"
2148         << "<head>"
2149         << "<style>.collapsible { "
2150         << "background-color: #777;"
2151         << " color: white;"
2152         << " cursor: pointer;"
2153         << " padding: 18px;"
2154         << " width: 100%;"
2155         << " border: none;"
2156         << " text-align: left;"
2157         << " outline: none;"
2158         << " font-size: 15px;"
2159         << "} .active, .collapsible:hover {"
2160         << " background-color: #555;"
2161         << "} .content {"
2162         << " padding: 0 18px;"
2163         << " display: none;"
2164         << " overflow: hidden;"
2165         << " background-color: #f1f1f1;"
2166         << "}"
2167         << "</style>"
2168         << "<title>passes.html</title>"
2169         << "</head>\n"
2170         << "<body>";
2171   return true;
2172 }
2173 
2174 DotCfgChangeReporter::~DotCfgChangeReporter() {
2175   if (!HTML)
2176     return;
2177   *HTML
2178       << "<script>var coll = document.getElementsByClassName(\"collapsible\");"
2179       << "var i;"
2180       << "for (i = 0; i < coll.length; i++) {"
2181       << "coll[i].addEventListener(\"click\", function() {"
2182       << " this.classList.toggle(\"active\");"
2183       << " var content = this.nextElementSibling;"
2184       << " if (content.style.display === \"block\"){"
2185       << " content.style.display = \"none\";"
2186       << " }"
2187       << " else {"
2188       << " content.style.display= \"block\";"
2189       << " }"
2190       << " });"
2191       << " }"
2192       << "</script>"
2193       << "</body>"
2194       << "</html>\n";
2195   HTML->flush();
2196   HTML->close();
2197 }
2198 
2199 void DotCfgChangeReporter::registerCallbacks(
2200     PassInstrumentationCallbacks &PIC) {
2201   if (PrintChanged == ChangePrinter::DotCfgVerbose ||
2202        PrintChanged == ChangePrinter::DotCfgQuiet) {
2203     SmallString<128> OutputDir;
2204     sys::fs::expand_tilde(DotCfgDir, OutputDir);
2205     sys::fs::make_absolute(OutputDir);
2206     assert(!OutputDir.empty() && "expected output dir to be non-empty");
2207     DotCfgDir = OutputDir.c_str();
2208     if (initializeHTML()) {
2209       ChangeReporter<IRDataT<DCData>>::registerRequiredCallbacks(PIC);
2210       return;
2211     }
2212     dbgs() << "Unable to open output stream for -cfg-dot-changed\n";
2213   }
2214 }
2215 
2216 StandardInstrumentations::StandardInstrumentations(
2217     LLVMContext &Context, bool DebugLogging, bool VerifyEach,
2218     PrintPassOptions PrintPassOpts)
2219     : PrintPass(DebugLogging, PrintPassOpts),
2220       OptNone(DebugLogging),
2221       OptPassGate(Context),
2222       PrintChangedIR(PrintChanged == ChangePrinter::Verbose),
2223       PrintChangedDiff(PrintChanged == ChangePrinter::DiffVerbose ||
2224                            PrintChanged == ChangePrinter::ColourDiffVerbose,
2225                        PrintChanged == ChangePrinter::ColourDiffVerbose ||
2226                            PrintChanged == ChangePrinter::ColourDiffQuiet),
2227       WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
2228       Verify(DebugLogging), VerifyEach(VerifyEach) {}
2229 
2230 PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
2231     nullptr;
2232 
2233 void PrintCrashIRInstrumentation::reportCrashIR() {
2234   if (!PrintOnCrashPath.empty()) {
2235     std::error_code EC;
2236     raw_fd_ostream Out(PrintOnCrashPath, EC);
2237     if (EC)
2238       report_fatal_error(errorCodeToError(EC));
2239     Out << SavedIR;
2240   } else {
2241     dbgs() << SavedIR;
2242   }
2243 }
2244 
2245 void PrintCrashIRInstrumentation::SignalHandler(void *) {
2246   // Called by signal handlers so do not lock here
2247   // Is the PrintCrashIRInstrumentation still alive?
2248   if (!CrashReporter)
2249     return;
2250 
2251   assert((PrintOnCrash || !PrintOnCrashPath.empty()) &&
2252          "Did not expect to get here without option set.");
2253   CrashReporter->reportCrashIR();
2254 }
2255 
2256 PrintCrashIRInstrumentation::~PrintCrashIRInstrumentation() {
2257   if (!CrashReporter)
2258     return;
2259 
2260   assert((PrintOnCrash || !PrintOnCrashPath.empty()) &&
2261          "Did not expect to get here without option set.");
2262   CrashReporter = nullptr;
2263 }
2264 
2265 void PrintCrashIRInstrumentation::registerCallbacks(
2266     PassInstrumentationCallbacks &PIC) {
2267   if ((!PrintOnCrash && PrintOnCrashPath.empty()) || CrashReporter)
2268     return;
2269 
2270   sys::AddSignalHandler(SignalHandler, nullptr);
2271   CrashReporter = this;
2272 
2273   PIC.registerBeforeNonSkippedPassCallback(
2274       [&PIC, this](StringRef PassID, Any IR) {
2275         SavedIR.clear();
2276         raw_string_ostream OS(SavedIR);
2277         OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
2278                       llvm::forcePrintModuleIR() ? "Module " : "", PassID);
2279         if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
2280           OS << " Filtered Out ***\n";
2281           return;
2282         }
2283         OS << " Started ***\n";
2284         unwrapAndPrint(OS, IR);
2285       });
2286 }
2287 
2288 void StandardInstrumentations::registerCallbacks(
2289     PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {
2290   PrintIR.registerCallbacks(PIC);
2291   PrintPass.registerCallbacks(PIC);
2292   TimePasses.registerCallbacks(PIC);
2293   OptNone.registerCallbacks(PIC);
2294   OptPassGate.registerCallbacks(PIC);
2295   PrintChangedIR.registerCallbacks(PIC);
2296   PseudoProbeVerification.registerCallbacks(PIC);
2297   if (VerifyEach)
2298     Verify.registerCallbacks(PIC);
2299   PrintChangedDiff.registerCallbacks(PIC);
2300   WebsiteChangeReporter.registerCallbacks(PIC);
2301   ChangeTester.registerCallbacks(PIC);
2302   PrintCrashIR.registerCallbacks(PIC);
2303   if (MAM)
2304     PreservedCFGChecker.registerCallbacks(PIC, *MAM);
2305 
2306   // TimeProfiling records the pass running time cost.
2307   // Its 'BeforePassCallback' can be appended at the tail of all the
2308   // BeforeCallbacks by calling `registerCallbacks` in the end.
2309   // Its 'AfterPassCallback' is put at the front of all the
2310   // AfterCallbacks by its `registerCallbacks`. This is necessary
2311   // to ensure that other callbacks are not included in the timings.
2312   TimeProfilingPasses.registerCallbacks(PIC);
2313 }
2314 
2315 template class ChangeReporter<std::string>;
2316 template class TextChangeReporter<std::string>;
2317 
2318 template class BlockDataT<EmptyData>;
2319 template class FuncDataT<EmptyData>;
2320 template class IRDataT<EmptyData>;
2321 template class ChangeReporter<IRDataT<EmptyData>>;
2322 template class TextChangeReporter<IRDataT<EmptyData>>;
2323 template class IRComparer<EmptyData>;
2324 
2325 } // namespace llvm
2326