LLVM  16.0.0git
StandardInstrumentations.cpp
Go to the documentation of this file.
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 
16 #include "llvm/ADT/Any.h"
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Analysis/LoopInfo.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Function.h"
25 #include "llvm/IR/Module.h"
27 #include "llvm/IR/PassManager.h"
28 #include "llvm/IR/PrintPasses.h"
29 #include "llvm/IR/Verifier.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/Error.h"
37 #include "llvm/Support/Program.h"
38 #include "llvm/Support/Regex.h"
39 #include "llvm/Support/Signals.h"
41 #include <unordered_map>
42 #include <unordered_set>
43 #include <utility>
44 #include <vector>
45 
46 using namespace llvm;
47 
49  "verify-cfg-preserved", cl::Hidden,
50 #ifdef NDEBUG
51  cl::init(false)
52 #else
53  cl::init(true)
54 #endif
55  );
56 
57 // An option that supports the -print-changed option. See
58 // the description for -print-changed for an explanation of the use
59 // of this option. Note that this option has no effect without -print-changed.
60 static cl::opt<bool>
61  PrintChangedBefore("print-before-changed",
62  cl::desc("Print before passes that change them"),
63  cl::init(false), cl::Hidden);
64 
65 // An option for specifying the dot used by
66 // print-changed=[dot-cfg | dot-cfg-quiet]
68  DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"),
69  cl::desc("system dot used by change reporters"));
70 
71 // An option that determines the colour used for elements that are only
72 // in the before part. Must be a colour named in appendix J of
73 // https://graphviz.org/pdf/dotguide.pdf
75  BeforeColour("dot-cfg-before-color",
76  cl::desc("Color for dot-cfg before elements"), cl::Hidden,
77  cl::init("red"));
78 // An option that determines the colour used for elements that are only
79 // in the after part. Must be a colour named in appendix J of
80 // https://graphviz.org/pdf/dotguide.pdf
82  AfterColour("dot-cfg-after-color",
83  cl::desc("Color for dot-cfg after elements"), cl::Hidden,
84  cl::init("forestgreen"));
85 // An option that determines the colour used for elements that are in both
86 // the before and after parts. Must be a colour named in appendix J of
87 // https://graphviz.org/pdf/dotguide.pdf
89  CommonColour("dot-cfg-common-color",
90  cl::desc("Color for dot-cfg common elements"), cl::Hidden,
91  cl::init("black"));
92 
93 // An option that determines where the generated website file (named
94 // passes.html) and the associated pdf files (named diff_*.pdf) are saved.
96  "dot-cfg-dir",
97  cl::desc("Generate dot files into specified directory for changed IRs"),
98  cl::Hidden, cl::init("./"));
99 
100 // An option to print the IR that was being processed when a pass crashes.
101 static cl::opt<bool>
102  PrintCrashIR("print-on-crash",
103  cl::desc("Print the last form of the IR before crash"),
104  cl::Hidden);
105 
107  "opt-bisect-print-ir-path",
108  cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden);
109 
110 namespace {
111 
112 /// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
113 /// certain global filters. Will never return nullptr if \p Force is true.
114 const Module *unwrapModule(Any IR, bool Force = false) {
115  if (any_isa<const Module *>(IR))
116  return any_cast<const Module *>(IR);
117 
118  if (any_isa<const Function *>(IR)) {
119  const Function *F = any_cast<const Function *>(IR);
120  if (!Force && !isFunctionInPrintList(F->getName()))
121  return nullptr;
122 
123  return F->getParent();
124  }
125 
126  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
127  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
128  for (const LazyCallGraph::Node &N : *C) {
129  const Function &F = N.getFunction();
130  if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
131  return F.getParent();
132  }
133  }
134  assert(!Force && "Expected a module");
135  return nullptr;
136  }
137 
138  if (any_isa<const Loop *>(IR)) {
139  const Loop *L = any_cast<const Loop *>(IR);
140  const Function *F = L->getHeader()->getParent();
141  if (!Force && !isFunctionInPrintList(F->getName()))
142  return nullptr;
143  return F->getParent();
144  }
145 
146  llvm_unreachable("Unknown IR unit");
147 }
148 
149 void printIR(raw_ostream &OS, const Function *F) {
150  if (!isFunctionInPrintList(F->getName()))
151  return;
152  OS << *F;
153 }
154 
155 void printIR(raw_ostream &OS, const Module *M) {
157  M->print(OS, nullptr);
158  } else {
159  for (const auto &F : M->functions()) {
160  printIR(OS, &F);
161  }
162  }
163 }
164 
165 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C) {
166  for (const LazyCallGraph::Node &N : *C) {
167  const Function &F = N.getFunction();
168  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
169  F.print(OS);
170  }
171  }
172 }
173 
174 void printIR(raw_ostream &OS, const Loop *L) {
175  const Function *F = L->getHeader()->getParent();
176  if (!isFunctionInPrintList(F->getName()))
177  return;
178  printLoop(const_cast<Loop &>(*L), OS);
179 }
180 
181 std::string getIRName(Any IR) {
182  if (any_isa<const Module *>(IR))
183  return "[module]";
184 
185  if (any_isa<const Function *>(IR)) {
186  const Function *F = any_cast<const Function *>(IR);
187  return F->getName().str();
188  }
189 
190  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
191  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
192  return C->getName();
193  }
194 
195  if (any_isa<const Loop *>(IR)) {
196  const Loop *L = any_cast<const Loop *>(IR);
197  return L->getName().str();
198  }
199 
200  llvm_unreachable("Unknown wrapped IR type");
201 }
202 
203 bool moduleContainsFilterPrintFunc(const Module &M) {
204  return any_of(M.functions(),
205  [](const Function &F) {
206  return isFunctionInPrintList(F.getName());
207  }) ||
209 }
210 
211 bool sccContainsFilterPrintFunc(const LazyCallGraph::SCC &C) {
212  return any_of(C,
213  [](const LazyCallGraph::Node &N) {
214  return isFunctionInPrintList(N.getName());
215  }) ||
217 }
218 
219 bool shouldPrintIR(Any IR) {
220  if (any_isa<const Module *>(IR)) {
221  const Module *M = any_cast<const Module *>(IR);
222  return moduleContainsFilterPrintFunc(*M);
223  }
224 
225  if (any_isa<const Function *>(IR)) {
226  const Function *F = any_cast<const Function *>(IR);
227  return isFunctionInPrintList(F->getName());
228  }
229 
230  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
231  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
232  return sccContainsFilterPrintFunc(*C);
233  }
234 
235  if (any_isa<const Loop *>(IR)) {
236  const Loop *L = any_cast<const Loop *>(IR);
238  }
239  llvm_unreachable("Unknown wrapped IR type");
240 }
241 
242 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
243 /// llvm::Any and does actual print job.
244 void unwrapAndPrint(raw_ostream &OS, Any IR) {
245  if (!shouldPrintIR(IR))
246  return;
247 
248  if (forcePrintModuleIR()) {
249  auto *M = unwrapModule(IR);
250  assert(M && "should have unwrapped module");
251  printIR(OS, M);
252  return;
253  }
254 
255  if (any_isa<const Module *>(IR)) {
256  const Module *M = any_cast<const Module *>(IR);
257  printIR(OS, M);
258  return;
259  }
260 
261  if (any_isa<const Function *>(IR)) {
262  const Function *F = any_cast<const Function *>(IR);
263  printIR(OS, F);
264  return;
265  }
266 
267  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
268  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
269  printIR(OS, C);
270  return;
271  }
272 
273  if (any_isa<const Loop *>(IR)) {
274  const Loop *L = any_cast<const Loop *>(IR);
275  printIR(OS, L);
276  return;
277  }
278  llvm_unreachable("Unknown wrapped IR type");
279 }
280 
281 // Return true when this is a pass for which changes should be ignored
282 bool isIgnored(StringRef PassID) {
283  return isSpecialPass(PassID,
284  {"PassManager", "PassAdaptor", "AnalysisManagerProxy",
285  "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass"});
286 }
287 
288 std::string makeHTMLReady(StringRef SR) {
289  std::string S;
290  while (true) {
291  StringRef Clean =
292  SR.take_until([](char C) { return C == '<' || C == '>'; });
293  S.append(Clean.str());
294  SR = SR.drop_front(Clean.size());
295  if (SR.size() == 0)
296  return S;
297  S.append(SR[0] == '<' ? "&lt;" : "&gt;");
298  SR = SR.drop_front();
299  }
300  llvm_unreachable("problems converting string to HTML");
301 }
302 
303 // Return the module when that is the appropriate level of comparison for \p IR.
304 const Module *getModuleForComparison(Any IR) {
305  if (any_isa<const Module *>(IR))
306  return any_cast<const Module *>(IR);
307  if (any_isa<const LazyCallGraph::SCC *>(IR))
308  return any_cast<const LazyCallGraph::SCC *>(IR)
309  ->begin()
310  ->getFunction()
311  .getParent();
312  return nullptr;
313 }
314 
315 bool isInterestingFunction(const Function &F) {
316  return isFunctionInPrintList(F.getName());
317 }
318 
319 // Return true when this is a pass on IR for which printing
320 // of changes is desired.
322  if (isIgnored(PassID) || !isPassInPrintList(PassName))
323  return false;
324  if (any_isa<const Function *>(IR))
325  return isInterestingFunction(*any_cast<const Function *>(IR));
326  return true;
327 }
328 
329 } // namespace
330 
331 template <typename T> ChangeReporter<T>::~ChangeReporter() {
332  assert(BeforeStack.empty() && "Problem with Change Printer stack.");
333 }
334 
335 template <typename T>
338  // Always need to place something on the stack because invalidated passes
339  // are not given the IR so it cannot be determined whether the pass was for
340  // something that was filtered out.
341  BeforeStack.emplace_back();
342 
343  if (!isInteresting(IR, PassID, PassName))
344  return;
345  // Is this the initial IR?
346  if (InitialIR) {
347  InitialIR = false;
348  if (VerboseMode)
349  handleInitialIR(IR);
350  }
351 
352  // Save the IR representation on the stack.
353  T &Data = BeforeStack.back();
354  generateIRRepresentation(IR, PassID, Data);
355 }
356 
357 template <typename T>
360  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
361 
362  std::string Name = getIRName(IR);
363 
364  if (isIgnored(PassID)) {
365  if (VerboseMode)
366  handleIgnored(PassID, Name);
367  } else if (!isInteresting(IR, PassID, PassName)) {
368  if (VerboseMode)
369  handleFiltered(PassID, Name);
370  } else {
371  // Get the before rep from the stack
372  T &Before = BeforeStack.back();
373  // Create the after rep
374  T After;
375  generateIRRepresentation(IR, PassID, After);
376 
377  // Was there a change in IR?
378  if (Before == After) {
379  if (VerboseMode)
380  omitAfter(PassID, Name);
381  } else
382  handleAfter(PassID, Name, Before, After, IR);
383  }
384  BeforeStack.pop_back();
385 }
386 
387 template <typename T>
389  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
390 
391  // Always flag it as invalidated as we cannot determine when
392  // a pass for a filtered function is invalidated since we do not
393  // get the IR in the call. Also, the output is just alternate
394  // forms of the banner anyway.
395  if (VerboseMode)
396  handleInvalidated(PassID);
397  BeforeStack.pop_back();
398 }
399 
400 template <typename T>
404  saveIRBeforePass(IR, P, PIC.getPassNameForClassName(P));
405  });
406 
408  [&PIC, this](StringRef P, Any IR, const PreservedAnalyses &) {
409  handleIRAfterPass(IR, P, PIC.getPassNameForClassName(P));
410  });
412  [this](StringRef P, const PreservedAnalyses &) {
413  handleInvalidatedPass(P);
414  });
415 }
416 
417 template <typename T>
419  : ChangeReporter<T>(Verbose), Out(dbgs()) {}
420 
421 template <typename T> void TextChangeReporter<T>::handleInitialIR(Any IR) {
422  // Always print the module.
423  // Unwrap and print directly to avoid filtering problems in general routines.
424  auto *M = unwrapModule(IR, /*Force=*/true);
425  assert(M && "Expected module to be unwrapped when forced.");
426  Out << "*** IR Dump At Start ***\n";
427  M->print(Out, nullptr);
428 }
429 
430 template <typename T>
431 void TextChangeReporter<T>::omitAfter(StringRef PassID, std::string &Name) {
432  Out << formatv("*** IR Dump After {0} on {1} omitted because no change ***\n",
433  PassID, Name);
434 }
435 
436 template <typename T>
438  Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
439 }
440 
441 template <typename T>
443  std::string &Name) {
444  SmallString<20> Banner =
445  formatv("*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
446  Out << Banner;
447 }
448 
449 template <typename T>
451  Out << formatv("*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
452 }
453 
454 IRChangedPrinter::~IRChangedPrinter() = default;
455 
460 }
461 
463  std::string &Output) {
464  raw_string_ostream OS(Output);
465  unwrapAndPrint(OS, IR);
466  OS.str();
467 }
468 
469 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
470  const std::string &Before,
471  const std::string &After, Any) {
472  // Report the IR before the changes when requested.
473  if (PrintChangedBefore)
474  Out << "*** IR Dump Before " << PassID << " on " << Name << " ***\n"
475  << Before;
476 
477  // We might not get anything to print if we only want to print a specific
478  // function but it gets deleted.
479  if (After.empty()) {
480  Out << "*** IR Deleted After " << PassID << " on " << Name << " ***\n";
481  return;
482  }
483 
484  Out << "*** IR Dump After " << PassID << " on " << Name << " ***\n" << After;
485 }
486 
487 template <typename T>
489  const OrderedChangedData &Before, const OrderedChangedData &After,
490  function_ref<void(const T *, const T *)> HandlePair) {
491  const auto &BFD = Before.getData();
492  const auto &AFD = After.getData();
493  std::vector<std::string>::const_iterator BI = Before.getOrder().begin();
494  std::vector<std::string>::const_iterator BE = Before.getOrder().end();
495  std::vector<std::string>::const_iterator AI = After.getOrder().begin();
496  std::vector<std::string>::const_iterator AE = After.getOrder().end();
497 
498  auto HandlePotentiallyRemovedData = [&](std::string S) {
499  // The order in LLVM may have changed so check if still exists.
500  if (!AFD.count(S)) {
501  // This has been removed.
502  HandlePair(&BFD.find(*BI)->getValue(), nullptr);
503  }
504  };
505  auto HandleNewData = [&](std::vector<const T *> &Q) {
506  // Print out any queued up new sections
507  for (const T *NBI : Q)
508  HandlePair(nullptr, NBI);
509  Q.clear();
510  };
511 
512  // Print out the data in the after order, with before ones interspersed
513  // appropriately (ie, somewhere near where they were in the before list).
514  // Start at the beginning of both lists. Loop through the
515  // after list. If an element is common, then advance in the before list
516  // reporting the removed ones until the common one is reached. Report any
517  // queued up new ones and then report the common one. If an element is not
518  // common, then enqueue it for reporting. When the after list is exhausted,
519  // loop through the before list, reporting any removed ones. Finally,
520  // report the rest of the enqueued new ones.
521  std::vector<const T *> NewDataQueue;
522  while (AI != AE) {
523  if (!BFD.count(*AI)) {
524  // This section is new so place it in the queue. This will cause it
525  // to be reported after deleted sections.
526  NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
527  ++AI;
528  continue;
529  }
530  // This section is in both; advance and print out any before-only
531  // until we get to it.
532  // It's possible that this section has moved to be later than before. This
533  // will mess up printing most blocks side by side, but it's a rare case and
534  // it's better than crashing.
535  while (BI != BE && *BI != *AI) {
536  HandlePotentiallyRemovedData(*BI);
537  ++BI;
538  }
539  // Report any new sections that were queued up and waiting.
540  HandleNewData(NewDataQueue);
541 
542  const T &AData = AFD.find(*AI)->getValue();
543  const T &BData = BFD.find(*AI)->getValue();
544  HandlePair(&BData, &AData);
545  if (BI != BE)
546  ++BI;
547  ++AI;
548  }
549 
550  // Check any remaining before sections to see if they have been removed
551  while (BI != BE) {
552  HandlePotentiallyRemovedData(*BI);
553  ++BI;
554  }
555 
556  HandleNewData(NewDataQueue);
557 }
558 
559 template <typename T>
561  bool CompareModule,
562  std::function<void(bool InModule, unsigned Minor,
563  const FuncDataT<T> &Before, const FuncDataT<T> &After)>
564  CompareFunc) {
565  if (!CompareModule) {
566  // Just handle the single function.
567  assert(Before.getData().size() == 1 && After.getData().size() == 1 &&
568  "Expected only one function.");
569  CompareFunc(false, 0, Before.getData().begin()->getValue(),
570  After.getData().begin()->getValue());
571  return;
572  }
573 
574  unsigned Minor = 0;
575  FuncDataT<T> Missing("");
576  IRDataT<T>::report(Before, After,
577  [&](const FuncDataT<T> *B, const FuncDataT<T> *A) {
578  assert((B || A) && "Both functions cannot be missing.");
579  if (!B)
580  B = &Missing;
581  else if (!A)
582  A = &Missing;
583  CompareFunc(true, Minor++, *B, *A);
584  });
585 }
586 
587 template <typename T> void IRComparer<T>::analyzeIR(Any IR, IRDataT<T> &Data) {
588  if (const Module *M = getModuleForComparison(IR)) {
589  // Create data for each existing/interesting function in the module.
590  for (const Function &F : *M)
591  generateFunctionData(Data, F);
592  return;
593  }
594 
595  const Function *F = nullptr;
596  if (any_isa<const Function *>(IR))
597  F = any_cast<const Function *>(IR);
598  else {
599  assert(any_isa<const Loop *>(IR) && "Unknown IR unit.");
600  const Loop *L = any_cast<const Loop *>(IR);
601  F = L->getHeader()->getParent();
602  }
603  assert(F && "Unknown IR unit.");
604  generateFunctionData(Data, *F);
605 }
606 
607 template <typename T>
609  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
610  FuncDataT<T> FD(F.getEntryBlock().getName().str());
611  int I = 0;
612  for (const auto &B : F) {
613  std::string BBName = B.getName().str();
614  if (BBName.empty()) {
615  BBName = formatv("{0}", I);
616  ++I;
617  }
618  FD.getOrder().emplace_back(BBName);
619  FD.getData().insert({BBName, B});
620  }
621  Data.getOrder().emplace_back(F.getName());
622  Data.getData().insert({F.getName(), FD});
623  return true;
624  }
625  return false;
626 }
627 
629  assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
630 }
631 
632 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
633  const Module *M = unwrapModule(IR);
634  ModuleDescStack.emplace_back(M, getIRName(IR), PassID);
635 }
636 
637 PrintIRInstrumentation::PrintModuleDesc
638 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
639  assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
640  PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
641  assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
642  return ModuleDesc;
643 }
644 
645 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
646  if (isIgnored(PassID))
647  return;
648 
649  // Saving Module for AfterPassInvalidated operations.
650  // Note: here we rely on a fact that we do not change modules while
651  // traversing the pipeline, so the latest captured module is good
652  // for all print operations that has not happen yet.
653  if (shouldPrintAfterPass(PassID))
654  pushModuleDesc(PassID, IR);
655 
656  if (!shouldPrintBeforePass(PassID))
657  return;
658 
659  if (!shouldPrintIR(IR))
660  return;
661 
662  dbgs() << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
663  << " ***\n";
664  unwrapAndPrint(dbgs(), IR);
665 }
666 
667 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
668  if (isIgnored(PassID))
669  return;
670 
671  if (!shouldPrintAfterPass(PassID))
672  return;
673 
674  const Module *M;
675  std::string IRName;
676  StringRef StoredPassID;
677  std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
678  assert(StoredPassID == PassID && "mismatched PassID");
679 
680  if (!shouldPrintIR(IR))
681  return;
682 
683  dbgs() << "*** IR Dump After " << PassID << " on " << IRName << " ***\n";
684  unwrapAndPrint(dbgs(), IR);
685 }
686 
687 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
689  if (!shouldPrintAfterPass(PassName))
690  return;
691 
692  if (isIgnored(PassID))
693  return;
694 
695  const Module *M;
696  std::string IRName;
697  StringRef StoredPassID;
698  std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
699  assert(StoredPassID == PassID && "mismatched PassID");
700  // Additional filtering (e.g. -filter-print-func) can lead to module
701  // printing being skipped.
702  if (!M)
703  return;
704 
705  SmallString<20> Banner =
706  formatv("*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
707  dbgs() << Banner << "\n";
708  printIR(dbgs(), M);
709 }
710 
711 bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
712  if (shouldPrintBeforeAll())
713  return true;
714 
717 }
718 
719 bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
720  if (shouldPrintAfterAll())
721  return true;
722 
725 }
726 
729  this->PIC = &PIC;
730 
731  // BeforePass callback is not just for printing, it also saves a Module
732  // for later use in AfterPassInvalidated.
735  [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
736 
737  if (shouldPrintAfterSomePass()) {
739  [this](StringRef P, Any IR, const PreservedAnalyses &) {
740  this->printAfterPass(P, IR);
741  });
743  [this](StringRef P, const PreservedAnalyses &) {
744  this->printAfterPassInvalidated(P);
745  });
746  }
747 }
748 
752  [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
753 }
754 
755 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
756  const Function *F = nullptr;
757  if (any_isa<const Function *>(IR)) {
758  F = any_cast<const Function *>(IR);
759  } else if (any_isa<const Loop *>(IR)) {
760  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
761  }
762  bool ShouldRun = !(F && F->hasOptNone());
763  if (!ShouldRun && DebugLogging) {
764  errs() << "Skipping pass " << PassID << " on " << F->getName()
765  << " due to optnone attribute\n";
766  }
767  return ShouldRun;
768 }
769 
771  if (isIgnored(PassName))
772  return true;
773 
774  bool ShouldRun =
775  Context.getOptPassGate().shouldRunPass(PassName, getIRName(IR));
776  if (!ShouldRun && !this->HasWrittenIR && !OptBisectPrintIRPath.empty()) {
777  // FIXME: print IR if limit is higher than number of opt-bisect
778  // invocations
779  this->HasWrittenIR = true;
780  const Module *M = unwrapModule(IR, /*Force=*/true);
781  assert((M && &M->getContext() == &Context) && "Missing/Mismatching Module");
782  std::error_code EC;
784  if (EC)
786  M->print(OS, nullptr);
787  }
788  return ShouldRun;
789 }
790 
793  OptPassGate &PassGate = Context.getOptPassGate();
794  if (!PassGate.isEnabled())
795  return;
796 
798  return this->shouldRun(PassName, IR);
799  });
800 }
801 
802 raw_ostream &PrintPassInstrumentation::print() {
803  if (Opts.Indent) {
804  assert(Indent >= 0);
805  dbgs().indent(Indent);
806  }
807  return dbgs();
808 }
809 
812  if (!Enabled)
813  return;
814 
815  std::vector<StringRef> SpecialPasses;
816  if (!Opts.Verbose) {
817  SpecialPasses.emplace_back("PassManager");
818  SpecialPasses.emplace_back("PassAdaptor");
819  }
820 
821  PIC.registerBeforeSkippedPassCallback([this, SpecialPasses](StringRef PassID,
822  Any IR) {
823  assert(!isSpecialPass(PassID, SpecialPasses) &&
824  "Unexpectedly skipping special pass");
825 
826  print() << "Skipping pass: " << PassID << " on " << getIRName(IR) << "\n";
827  });
828  PIC.registerBeforeNonSkippedPassCallback([this, SpecialPasses](
829  StringRef PassID, Any IR) {
830  if (isSpecialPass(PassID, SpecialPasses))
831  return;
832 
833  auto &OS = print();
834  OS << "Running pass: " << PassID << " on " << getIRName(IR);
835  if (any_isa<const Function *>(IR)) {
836  unsigned Count = any_cast<const Function *>(IR)->getInstructionCount();
837  OS << " (" << Count << " instruction";
838  if (Count != 1)
839  OS << 's';
840  OS << ')';
841  } else if (any_isa<const LazyCallGraph::SCC *>(IR)) {
842  int Count = any_cast<const LazyCallGraph::SCC *>(IR)->size();
843  OS << " (" << Count << " node";
844  if (Count != 1)
845  OS << 's';
846  OS << ')';
847  }
848  OS << "\n";
849  Indent += 2;
850  });
852  [this, SpecialPasses](StringRef PassID, Any IR,
853  const PreservedAnalyses &) {
854  if (isSpecialPass(PassID, SpecialPasses))
855  return;
856 
857  Indent -= 2;
858  });
860  [this, SpecialPasses](StringRef PassID, Any IR) {
861  if (isSpecialPass(PassID, SpecialPasses))
862  return;
863 
864  Indent -= 2;
865  });
866 
867  if (!Opts.SkipAnalyses) {
869  print() << "Running analysis: " << PassID << " on " << getIRName(IR)
870  << "\n";
871  Indent += 2;
872  });
874  [this](StringRef PassID, Any IR) { Indent -= 2; });
876  print() << "Invalidating analysis: " << PassID << " on " << getIRName(IR)
877  << "\n";
878  });
880  print() << "Clearing all analysis results for: " << IRName << "\n";
881  });
882  }
883 }
884 
886  bool TrackBBLifetime) {
887  if (TrackBBLifetime)
889  for (const auto &BB : *F) {
890  if (BBGuards)
891  BBGuards->try_emplace(intptr_t(&BB), &BB);
892  for (const auto *Succ : successors(&BB)) {
893  Graph[&BB][Succ]++;
894  if (BBGuards)
895  BBGuards->try_emplace(intptr_t(Succ), Succ);
896  }
897  }
898 }
899 
900 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
901  if (BB->hasName()) {
902  out << BB->getName() << "<" << BB << ">";
903  return;
904  }
905 
906  if (!BB->getParent()) {
907  out << "unnamed_removed<" << BB << ">";
908  return;
909  }
910 
911  if (BB->isEntryBlock()) {
912  out << "entry"
913  << "<" << BB << ">";
914  return;
915  }
916 
917  unsigned FuncOrderBlockNum = 0;
918  for (auto &FuncBB : *BB->getParent()) {
919  if (&FuncBB == BB)
920  break;
921  FuncOrderBlockNum++;
922  }
923  out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
924 }
925 
927  const CFG &Before,
928  const CFG &After) {
929  assert(!After.isPoisoned());
930  if (Before.isPoisoned()) {
931  out << "Some blocks were deleted\n";
932  return;
933  }
934 
935  // Find and print graph differences.
936  if (Before.Graph.size() != After.Graph.size())
937  out << "Different number of non-leaf basic blocks: before="
938  << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
939 
940  for (auto &BB : Before.Graph) {
941  auto BA = After.Graph.find(BB.first);
942  if (BA == After.Graph.end()) {
943  out << "Non-leaf block ";
944  printBBName(out, BB.first);
945  out << " is removed (" << BB.second.size() << " successors)\n";
946  }
947  }
948 
949  for (auto &BA : After.Graph) {
950  auto BB = Before.Graph.find(BA.first);
951  if (BB == Before.Graph.end()) {
952  out << "Non-leaf block ";
953  printBBName(out, BA.first);
954  out << " is added (" << BA.second.size() << " successors)\n";
955  continue;
956  }
957 
958  if (BB->second == BA.second)
959  continue;
960 
961  out << "Different successors of block ";
962  printBBName(out, BA.first);
963  out << " (unordered):\n";
964  out << "- before (" << BB->second.size() << "): ";
965  for (auto &SuccB : BB->second) {
966  printBBName(out, SuccB.first);
967  if (SuccB.second != 1)
968  out << "(" << SuccB.second << "), ";
969  else
970  out << ", ";
971  }
972  out << "\n";
973  out << "- after (" << BA.second.size() << "): ";
974  for (auto &SuccA : BA.second) {
975  printBBName(out, SuccA.first);
976  if (SuccA.second != 1)
977  out << "(" << SuccA.second << "), ";
978  else
979  out << ", ";
980  }
981  out << "\n";
982  }
983 }
984 
985 // PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
986 // passes, that reported they kept CFG analyses up-to-date, did not actually
987 // change CFG. This check is done as follows. Before every functional pass in
988 // BeforeNonSkippedPassCallback a CFG snapshot (an instance of
989 // PreservedCFGCheckerInstrumentation::CFG) is requested from
990 // FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
991 // functional pass finishes and reports that CFGAnalyses or AllAnalyses are
992 // up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
993 // available) is checked to be equal to a freshly created CFG snapshot.
995  : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {
997 
998  static AnalysisKey Key;
999 
1000 public:
1001  /// Provide the result type for this analysis pass.
1003 
1004  /// Run the analysis pass over a function and produce CFG.
1006  return Result(&F, /* TrackBBLifetime */ true);
1007  }
1008 };
1009 
1011 
1013  Function &F, const PreservedAnalyses &PA,
1015  auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>();
1016  return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
1017  PAC.preservedSet<CFGAnalyses>());
1018 }
1019 
1022  if (!VerifyPreservedCFG)
1023  return;
1024 
1025  FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); });
1026 
1027  auto checkCFG = [](StringRef Pass, StringRef FuncName, const CFG &GraphBefore,
1028  const CFG &GraphAfter) {
1029  if (GraphAfter == GraphBefore)
1030  return;
1031 
1032  dbgs() << "Error: " << Pass
1033  << " does not invalidate CFG analyses but CFG changes detected in "
1034  "function @"
1035  << FuncName << ":\n";
1036  CFG::printDiff(dbgs(), GraphBefore, GraphAfter);
1037  report_fatal_error(Twine("CFG unexpectedly changed by ", Pass));
1038  };
1039 
1041 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1042  assert(&PassStack.emplace_back(P));
1043 #endif
1044  (void)this;
1045  if (!any_isa<const Function *>(IR))
1046  return;
1047 
1048  const auto *F = any_cast<const Function *>(IR);
1049  // Make sure a fresh CFG snapshot is available before the pass.
1051  });
1052 
1054  [this](StringRef P, const PreservedAnalyses &PassPA) {
1055 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1056  assert(PassStack.pop_back_val() == P &&
1057  "Before and After callbacks must correspond");
1058 #endif
1059  (void)this;
1060  });
1061 
1063  checkCFG](StringRef P, Any IR,
1064  const PreservedAnalyses &PassPA) {
1065 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1066  assert(PassStack.pop_back_val() == P &&
1067  "Before and After callbacks must correspond");
1068 #endif
1069  (void)this;
1070 
1071  if (!any_isa<const Function *>(IR))
1072  return;
1073 
1074  if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>() &&
1076  return;
1077 
1078  const auto *F = any_cast<const Function *>(IR);
1079  if (auto *GraphBefore = FAM.getCachedResult<PreservedCFGCheckerAnalysis>(
1080  *const_cast<Function *>(F)))
1081  checkCFG(P, F->getName(), *GraphBefore,
1082  CFG(F, /* TrackBBLifetime */ false));
1083  });
1084 }
1085 
1089  [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
1090  if (isIgnored(P) || P == "VerifierPass")
1091  return;
1092  if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
1093  const Function *F;
1094  if (any_isa<const Loop *>(IR))
1095  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
1096  else
1097  F = any_cast<const Function *>(IR);
1098  if (DebugLogging)
1099  dbgs() << "Verifying function " << F->getName() << "\n";
1100 
1101  if (verifyFunction(*F, &errs()))
1102  report_fatal_error("Broken function found, compilation aborted!");
1103  } else if (any_isa<const Module *>(IR) ||
1104  any_isa<const LazyCallGraph::SCC *>(IR)) {
1105  const Module *M;
1106  if (any_isa<const LazyCallGraph::SCC *>(IR))
1107  M = any_cast<const LazyCallGraph::SCC *>(IR)
1108  ->begin()
1109  ->getFunction()
1110  .getParent();
1111  else
1112  M = any_cast<const Module *>(IR);
1113  if (DebugLogging)
1114  dbgs() << "Verifying module " << M->getName() << "\n";
1115 
1116  if (verifyModule(*M, &errs()))
1117  report_fatal_error("Broken module found, compilation aborted!");
1118  }
1119  });
1120 }
1121 
1123 
1125  IRDataT<EmptyData> &D) {
1127 }
1128 
1129 void InLineChangePrinter::handleAfter(StringRef PassID, std::string &Name,
1130  const IRDataT<EmptyData> &Before,
1131  const IRDataT<EmptyData> &After, Any IR) {
1132  SmallString<20> Banner =
1133  formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);
1134  Out << Banner;
1135  IRComparer<EmptyData>(Before, After)
1136  .compare(getModuleForComparison(IR),
1137  [&](bool InModule, unsigned Minor,
1138  const FuncDataT<EmptyData> &Before,
1139  const FuncDataT<EmptyData> &After) -> void {
1140  handleFunctionCompare(Name, "", PassID, " on ", InModule,
1141  Minor, Before, After);
1142  });
1143  Out << "\n";
1144 }
1145 
1147  StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
1148  bool InModule, unsigned Minor, const FuncDataT<EmptyData> &Before,
1149  const FuncDataT<EmptyData> &After) {
1150  // Print a banner when this is being shown in the context of a module
1151  if (InModule)
1152  Out << "\n*** IR for function " << Name << " ***\n";
1153 
1155  Before, After,
1156  [&](const BlockDataT<EmptyData> *B, const BlockDataT<EmptyData> *A) {
1157  StringRef BStr = B ? B->getBody() : "\n";
1158  StringRef AStr = A ? A->getBody() : "\n";
1159  const std::string Removed =
1160  UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";
1161  const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";
1162  const std::string NoChange = " %l\n";
1163  Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1164  });
1165 }
1166 
1172  TextChangeReporter<IRDataT<EmptyData>>::registerRequiredCallbacks(PIC);
1173 }
1174 
1176 
1180  return;
1182  [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
1184  [this](StringRef P, Any IR, const PreservedAnalyses &) {
1185  this->runAfterPass();
1186  },
1187  true);
1189  [this](StringRef P, const PreservedAnalyses &) { this->runAfterPass(); },
1190  true);
1192  [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
1194  [this](StringRef P, Any IR) { this->runAfterPass(); }, true);
1195 }
1196 
1197 void TimeProfilingPassesHandler::runBeforePass(StringRef PassID, Any IR) {
1198  timeTraceProfilerBegin(PassID, getIRName(IR));
1199 }
1200 
1201 void TimeProfilingPassesHandler::runAfterPass() { timeTraceProfilerEnd(); }
1202 
1203 namespace {
1204 
1205 class DisplayNode;
1206 class DotCfgDiffDisplayGraph;
1207 
1208 // Base class for a node or edge in the dot-cfg-changes graph.
1209 class DisplayElement {
1210 public:
1211  // Is this in before, after, or both?
1212  StringRef getColour() const { return Colour; }
1213 
1214 protected:
1215  DisplayElement(StringRef Colour) : Colour(Colour) {}
1216  const StringRef Colour;
1217 };
1218 
1219 // An edge representing a transition between basic blocks in the
1220 // dot-cfg-changes graph.
1221 class DisplayEdge : public DisplayElement {
1222 public:
1223  DisplayEdge(std::string Value, DisplayNode &Node, StringRef Colour)
1224  : DisplayElement(Colour), Value(Value), Node(Node) {}
1225  // The value on which the transition is made.
1226  std::string getValue() const { return Value; }
1227  // The node (representing a basic block) reached by this transition.
1228  const DisplayNode &getDestinationNode() const { return Node; }
1229 
1230 protected:
1231  std::string Value;
1232  const DisplayNode &Node;
1233 };
1234 
1235 // A node in the dot-cfg-changes graph which represents a basic block.
1236 class DisplayNode : public DisplayElement {
1237 public:
1238  // \p C is the content for the node, \p T indicates the colour for the
1239  // outline of the node
1240  DisplayNode(std::string Content, StringRef Colour)
1241  : DisplayElement(Colour), Content(Content) {}
1242 
1243  // Iterator to the child nodes. Required by GraphWriter.
1244  using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1245  ChildIterator children_begin() const { return Children.cbegin(); }
1246  ChildIterator children_end() const { return Children.cend(); }
1247 
1248  // Iterator for the edges. Required by GraphWriter.
1249  using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1250  EdgeIterator edges_begin() const { return EdgePtrs.cbegin(); }
1251  EdgeIterator edges_end() const { return EdgePtrs.cend(); }
1252 
1253  // Create an edge to \p Node on value \p Value, with colour \p Colour.
1254  void createEdge(StringRef Value, DisplayNode &Node, StringRef Colour);
1255 
1256  // Return the content of this node.
1257  std::string getContent() const { return Content; }
1258 
1259  // Return the edge to node \p S.
1260  const DisplayEdge &getEdge(const DisplayNode &To) const {
1261  assert(EdgeMap.find(&To) != EdgeMap.end() && "Expected to find edge.");
1262  return *EdgeMap.find(&To)->second;
1263  }
1264 
1265  // Return the value for the transition to basic block \p S.
1266  // Required by GraphWriter.
1267  std::string getEdgeSourceLabel(const DisplayNode &Sink) const {
1268  return getEdge(Sink).getValue();
1269  }
1270 
1271  void createEdgeMap();
1272 
1273 protected:
1274  const std::string Content;
1275 
1276  // Place to collect all of the edges. Once they are all in the vector,
1277  // the vector will not reallocate so then we can use pointers to them,
1278  // which are required by the graph writing routines.
1279  std::vector<DisplayEdge> Edges;
1280 
1281  std::vector<DisplayEdge *> EdgePtrs;
1282  std::unordered_set<DisplayNode *> Children;
1283  std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1284 
1285  // Safeguard adding of edges.
1286  bool AllEdgesCreated = false;
1287 };
1288 
1289 // Class representing a difference display (corresponds to a pdf file).
1290 class DotCfgDiffDisplayGraph {
1291 public:
1292  DotCfgDiffDisplayGraph(std::string Name) : GraphName(Name) {}
1293 
1294  // Generate the file into \p DotFile.
1295  void generateDotFile(StringRef DotFile);
1296 
1297  // Iterator to the nodes. Required by GraphWriter.
1298  using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1299  NodeIterator nodes_begin() const {
1300  assert(NodeGenerationComplete && "Unexpected children iterator creation");
1301  return NodePtrs.cbegin();
1302  }
1303  NodeIterator nodes_end() const {
1304  assert(NodeGenerationComplete && "Unexpected children iterator creation");
1305  return NodePtrs.cend();
1306  }
1307 
1308  // Record the index of the entry node. At this point, we can build up
1309  // vectors of pointers that are required by the graph routines.
1310  void setEntryNode(unsigned N) {
1311  // At this point, there will be no new nodes.
1312  assert(!NodeGenerationComplete && "Unexpected node creation");
1313  NodeGenerationComplete = true;
1314  for (auto &N : Nodes)
1315  NodePtrs.emplace_back(&N);
1316 
1317  EntryNode = NodePtrs[N];
1318  }
1319 
1320  // Create a node.
1321  void createNode(std::string C, StringRef Colour) {
1322  assert(!NodeGenerationComplete && "Unexpected node creation");
1323  Nodes.emplace_back(C, Colour);
1324  }
1325  // Return the node at index \p N to avoid problems with vectors reallocating.
1326  DisplayNode &getNode(unsigned N) {
1327  assert(N < Nodes.size() && "Node is out of bounds");
1328  return Nodes[N];
1329  }
1330  unsigned size() const {
1331  assert(NodeGenerationComplete && "Unexpected children iterator creation");
1332  return Nodes.size();
1333  }
1334 
1335  // Return the name of the graph. Required by GraphWriter.
1336  std::string getGraphName() const { return GraphName; }
1337 
1338  // Return the string representing the differences for basic block \p Node.
1339  // Required by GraphWriter.
1340  std::string getNodeLabel(const DisplayNode &Node) const {
1341  return Node.getContent();
1342  }
1343 
1344  // Return a string with colour information for Dot. Required by GraphWriter.
1345  std::string getNodeAttributes(const DisplayNode &Node) const {
1346  return attribute(Node.getColour());
1347  }
1348 
1349  // Return a string with colour information for Dot. Required by GraphWriter.
1350  std::string getEdgeColorAttr(const DisplayNode &From,
1351  const DisplayNode &To) const {
1352  return attribute(From.getEdge(To).getColour());
1353  }
1354 
1355  // Get the starting basic block. Required by GraphWriter.
1356  DisplayNode *getEntryNode() const {
1357  assert(NodeGenerationComplete && "Unexpected children iterator creation");
1358  return EntryNode;
1359  }
1360 
1361 protected:
1362  // Return the string containing the colour to use as a Dot attribute.
1363  std::string attribute(StringRef Colour) const {
1364  return "color=" + Colour.str();
1365  }
1366 
1367  bool NodeGenerationComplete = false;
1368  const std::string GraphName;
1369  std::vector<DisplayNode> Nodes;
1370  std::vector<DisplayNode *> NodePtrs;
1371  DisplayNode *EntryNode = nullptr;
1372 };
1373 
1374 void DisplayNode::createEdge(StringRef Value, DisplayNode &Node,
1375  StringRef Colour) {
1376  assert(!AllEdgesCreated && "Expected to be able to still create edges.");
1377  Edges.emplace_back(Value.str(), Node, Colour);
1378  Children.insert(&Node);
1379 }
1380 
1381 void DisplayNode::createEdgeMap() {
1382  // No more edges will be added so we can now use pointers to the edges
1383  // as the vector will not grow and reallocate.
1384  AllEdgesCreated = true;
1385  for (auto &E : Edges)
1386  EdgeMap.insert({&E.getDestinationNode(), &E});
1387 }
1388 
1389 class DotCfgDiffNode;
1390 class DotCfgDiff;
1391 
1392 // A class representing a basic block in the Dot difference graph.
1393 class DotCfgDiffNode {
1394 public:
1395  DotCfgDiffNode() = delete;
1396 
1397  // Create a node in Dot difference graph \p G representing the basic block
1398  // represented by \p BD with colour \p Colour (where it exists).
1399  DotCfgDiffNode(DotCfgDiff &G, unsigned N, const BlockDataT<DCData> &BD,
1400  StringRef Colour)
1401  : Graph(G), N(N), Data{&BD, nullptr}, Colour(Colour) {}
1402  DotCfgDiffNode(const DotCfgDiffNode &DN)
1403  : Graph(DN.Graph), N(DN.N), Data{DN.Data[0], DN.Data[1]},
1404  Colour(DN.Colour), EdgesMap(DN.EdgesMap), Children(DN.Children),
1405  Edges(DN.Edges) {}
1406 
1407  unsigned getIndex() const { return N; }
1408 
1409  // The label of the basic block
1410  StringRef getLabel() const {
1411  assert(Data[0] && "Expected Data[0] to be set.");
1412  return Data[0]->getLabel();
1413  }
1414  // Return the colour for this block
1415  StringRef getColour() const { return Colour; }
1416  // Change this basic block from being only in before to being common.
1417  // Save the pointer to \p Other.
1418  void setCommon(const BlockDataT<DCData> &Other) {
1419  assert(!Data[1] && "Expected only one block datum");
1420  Data[1] = &Other;
1421  Colour = CommonColour;
1422  }
1423  // Add an edge to \p E of colour {\p Value, \p Colour}.
1424  void addEdge(unsigned E, StringRef Value, StringRef Colour) {
1425  // This is a new edge or it is an edge being made common.
1426  assert((EdgesMap.count(E) == 0 || Colour == CommonColour) &&
1427  "Unexpected edge count and color.");
1428  EdgesMap[E] = {Value.str(), Colour};
1429  }
1430  // Record the children and create edges.
1431  void finalize(DotCfgDiff &G);
1432 
1433  // Return the colour of the edge to node \p S.
1434  StringRef getEdgeColour(const unsigned S) const {
1435  assert(EdgesMap.count(S) == 1 && "Expected to find edge.");
1436  return EdgesMap.at(S).second;
1437  }
1438 
1439  // Return the string representing the basic block.
1440  std::string getBodyContent() const;
1441 
1442  void createDisplayEdges(DotCfgDiffDisplayGraph &Graph, unsigned DisplayNode,
1443  std::map<const unsigned, unsigned> &NodeMap) const;
1444 
1445 protected:
1446  DotCfgDiff &Graph;
1447  const unsigned N;
1448  const BlockDataT<DCData> *Data[2];
1449  StringRef Colour;
1450  std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1451  std::vector<unsigned> Children;
1452  std::vector<unsigned> Edges;
1453 };
1454 
1455 // Class representing the difference graph between two functions.
1456 class DotCfgDiff {
1457 public:
1458  // \p Title is the title given to the graph. \p EntryNodeName is the
1459  // entry node for the function. \p Before and \p After are the before
1460  // after versions of the function, respectively. \p Dir is the directory
1461  // in which to store the results.
1462  DotCfgDiff(StringRef Title, const FuncDataT<DCData> &Before,
1463  const FuncDataT<DCData> &After);
1464 
1465  DotCfgDiff(const DotCfgDiff &) = delete;
1466  DotCfgDiff &operator=(const DotCfgDiff &) = delete;
1467 
1468  DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1469  StringRef EntryNodeName);
1470 
1471  // Return a string consisting of the labels for the \p Source and \p Sink.
1472  // The combination allows distinguishing changing transitions on the
1473  // same value (ie, a transition went to X before and goes to Y after).
1474  // Required by GraphWriter.
1475  StringRef getEdgeSourceLabel(const unsigned &Source,
1476  const unsigned &Sink) const {
1477  std::string S =
1478  getNode(Source).getLabel().str() + " " + getNode(Sink).getLabel().str();
1479  assert(EdgeLabels.count(S) == 1 && "Expected to find edge label.");
1480  return EdgeLabels.find(S)->getValue();
1481  }
1482 
1483  // Return the number of basic blocks (nodes). Required by GraphWriter.
1484  unsigned size() const { return Nodes.size(); }
1485 
1486  const DotCfgDiffNode &getNode(unsigned N) const {
1487  assert(N < Nodes.size() && "Unexpected index for node reference");
1488  return Nodes[N];
1489  }
1490 
1491 protected:
1492  // Return the string surrounded by HTML to make it the appropriate colour.
1493  std::string colourize(std::string S, StringRef Colour) const;
1494 
1495  void createNode(StringRef Label, const BlockDataT<DCData> &BD, StringRef C) {
1496  unsigned Pos = Nodes.size();
1497  Nodes.emplace_back(*this, Pos, BD, C);
1498  NodePosition.insert({Label, Pos});
1499  }
1500 
1501  // TODO Nodes should probably be a StringMap<DotCfgDiffNode> after the
1502  // display graph is separated out, which would remove the need for
1503  // NodePosition.
1504  std::vector<DotCfgDiffNode> Nodes;
1505  StringMap<unsigned> NodePosition;
1506  const std::string GraphName;
1507 
1508  StringMap<std::string> EdgeLabels;
1509 };
1510 
1511 std::string DotCfgDiffNode::getBodyContent() const {
1512  if (Colour == CommonColour) {
1513  assert(Data[1] && "Expected Data[1] to be set.");
1514 
1515  StringRef SR[2];
1516  for (unsigned I = 0; I < 2; ++I) {
1517  SR[I] = Data[I]->getBody();
1518  // drop initial '\n' if present
1519  if (SR[I][0] == '\n')
1520  SR[I] = SR[I].drop_front();
1521  // drop predecessors as they can be big and are redundant
1522  SR[I] = SR[I].drop_until([](char C) { return C == '\n'; }).drop_front();
1523  }
1524 
1525  SmallString<80> OldLineFormat = formatv(
1526  "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", BeforeColour);
1527  SmallString<80> NewLineFormat = formatv(
1528  "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", AfterColour);
1529  SmallString<80> UnchangedLineFormat = formatv(
1530  "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>", CommonColour);
1531  std::string Diff = Data[0]->getLabel().str();
1532  Diff += ":\n<BR align=\"left\"/>" +
1533  doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1534  OldLineFormat, NewLineFormat, UnchangedLineFormat);
1535 
1536  // Diff adds in some empty colour changes which are not valid HTML
1537  // so remove them. Colours are all lowercase alpha characters (as
1538  // listed in https://graphviz.org/pdf/dotguide.pdf).
1539  Regex R("<FONT COLOR=\"\\w+\"></FONT>");
1540  while (true) {
1541  std::string Error;
1542  std::string S = R.sub("", Diff, &Error);
1543  if (Error != "")
1544  return Error;
1545  if (S == Diff)
1546  return Diff;
1547  Diff = S;
1548  }
1549  llvm_unreachable("Should not get here");
1550  }
1551 
1552  // Put node out in the appropriate colour.
1553  assert(!Data[1] && "Data[1] is set unexpectedly.");
1554  std::string Body = makeHTMLReady(Data[0]->getBody());
1555  const StringRef BS = Body;
1556  StringRef BS1 = BS;
1557  // Drop leading newline, if present.
1558  if (BS.front() == '\n')
1559  BS1 = BS1.drop_front(1);
1560  // Get label.
1561  StringRef Label = BS1.take_until([](char C) { return C == ':'; });
1562  // drop predecessors as they can be big and are redundant
1563  BS1 = BS1.drop_until([](char C) { return C == '\n'; }).drop_front();
1564 
1565  std::string S = "<FONT COLOR=\"" + Colour.str() + "\">" + Label.str() + ":";
1566 
1567  // align each line to the left.
1568  while (BS1.size()) {
1569  S.append("<BR align=\"left\"/>");
1570  StringRef Line = BS1.take_until([](char C) { return C == '\n'; });
1571  S.append(Line.str());
1572  BS1 = BS1.drop_front(Line.size() + 1);
1573  }
1574  S.append("<BR align=\"left\"/></FONT>");
1575  return S;
1576 }
1577 
1578 std::string DotCfgDiff::colourize(std::string S, StringRef Colour) const {
1579  if (S.length() == 0)
1580  return S;
1581  return "<FONT COLOR=\"" + Colour.str() + "\">" + S + "</FONT>";
1582 }
1583 
1584 DotCfgDiff::DotCfgDiff(StringRef Title, const FuncDataT<DCData> &Before,
1585  const FuncDataT<DCData> &After)
1586  : GraphName(Title.str()) {
1587  StringMap<StringRef> EdgesMap;
1588 
1589  // Handle each basic block in the before IR.
1590  for (auto &B : Before.getData()) {
1591  StringRef Label = B.getKey();
1592  const BlockDataT<DCData> &BD = B.getValue();
1593  createNode(Label, BD, BeforeColour);
1594 
1595  // Create transitions with names made up of the from block label, the value
1596  // on which the transition is made and the to block label.
1598  E = BD.getData().end();
1599  Sink != E; ++Sink) {
1600  std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +
1601  BD.getData().getSuccessorLabel(Sink->getKey()).str();
1602  EdgesMap.insert({Key, BeforeColour});
1603  }
1604  }
1605 
1606  // Handle each basic block in the after IR
1607  for (auto &A : After.getData()) {
1608  StringRef Label = A.getKey();
1609  const BlockDataT<DCData> &BD = A.getValue();
1610  unsigned C = NodePosition.count(Label);
1611  if (C == 0)
1612  // This only exists in the after IR. Create the node.
1613  createNode(Label, BD, AfterColour);
1614  else {
1615  assert(C == 1 && "Unexpected multiple nodes.");
1616  Nodes[NodePosition[Label]].setCommon(BD);
1617  }
1618  // Add in the edges between the nodes (as common or only in after).
1620  E = BD.getData().end();
1621  Sink != E; ++Sink) {
1622  std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +
1623  BD.getData().getSuccessorLabel(Sink->getKey()).str();
1624  unsigned C = EdgesMap.count(Key);
1625  if (C == 0)
1626  EdgesMap.insert({Key, AfterColour});
1627  else {
1628  EdgesMap[Key] = CommonColour;
1629  }
1630  }
1631  }
1632 
1633  // Now go through the map of edges and add them to the node.
1634  for (auto &E : EdgesMap) {
1635  // Extract the source, sink and value from the edge key.
1636  StringRef S = E.getKey();
1637  auto SP1 = S.rsplit(' ');
1638  auto &SourceSink = SP1.first;
1639  auto SP2 = SourceSink.split(' ');
1640  StringRef Source = SP2.first;
1641  StringRef Sink = SP2.second;
1642  StringRef Value = SP1.second;
1643 
1644  assert(NodePosition.count(Source) == 1 && "Expected to find node.");
1645  DotCfgDiffNode &SourceNode = Nodes[NodePosition[Source]];
1646  assert(NodePosition.count(Sink) == 1 && "Expected to find node.");
1647  unsigned SinkNode = NodePosition[Sink];
1648  StringRef Colour = E.second;
1649 
1650  // Look for an edge from Source to Sink
1651  if (EdgeLabels.count(SourceSink) == 0)
1652  EdgeLabels.insert({SourceSink, colourize(Value.str(), Colour)});
1653  else {
1654  StringRef V = EdgeLabels.find(SourceSink)->getValue();
1655  std::string NV = colourize(V.str() + " " + Value.str(), Colour);
1656  Colour = CommonColour;
1657  EdgeLabels[SourceSink] = NV;
1658  }
1659  SourceNode.addEdge(SinkNode, Value, Colour);
1660  }
1661  for (auto &I : Nodes)
1662  I.finalize(*this);
1663 }
1664 
1665 DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(StringRef Title,
1666  StringRef EntryNodeName) {
1667  assert(NodePosition.count(EntryNodeName) == 1 &&
1668  "Expected to find entry block in map.");
1669  unsigned Entry = NodePosition[EntryNodeName];
1670  assert(Entry < Nodes.size() && "Expected to find entry node");
1671  DotCfgDiffDisplayGraph G(Title.str());
1672 
1673  std::map<const unsigned, unsigned> NodeMap;
1674 
1675  int EntryIndex = -1;
1676  unsigned Index = 0;
1677  for (auto &I : Nodes) {
1678  if (I.getIndex() == Entry)
1679  EntryIndex = Index;
1680  G.createNode(I.getBodyContent(), I.getColour());
1681  NodeMap.insert({I.getIndex(), Index++});
1682  }
1683  assert(EntryIndex >= 0 && "Expected entry node index to be set.");
1684  G.setEntryNode(EntryIndex);
1685 
1686  for (auto &I : NodeMap) {
1687  unsigned SourceNode = I.first;
1688  unsigned DisplayNode = I.second;
1689  getNode(SourceNode).createDisplayEdges(G, DisplayNode, NodeMap);
1690  }
1691  return G;
1692 }
1693 
1694 void DotCfgDiffNode::createDisplayEdges(
1695  DotCfgDiffDisplayGraph &DisplayGraph, unsigned DisplayNodeIndex,
1696  std::map<const unsigned, unsigned> &NodeMap) const {
1697 
1698  DisplayNode &SourceDisplayNode = DisplayGraph.getNode(DisplayNodeIndex);
1699 
1700  for (auto I : Edges) {
1701  unsigned SinkNodeIndex = I;
1702  StringRef Colour = getEdgeColour(SinkNodeIndex);
1703  const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1704 
1705  StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1706  DisplayNode &SinkDisplayNode = DisplayGraph.getNode(SinkNode->getIndex());
1707  SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1708  }
1709  SourceDisplayNode.createEdgeMap();
1710 }
1711 
1712 void DotCfgDiffNode::finalize(DotCfgDiff &G) {
1713  for (auto E : EdgesMap) {
1714  Children.emplace_back(E.first);
1715  Edges.emplace_back(E.first);
1716  }
1717 }
1718 
1719 } // namespace
1720 
1721 namespace llvm {
1722 
1723 template <> struct GraphTraits<DotCfgDiffDisplayGraph *> {
1724  using NodeRef = const DisplayNode *;
1725  using ChildIteratorType = DisplayNode::ChildIterator;
1726  using nodes_iterator = DotCfgDiffDisplayGraph::NodeIterator;
1727  using EdgeRef = const DisplayEdge *;
1728  using ChildEdgeIterator = DisplayNode::EdgeIterator;
1729 
1730  static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G) {
1731  return G->getEntryNode();
1732  }
1734  return N->children_begin();
1735  }
1736  static ChildIteratorType child_end(NodeRef N) { return N->children_end(); }
1737  static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G) {
1738  return G->nodes_begin();
1739  }
1740  static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G) {
1741  return G->nodes_end();
1742  }
1744  return N->edges_begin();
1745  }
1746  static ChildEdgeIterator child_edge_end(NodeRef N) { return N->edges_end(); }
1747  static NodeRef edge_dest(EdgeRef E) { return &E->getDestinationNode(); }
1748  static unsigned size(const DotCfgDiffDisplayGraph *G) { return G->size(); }
1749 };
1750 
1751 template <>
1752 struct DOTGraphTraits<DotCfgDiffDisplayGraph *> : public DefaultDOTGraphTraits {
1753  explicit DOTGraphTraits(bool Simple = false)
1754  : DefaultDOTGraphTraits(Simple) {}
1755 
1756  static bool renderNodesUsingHTML() { return true; }
1757  static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData) {
1758  return DiffData->getGraphName();
1759  }
1760  static std::string
1761  getGraphProperties(const DotCfgDiffDisplayGraph *DiffData) {
1762  return "\tsize=\"190, 190\";\n";
1763  }
1764  static std::string getNodeLabel(const DisplayNode *Node,
1765  const DotCfgDiffDisplayGraph *DiffData) {
1766  return DiffData->getNodeLabel(*Node);
1767  }
1768  static std::string getNodeAttributes(const DisplayNode *Node,
1769  const DotCfgDiffDisplayGraph *DiffData) {
1770  return DiffData->getNodeAttributes(*Node);
1771  }
1772  static std::string getEdgeSourceLabel(const DisplayNode *From,
1773  DisplayNode::ChildIterator &To) {
1774  return From->getEdgeSourceLabel(**To);
1775  }
1776  static std::string getEdgeAttributes(const DisplayNode *From,
1777  DisplayNode::ChildIterator &To,
1778  const DotCfgDiffDisplayGraph *DiffData) {
1779  return DiffData->getEdgeColorAttr(*From, **To);
1780  }
1781 };
1782 
1783 } // namespace llvm
1784 
1785 namespace {
1786 
1787 void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
1788  std::error_code EC;
1789  raw_fd_ostream OutStream(DotFile, EC);
1790  if (EC) {
1791  errs() << "Error: " << EC.message() << "\n";
1792  return;
1793  }
1794  WriteGraph(OutStream, this, false);
1795  OutStream.flush();
1796  OutStream.close();
1797 }
1798 
1799 } // namespace
1800 
1801 namespace llvm {
1802 
1804  // Build up transition labels.
1805  const Instruction *Term = B.getTerminator();
1806  if (const BranchInst *Br = dyn_cast<const BranchInst>(Term))
1807  if (Br->isUnconditional())
1808  addSuccessorLabel(Br->getSuccessor(0)->getName().str(), "");
1809  else {
1810  addSuccessorLabel(Br->getSuccessor(0)->getName().str(), "true");
1811  addSuccessorLabel(Br->getSuccessor(1)->getName().str(), "false");
1812  }
1813  else if (const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
1814  addSuccessorLabel(Sw->case_default()->getCaseSuccessor()->getName().str(),
1815  "default");
1816  for (auto &C : Sw->cases()) {
1817  assert(C.getCaseValue() && "Expected to find case value.");
1818  SmallString<20> Value = formatv("{0}", C.getCaseValue()->getSExtValue());
1819  addSuccessorLabel(C.getCaseSuccessor()->getName().str(), Value);
1820  }
1821  } else
1822  for (const_succ_iterator I = succ_begin(&B), E = succ_end(&B); I != E; ++I)
1823  addSuccessorLabel((*I)->getName().str(), "");
1824 }
1825 
1828 
1830  StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
1831  bool InModule, unsigned Minor, const FuncDataT<DCData> &Before,
1832  const FuncDataT<DCData> &After) {
1833  assert(HTML && "Expected outstream to be set");
1834  SmallString<8> Extender;
1836  // Handle numbering and file names.
1837  if (InModule) {
1838  Extender = formatv("{0}_{1}", N, Minor);
1839  Number = formatv("{0}.{1}", N, Minor);
1840  } else {
1841  Extender = formatv("{0}", N);
1842  Number = formatv("{0}", N);
1843  }
1844  // Create a temporary file name for the dot file.
1846  sys::fs::createUniquePath("cfgdot-%%%%%%.dot", SV, true);
1847  std::string DotFile = Twine(SV).str();
1848 
1849  SmallString<20> PDFFileName = formatv("diff_{0}.pdf", Extender);
1850  SmallString<200> Text;
1851 
1852  Text = formatv("{0}.{1}{2}{3}{4}", Number, Prefix, makeHTMLReady(PassID),
1853  Divider, Name);
1854 
1855  DotCfgDiff Diff(Text, Before, After);
1856  std::string EntryBlockName = After.getEntryBlockName();
1857  // Use the before entry block if the after entry block was removed.
1858  if (EntryBlockName == "")
1859  EntryBlockName = Before.getEntryBlockName();
1860  assert(EntryBlockName != "" && "Expected to find entry block");
1861 
1862  DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
1863  DG.generateDotFile(DotFile);
1864 
1865  *HTML << genHTML(Text, DotFile, PDFFileName);
1866  std::error_code EC = sys::fs::remove(DotFile);
1867  if (EC)
1868  errs() << "Error: " << EC.message() << "\n";
1869 }
1870 
1872  StringRef PDFFileName) {
1873  SmallString<20> PDFFile = formatv("{0}/{1}", DotCfgDir, PDFFileName);
1874  // Create the PDF file.
1876  if (!DotExe)
1877  return "Unable to find dot executable.";
1878 
1879  StringRef Args[] = {DotBinary, "-Tpdf", "-o", PDFFile, DotFile};
1880  int Result = sys::ExecuteAndWait(*DotExe, Args, std::nullopt);
1881  if (Result < 0)
1882  return "Error executing system dot.";
1883 
1884  // Create the HTML tag refering to the PDF file.
1886  " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
1887  return S.c_str();
1888 }
1889 
1891  assert(HTML && "Expected outstream to be set");
1892  *HTML << "<button type=\"button\" class=\"collapsible\">0. "
1893  << "Initial IR (by function)</button>\n"
1894  << "<div class=\"content\">\n"
1895  << " <p>\n";
1896  // Create representation of IR
1899  // Now compare it against itself, which will have everything the
1900  // same and will generate the files.
1902  .compare(getModuleForComparison(IR),
1903  [&](bool InModule, unsigned Minor,
1904  const FuncDataT<DCData> &Before,
1905  const FuncDataT<DCData> &After) -> void {
1906  handleFunctionCompare("", " ", "Initial IR", "", InModule,
1907  Minor, Before, After);
1908  });
1909  *HTML << " </p>\n"
1910  << "</div><br/>\n";
1911  ++N;
1912 }
1913 
1915  IRDataT<DCData> &Data) {
1917 }
1918 
1919 void DotCfgChangeReporter::omitAfter(StringRef PassID, std::string &Name) {
1920  assert(HTML && "Expected outstream to be set");
1921  SmallString<20> Banner =
1922  formatv(" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
1923  N, makeHTMLReady(PassID), Name);
1924  *HTML << Banner;
1925  ++N;
1926 }
1927 
1928 void DotCfgChangeReporter::handleAfter(StringRef PassID, std::string &Name,
1929  const IRDataT<DCData> &Before,
1930  const IRDataT<DCData> &After, Any IR) {
1931  assert(HTML && "Expected outstream to be set");
1932  IRComparer<DCData>(Before, After)
1933  .compare(getModuleForComparison(IR),
1934  [&](bool InModule, unsigned Minor,
1935  const FuncDataT<DCData> &Before,
1936  const FuncDataT<DCData> &After) -> void {
1937  handleFunctionCompare(Name, " Pass ", PassID, " on ", InModule,
1938  Minor, Before, After);
1939  });
1940  *HTML << " </p></div>\n";
1941  ++N;
1942 }
1943 
1945  assert(HTML && "Expected outstream to be set");
1946  SmallString<20> Banner =
1947  formatv(" <a>{0}. {1} invalidated</a><br/>\n", N, makeHTMLReady(PassID));
1948  *HTML << Banner;
1949  ++N;
1950 }
1951 
1952 void DotCfgChangeReporter::handleFiltered(StringRef PassID, std::string &Name) {
1953  assert(HTML && "Expected outstream to be set");
1954  SmallString<20> Banner =
1955  formatv(" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n", N,
1956  makeHTMLReady(PassID), Name);
1957  *HTML << Banner;
1958  ++N;
1959 }
1960 
1961 void DotCfgChangeReporter::handleIgnored(StringRef PassID, std::string &Name) {
1962  assert(HTML && "Expected outstream to be set");
1963  SmallString<20> Banner = formatv(" <a>{0}. {1} on {2} ignored</a><br/>\n", N,
1964  makeHTMLReady(PassID), Name);
1965  *HTML << Banner;
1966  ++N;
1967 }
1968 
1970  std::error_code EC;
1971  HTML = std::make_unique<raw_fd_ostream>(DotCfgDir + "/passes.html", EC);
1972  if (EC) {
1973  HTML = nullptr;
1974  return false;
1975  }
1976 
1977  *HTML << "<!doctype html>"
1978  << "<html>"
1979  << "<head>"
1980  << "<style>.collapsible { "
1981  << "background-color: #777;"
1982  << " color: white;"
1983  << " cursor: pointer;"
1984  << " padding: 18px;"
1985  << " width: 100%;"
1986  << " border: none;"
1987  << " text-align: left;"
1988  << " outline: none;"
1989  << " font-size: 15px;"
1990  << "} .active, .collapsible:hover {"
1991  << " background-color: #555;"
1992  << "} .content {"
1993  << " padding: 0 18px;"
1994  << " display: none;"
1995  << " overflow: hidden;"
1996  << " background-color: #f1f1f1;"
1997  << "}"
1998  << "</style>"
1999  << "<title>passes.html</title>"
2000  << "</head>\n"
2001  << "<body>";
2002  return true;
2003 }
2004 
2006  if (!HTML)
2007  return;
2008  *HTML
2009  << "<script>var coll = document.getElementsByClassName(\"collapsible\");"
2010  << "var i;"
2011  << "for (i = 0; i < coll.length; i++) {"
2012  << "coll[i].addEventListener(\"click\", function() {"
2013  << " this.classList.toggle(\"active\");"
2014  << " var content = this.nextElementSibling;"
2015  << " if (content.style.display === \"block\"){"
2016  << " content.style.display = \"none\";"
2017  << " }"
2018  << " else {"
2019  << " content.style.display= \"block\";"
2020  << " }"
2021  << " });"
2022  << " }"
2023  << "</script>"
2024  << "</body>"
2025  << "</html>\n";
2026  HTML->flush();
2027  HTML->close();
2028 }
2029 
2034  SmallString<128> OutputDir;
2035  sys::fs::expand_tilde(DotCfgDir, OutputDir);
2036  sys::fs::make_absolute(OutputDir);
2037  assert(!OutputDir.empty() && "expected output dir to be non-empty");
2038  DotCfgDir = OutputDir.c_str();
2039  if (initializeHTML()) {
2041  return;
2042  }
2043  dbgs() << "Unable to open output stream for -cfg-dot-changed\n";
2044  }
2045 }
2046 
2048  LLVMContext &Context, bool DebugLogging, bool VerifyEach,
2049  PrintPassOptions PrintPassOpts)
2050  : PrintPass(DebugLogging, PrintPassOpts),
2051  OptNone(DebugLogging),
2053  PrintChangedIR(PrintChanged == ChangePrinter::Verbose),
2054  PrintChangedDiff(PrintChanged == ChangePrinter::DiffVerbose ||
2058  WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
2059  Verify(DebugLogging), VerifyEach(VerifyEach) {}
2060 
2061 PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
2062  nullptr;
2063 
2065 
2066 void PrintCrashIRInstrumentation::SignalHandler(void *) {
2067  // Called by signal handlers so do not lock here
2068  // Is the PrintCrashIRInstrumentation still alive?
2069  if (!CrashReporter)
2070  return;
2071 
2072  assert(PrintCrashIR && "Did not expect to get here without option set.");
2073  CrashReporter->reportCrashIR();
2074 }
2075 
2077  if (!CrashReporter)
2078  return;
2079 
2080  assert(PrintCrashIR && "Did not expect to get here without option set.");
2081  CrashReporter = nullptr;
2082 }
2083 
2086  if (!PrintCrashIR || CrashReporter)
2087  return;
2088 
2089  sys::AddSignalHandler(SignalHandler, nullptr);
2090  CrashReporter = this;
2091 
2093  Any IR) {
2094  SavedIR.clear();
2096  OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
2097  llvm::forcePrintModuleIR() ? "Module " : "", PassID);
2098  if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
2099  OS << " Filtered Out ***\n";
2100  return;
2101  }
2102  OS << " Started ***\n";
2103  unwrapAndPrint(OS, IR);
2104  });
2105 }
2106 
2109  PrintIR.registerCallbacks(PIC);
2110  PrintPass.registerCallbacks(PIC);
2111  TimePasses.registerCallbacks(PIC);
2112  OptNone.registerCallbacks(PIC);
2113  OptPassGate.registerCallbacks(PIC);
2114  if (FAM)
2115  PreservedCFGChecker.registerCallbacks(PIC, *FAM);
2116  PrintChangedIR.registerCallbacks(PIC);
2117  PseudoProbeVerification.registerCallbacks(PIC);
2118  if (VerifyEach)
2119  Verify.registerCallbacks(PIC);
2120  PrintChangedDiff.registerCallbacks(PIC);
2121  WebsiteChangeReporter.registerCallbacks(PIC);
2122  PrintCrashIR.registerCallbacks(PIC);
2123  // TimeProfiling records the pass running time cost.
2124  // Its 'BeforePassCallback' can be appended at the tail of all the
2125  // BeforeCallbacks by calling `registerCallbacks` in the end.
2126  // Its 'AfterPassCallback' is put at the front of all the
2127  // AfterCallbacks by its `registerCallbacks`. This is necessary
2128  // to ensure that other callbacks are not included in the timings.
2129  TimeProfilingPasses.registerCallbacks(PIC);
2130 }
2131 
2132 template class ChangeReporter<std::string>;
2133 template class TextChangeReporter<std::string>;
2134 
2135 template class BlockDataT<EmptyData>;
2136 template class FuncDataT<EmptyData>;
2137 template class IRDataT<EmptyData>;
2138 template class ChangeReporter<IRDataT<EmptyData>>;
2140 template class IRComparer<EmptyData>;
2141 
2142 } // namespace llvm
llvm::OrderedChangedData
Definition: StandardInstrumentations.h:293
llvm::sys::fs::createUniquePath
void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
Definition: Path.cpp:796
llvm::BlockDataT::getData
const T & getData() const
Definition: StandardInstrumentations.h:283
llvm::SuccIterator
Definition: CFG.h:138
llvm::sys::findProgramByName
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
llvm::InLineChangePrinter::~InLineChangePrinter
~InLineChangePrinter() override
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
MemoryBuffer.h
llvm::IRDataT
Definition: StandardInstrumentations.h:342
llvm::IRComparer::generateFunctionData
static bool generateFunctionData(IRDataT< T > &Data, const Function &F)
Definition: StandardInstrumentations.cpp:608
llvm::PassInstrumentationCallbacks::registerAfterPassInvalidatedCallback
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:119
Signals.h
PreservedCFGCheckerAnalysis
Definition: StandardInstrumentations.cpp:994
llvm::PrintChanged
cl::opt< ChangePrinter > PrintChanged
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::ChildEdgeIterator
DisplayNode::EdgeIterator ChildEdgeIterator
Definition: StandardInstrumentations.cpp:1728
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
Pass
print lazy value Lazy Value Info Printer Pass
Definition: LazyValueInfo.cpp:1999
Optional.h
llvm::DotCfgChangeReporter::~DotCfgChangeReporter
~DotCfgChangeReporter() override
Definition: StandardInstrumentations.cpp:2005
llvm::getTimeTraceProfilerInstance
TimeTraceProfiler * getTimeTraceProfilerInstance()
Definition: TimeProfiler.cpp:54
intptr_t
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:104
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:774
llvm::cl::Prefix
@ Prefix
Definition: CommandLine.h:161
llvm::OrderedChangedData::getOrder
std::vector< std::string > & getOrder()
Definition: StandardInstrumentations.h:296
llvm::succ_end
Interval::succ_iterator succ_end(Interval *I)
Definition: Interval.h:102
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::nodes_iterator
DotCfgDiffDisplayGraph::NodeIterator nodes_iterator
Definition: StandardInstrumentations.cpp:1726
T
llvm::StringRef::front
char front() const
front - Get the first character in the string.
Definition: StringRef.h:140
llvm::Function
Definition: Function.h:60
llvm::Loop
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:547
StringRef.h
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:629
DotCfgDir
static cl::opt< std::string > DotCfgDir("dot-cfg-dir", cl::desc("Generate dot files into specified directory for changed IRs"), cl::Hidden, cl::init("./"))
llvm::TextChangeReporter::TextChangeReporter
TextChangeReporter(bool Verbose)
Definition: StandardInstrumentations.cpp:418
addEdge
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
Definition: LazyCallGraph.cpp:60
llvm::InlinerFunctionImportStatsOpts::Verbose
@ Verbose
llvm::PassInstrumentationCallbacks::registerBeforeNonSkippedPassCallback
void registerBeforeNonSkippedPassCallback(CallableT C)
Definition: PassInstrumentation.h:106
llvm::ChangePrinter::Quiet
@ Quiet
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::child_begin
static ChildIteratorType child_begin(NodeRef N)
Definition: StandardInstrumentations.cpp:1733
llvm::DotCfgChangeReporter::generateIRRepresentation
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< DCData > &Output) override
Definition: StandardInstrumentations.cpp:1914
llvm::DotCfgChangeReporter::handleFunctionCompare
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< DCData > &Before, const FuncDataT< DCData > &After)
Definition: StandardInstrumentations.cpp:1829
llvm::StandardInstrumentations::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM=nullptr)
Definition: StandardInstrumentations.cpp:2107
llvm::OptPassGate::isEnabled
virtual bool isEnabled() const
isEnabled() should return true before calling shouldRunPass().
Definition: OptBisect.h:38
llvm::DotCfgChangeReporter::DotCfgChangeReporter
DotCfgChangeReporter(bool Verbose)
Definition: StandardInstrumentations.cpp:1826
llvm::AllAnalysesOn
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
Definition: PassManager.h:90
llvm::PrintIRInstrumentation::~PrintIRInstrumentation
~PrintIRInstrumentation()
Definition: StandardInstrumentations.cpp:628
Content
T Content
Definition: ELFObjHandler.cpp:89
llvm::InLineChangePrinter::handleFunctionCompare
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
Definition: StandardInstrumentations.cpp:1146
llvm::DCData::end
StringMap< std::string >::const_iterator end() const
Definition: StandardInstrumentations.h:441
Error.h
llvm::DotCfgChangeReporter::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:2030
llvm::ChangePrinter::ColourDiffVerbose
@ ColourDiffVerbose
FAM
FunctionAnalysisManager FAM
Definition: PassBuilderBindings.cpp:59
llvm::verifyFunction
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
Definition: Verifier.cpp:6319
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:140
llvm::DotCfgChangeReporter::omitAfter
void omitAfter(StringRef PassID, std::string &Name) override
Definition: StandardInstrumentations.cpp:1919
Module.h
llvm::PassInstrumentationCallbacks::registerAnalysesClearedCallback
void registerAnalysesClearedCallback(CallableT C)
Definition: PassInstrumentation.h:147
llvm::IRChangedPrinter::generateIRRepresentation
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
Definition: StandardInstrumentations.cpp:462
llvm::DotCfgChangeReporter::handleInitialIR
void handleInitialIR(Any IR) override
Definition: StandardInstrumentations.cpp:1890
PIC
PassInstrumentationCallbacks PIC
Definition: PassBuilderBindings.cpp:55
llvm::ore::NV
DiagnosticInfoOptimizationBase::Argument NV
Definition: OptimizationRemarkEmitter.h:136
llvm::successors
auto successors(MachineBasicBlock *BB)
Definition: MachineSSAContext.h:29
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
llvm::PrintCrashIRInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:2084
llvm::InLineChangePrinter::generateIRRepresentation
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override
Definition: StandardInstrumentations.cpp:1124
llvm::PreservedCFGCheckerInstrumentation::CFG::printDiff
static void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
Definition: StandardInstrumentations.cpp:926
llvm::ChangePrinter
ChangePrinter
Definition: PrintPasses.h:18
LegacyPassManager.h
OptBisectPrintIRPath
static cl::opt< std::string > OptBisectPrintIRPath("opt-bisect-print-ir-path", cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden)
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
endif
__FakeVCSRevision h endif() endif() set(generated_files "$
Definition: CMakeLists.txt:16
llvm::PassInstrumentationCallbacks::getPassNameForClassName
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
Definition: PassInstrumentation.cpp:27
llvm::PreservedCFGCheckerInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM)
Definition: StandardInstrumentations.cpp:1020
llvm::ChangeReporter::registerRequiredCallbacks
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:401
llvm::shouldPrintBeforeAll
bool shouldPrintBeforeAll()
Definition: PrintPasses.cpp:121
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
llvm::FuncDataT::getEntryBlockName
std::string getEntryBlockName() const
Definition: StandardInstrumentations.h:334
Verify
ppc ctr loops PowerPC CTR Loops Verify
Definition: PPCCTRLoopsVerify.cpp:77
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::shouldPrintAfterSomePass
bool shouldPrintAfterSomePass()
Definition: PrintPasses.cpp:112
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::nodes_begin
static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G)
Definition: StandardInstrumentations.cpp:1737
CommandLine.h
llvm::TextChangeReporter< std::string >::Out
raw_ostream & Out
Definition: StandardInstrumentations.h:241
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:251
llvm::IRComparer::compare
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
Definition: StandardInstrumentations.cpp:560
llvm::PrintPassOptions::SkipAnalyses
bool SkipAnalyses
Don't print information for analyses.
Definition: StandardInstrumentations.h:90
llvm::PrintIRInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:727
llvm::DCData::DCData
DCData(const BasicBlock &B)
Definition: StandardInstrumentations.cpp:1803
llvm::OptNoneInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:749
llvm::DotCfgChangeReporter::genHTML
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
Definition: StandardInstrumentations.cpp:1871
llvm::LazyCallGraph::SCC
An SCC of the call graph.
Definition: LazyCallGraph.h:420
llvm::FuncDataT
Definition: StandardInstrumentations.h:329
Constants.h
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::child_edge_begin
static ChildEdgeIterator child_edge_begin(NodeRef N)
Definition: StandardInstrumentations.cpp:1743
llvm::OptPassGateInstrumentation::shouldRun
bool shouldRun(StringRef PassName, Any IR)
Definition: StandardInstrumentations.cpp:770
llvm::PrintPassOptions
Definition: StandardInstrumentations.h:86
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::OrderedChangedData::getData
StringMap< T > & getData()
Definition: StandardInstrumentations.h:300
llvm::timeTraceProfilerBegin
void timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
Definition: TimeProfiler.cpp:344
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
finalize
arc branch finalize
Definition: ARCBranchFinalize.cpp:65
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getGraphName
static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData)
Definition: StandardInstrumentations.cpp:1757
llvm::StringMap::insert
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:275
llvm::VerifyInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:1086
llvm::TimeProfilingPassesHandler::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:1177
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
PassInstrumentation.h
llvm::OptPassGate
Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...
Definition: OptBisect.h:26
llvm::ChangePrinter::Verbose
@ Verbose
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:486
PreservedCFGCheckerAnalysis::Key
static AnalysisKey Key
Definition: StandardInstrumentations.cpp:998
llvm::isSpecialPass
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
Definition: PassInstrumentation.cpp:33
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::getEntryNode
static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G)
Definition: StandardInstrumentations.cpp:1730
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::ChangePrinter::DiffQuiet
@ DiffQuiet
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::logicalview::LVSortMode::Line
@ Line
llvm::printLoop
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
Definition: LoopInfo.cpp:977
llvm::Instruction
Definition: Instruction.h:42
llvm::OrderedChangedData::report
static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const T *, const T *)> HandlePair)
Definition: StandardInstrumentations.cpp:488
llvm::DCData::getSuccessorLabel
StringRef getSuccessorLabel(StringRef S) const
Definition: StandardInstrumentations.h:446
llvm::StandardInstrumentations::StandardInstrumentations
StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
Definition: StandardInstrumentations.cpp:2047
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::StringRef::take_until
StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
Definition: StringRef.h:596
llvm::StringRef::drop_until
StringRef drop_until(function_ref< bool(char)> F) const
Return a StringRef equal to 'this', but with all characters not satisfying the given predicate droppe...
Definition: StringRef.h:622
llvm::shouldPrintBeforeSomePass
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
Definition: PrintPasses.cpp:108
llvm::BlockDataT
Definition: StandardInstrumentations.h:267
IR
Statically lint checks LLVM IR
Definition: Lint.cpp:746
llvm::DotCfgChangeReporter::N
unsigned N
Definition: StandardInstrumentations.h:501
llvm::AnalysisManager::Invalidator
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:661
llvm::PassInstrumentationCallbacks::registerShouldRunOptionalPassCallback
void registerShouldRunOptionalPassCallback(CallableT C)
Definition: PassInstrumentation.h:96
LazyCallGraph.h
AfterColour
static cl::opt< std::string > AfterColour("dot-cfg-after-color", cl::desc("Color for dot-cfg after elements"), cl::Hidden, cl::init("forestgreen"))
FormatVariadic.h
PrintPasses.h
llvm::Loop::getName
StringRef getName() const
Definition: LoopInfo.h:891
llvm::PrintPassOptions::Indent
bool Indent
Indent based on hierarchy.
Definition: StandardInstrumentations.h:92
llvm::DotCfgChangeReporter::handleAfter
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, Any) override
Definition: StandardInstrumentations.cpp:1928
llvm::LLVMContext::getOptPassGate
OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time.
Definition: LLVMContext.cpp:355
llvm::DCData::addSuccessorLabel
void addSuccessorLabel(StringRef Succ, StringRef Label)
Definition: StandardInstrumentations.h:453
llvm::PrintCrashIRInstrumentation::reportCrashIR
void reportCrashIR()
Definition: StandardInstrumentations.cpp:2064
llvm::StringMap< unsigned >
llvm::SmallString
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
LoopInfo.h
llvm::DOTGraphTraits
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
Definition: DOTGraphTraits.h:166
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
llvm::DotCfgChangeReporter::handleIgnored
void handleIgnored(StringRef PassID, std::string &Name) override
Definition: StandardInstrumentations.cpp:1961
llvm::ChangeReporter::~ChangeReporter
virtual ~ChangeReporter()
Definition: StandardInstrumentations.cpp:331
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::DOTGraphTraits
DOTGraphTraits(bool Simple=false)
Definition: StandardInstrumentations.cpp:1753
llvm::PassInstrumentationCallbacks::registerBeforeAnalysisCallback
void registerBeforeAnalysisCallback(CallableT C)
Definition: PassInstrumentation.h:128
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::cl::opt< bool >
llvm::SmallString::c_str
const char * c_str()
Definition: SmallString.h:263
llvm::ChangeReporter
Definition: StandardInstrumentations.h:175
llvm::PassInstrumentationCallbacks::registerAnalysisInvalidatedCallback
void registerAnalysisInvalidatedCallback(CallableT C)
Definition: PassInstrumentation.h:142
Index
uint32_t Index
Definition: ELFObjHandler.cpp:83
llvm::PrintCrashIRInstrumentation::SavedIR
std::string SavedIR
Definition: StandardInstrumentations.h:515
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getNodeLabel
static std::string getNodeLabel(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
Definition: StandardInstrumentations.cpp:1764
PrintChangedBefore
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
isInteresting
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
Definition: IVUsers.cpp:56
llvm::shouldPrintAfterAll
bool shouldPrintAfterAll()
Definition: PrintPasses.cpp:123
llvm::ChangePrinter::DotCfgVerbose
@ DotCfgVerbose
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
llvm::DenseMap
Definition: DenseMap.h:714
llvm::AnalysisKey
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: PassManager.h:69
llvm::ChangeReporter::handleIRAfterPass
void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName)
Definition: StandardInstrumentations.cpp:358
llvm::TextChangeReporter
Definition: StandardInstrumentations.h:224
llvm::DisplayGraph
bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
Definition: GraphWriter.cpp:190
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::succ_begin
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Definition: Interval.h:99
llvm::ChangePrinter::DotCfgQuiet
@ DotCfgQuiet
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:447
llvm::PreservedCFGCheckerInstrumentation::CFG::BBGuards
Optional< DenseMap< intptr_t, BBGuard > > BBGuards
Definition: StandardInstrumentations.h:130
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1868
llvm::isFunctionInPrintList
bool isFunctionInPrintList(StringRef FunctionName)
Definition: PrintPasses.cpp:151
llvm::sys::AddSignalHandler
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
llvm::PrintCrashIRInstrumentation::~PrintCrashIRInstrumentation
~PrintCrashIRInstrumentation()
Definition: StandardInstrumentations.cpp:2076
llvm::StringMap::begin
iterator begin()
Definition: StringMap.h:203
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::PrintCrashIRInstrumentation
Definition: StandardInstrumentations.h:506
llvm::IRComparer::analyzeIR
static void analyzeIR(Any IR, IRDataT< T > &Data)
Definition: StandardInstrumentations.cpp:587
Regex.h
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::DotCfgChangeReporter::initializeHTML
bool initializeHTML()
Definition: StandardInstrumentations.cpp:1969
llvm::sys::fs::expand_tilde
void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
PreservedCFGCheckerAnalysis::run
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
Definition: StandardInstrumentations.cpp:1005
llvm::WriteGraph
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
Definition: GraphWriter.h:359
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::printBeforePasses
std::vector< std::string > printBeforePasses()
Definition: PrintPasses.cpp:133
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:906
llvm::PreservedAnalyses::allAnalysesInSetPreserved
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
Definition: PassManager.h:335
llvm::PreservedCFGCheckerInstrumentation::CFG::invalidate
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
Definition: StandardInstrumentations.cpp:1012
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:66
NDEBUG
#define NDEBUG
Definition: regutils.h:48
llvm::StringMapImpl::size
unsigned size() const
Definition: StringMap.h:95
llvm::PreservedCFGCheckerInstrumentation::CFG
Definition: StandardInstrumentations.h:129
llvm::AnalysisInfoMixin
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:394
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getEdgeSourceLabel
static std::string getEdgeSourceLabel(const DisplayNode *From, DisplayNode::ChildIterator &To)
Definition: StandardInstrumentations.cpp:1772
llvm::LazyCallGraph::Node
A node in the call graph.
Definition: LazyCallGraph.h:316
llvm::printAfterPasses
std::vector< std::string > printAfterPasses()
Definition: PrintPasses.cpp:137
llvm::IRChangedPrinter::handleAfter
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
Definition: StandardInstrumentations.cpp:469
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1715
llvm::sys::fs::remove
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
llvm::Sched::Source
@ Source
Definition: TargetLowering.h:99
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::NodeRef
const DisplayNode * NodeRef
Definition: StandardInstrumentations.cpp:1724
llvm::any_of
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1741
llvm::OptPassGate::shouldRunPass
virtual bool shouldRunPass(const StringRef PassName, StringRef IRDescription)
IRDescription is a textual description of the IR unit the pass is running over.
Definition: OptBisect.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::ChangeReporter::saveIRBeforePass
void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName)
Definition: StandardInstrumentations.cpp:336
llvm::TimePassesHandler::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: PassTimingInfo.cpp:299
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getGraphProperties
static std::string getGraphProperties(const DotCfgDiffDisplayGraph *DiffData)
Definition: StandardInstrumentations.cpp:1761
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::CFGAnalyses
Represents analyses that only rely on functions' control flow.
Definition: PassManager.h:113
llvm::cl::Sink
@ Sink
Definition: CommandLine.h:168
VerifyEach
bool VerifyEach
Definition: PassBuilderBindings.cpp:52
Number
uint32_t Number
Definition: Profile.cpp:47
getParent
static const Function * getParent(const Value *V)
Definition: BasicAliasAnalysis.cpp:805
llvm::PseudoProbeVerifier::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: SampleProfileProbe.cpp:87
llvm::PreservedCFGCheckerInstrumentation::CFG::isPoisoned
bool isPoisoned() const
Definition: StandardInstrumentations.h:139
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::ChildIteratorType
DisplayNode::ChildIterator ChildIteratorType
Definition: StandardInstrumentations.cpp:1725
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::M68kBeads::Term
@ Term
Definition: M68kBaseInfo.h:71
CallGraphSCCPass.h
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:308
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:441
registerCallbacks
SI registerCallbacks(PIC, &FAM)
llvm::PrintPassOptions::Verbose
bool Verbose
Print adaptors and pass managers.
Definition: StandardInstrumentations.h:88
llvm::PassInstrumentationCallbacks::registerAfterPassCallback
void registerAfterPassCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:111
CFG
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to CFG
Definition: README.txt:39
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
llvm::InLineChangePrinter::handleAfter
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override
Definition: StandardInstrumentations.cpp:1129
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
llvm::Any
Definition: Any.h:28
Verifier.h
llvm::pdb::PDB_SymType::Label
@ Label
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
GraphWriter.h
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::size
static unsigned size(const DotCfgDiffDisplayGraph *G)
Definition: StandardInstrumentations.cpp:1748
llvm::doSystemDiff
std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
Definition: PrintPasses.cpp:158
llvm::isPassInPrintList
bool isPassInPrintList(StringRef PassName)
Definition: PrintPasses.cpp:143
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::AnalysisManager::getCachedResult
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:793
Function.h
llvm::LoopBase::getHeader
BlockT * getHeader() const
Definition: LoopInfo.h:105
llvm::DotCfgChangeReporter::handleInvalidated
void handleInvalidated(StringRef PassID) override
Definition: StandardInstrumentations.cpp:1944
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
PassManager.h
llvm::PassInstrumentationCallbacks::registerBeforeSkippedPassCallback
void registerBeforeSkippedPassCallback(CallableT C)
Definition: PassInstrumentation.h:101
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::edge_dest
static NodeRef edge_dest(EdgeRef E)
Definition: StandardInstrumentations.cpp:1747
llvm::InLineChangePrinter::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:1167
llvm::StringMap::count
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:245
llvm::AnalysisManager::registerPass
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
Definition: PassManager.h:836
llvm::ChangeReporter::handleInvalidatedPass
void handleInvalidatedPass(StringRef PassID)
Definition: StandardInstrumentations.cpp:388
Any.h
BeforeColour
static cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements"), cl::Hidden, cl::init("red"))
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::EdgeRef
const DisplayEdge * EdgeRef
Definition: StandardInstrumentations.cpp:1727
llvm::PreservedCFGCheckerInstrumentation::CFG::CFG
CFG(const Function *F, bool TrackBBLifetime)
Definition: StandardInstrumentations.cpp:885
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
DotBinary
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
llvm::ChangePrinter::ColourDiffQuiet
@ ColourDiffQuiet
CrashRecoveryContext.h
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition: raw_ostream.cpp:494
llvm::PassInstrumentationCallbacks
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
Definition: PassInstrumentation.h:66
llvm::DCData::begin
StringMap< std::string >::const_iterator begin() const
Definition: StandardInstrumentations.h:438
N
#define N
Program.h
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::renderNodesUsingHTML
static bool renderNodesUsingHTML()
Definition: StandardInstrumentations.cpp:1756
llvm::SmallVectorImpl::pop_back_val
T pop_back_val()
Definition: SmallVector.h:677
llvm::forcePrintModuleIR
bool forcePrintModuleIR()
Definition: PrintPasses.cpp:141
llvm::DefaultDOTGraphTraits
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
Definition: DOTGraphTraits.h:28
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::nodes_end
static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G)
Definition: StandardInstrumentations.cpp:1740
getNodeLabel
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
Definition: ModuleSummaryIndex.cpp:488
CommonColour
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
llvm::DCData
Definition: StandardInstrumentations.h:432
llvm::timeTraceProfilerEnd
void timeTraceProfilerEnd()
Manually end the last time section.
Definition: TimeProfiler.cpp:356
llvm::PreservedAnalyses::getChecker
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition: PassManager.h:310
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:42
llvm::StringRef::str
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:221
llvm::StringRef::find
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:294
llvm::ChangePrinter::DiffVerbose
@ DiffVerbose
llvm::IRChangedPrinter::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:456
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getNodeAttributes
static std::string getNodeAttributes(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
Definition: StandardInstrumentations.cpp:1768
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::child_end
static ChildIteratorType child_end(NodeRef N)
Definition: StandardInstrumentations.cpp:1736
llvm::PassInstrumentationCallbacks::registerAfterAnalysisCallback
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:133
llvm::sys::ExecuteAndWait
int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef >> Env=std::nullopt, ArrayRef< std::optional< StringRef >> Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
Definition: Program.cpp:32
llvm::GraphTraits
Definition: GraphTraits.h:37
From
BlockVerifier::State From
Definition: BlockVerifier.cpp:55
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3276
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
llvm::cl::desc
Definition: CommandLine.h:413
llvm::Regex
Definition: Regex.h:28
llvm::BranchInst
Conditional or Unconditional Branch instruction.
Definition: Instructions.h:3132
raw_ostream.h
llvm::DotCfgChangeReporter::HTML
std::unique_ptr< raw_fd_ostream > HTML
Definition: StandardInstrumentations.h:502
llvm::DOTGraphTraits< DotCfgDiffDisplayGraph * >::getEdgeAttributes
static std::string getEdgeAttributes(const DisplayNode *From, DisplayNode::ChildIterator &To, const DotCfgDiffDisplayGraph *DiffData)
Definition: StandardInstrumentations.cpp:1776
llvm::IRComparer
Definition: StandardInstrumentations.h:347
llvm::raw_string_ostream::str
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:647
llvm::TimeProfilingPassesHandler::TimeProfilingPassesHandler
TimeProfilingPassesHandler()
Definition: StandardInstrumentations.cpp:1175
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::GraphTraits< DotCfgDiffDisplayGraph * >::child_edge_end
static ChildEdgeIterator child_edge_end(NodeRef N)
Definition: StandardInstrumentations.cpp:1746
llvm::DotCfgChangeReporter::handleFiltered
void handleFiltered(StringRef PassID, std::string &Name) override
Definition: StandardInstrumentations.cpp:1952
Debug.h
printBBName
static void printBBName(raw_ostream &out, const BasicBlock *BB)
Definition: StandardInstrumentations.cpp:900
PassName
static const char PassName[]
Definition: X86LowerAMXIntrinsics.cpp:671
llvm::logicalview::LVReportKind::Children
@ Children
llvm::StringRef::drop_front
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:602
llvm::PreservedCFGCheckerInstrumentation::CFG::Graph
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
Definition: StandardInstrumentations.h:131
llvm::verifyModule
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Definition: Verifier.cpp:6330
llvm::PrintPassInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:810
StandardInstrumentations.h
Other
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1251
llvm::SmallVectorImpl::emplace_back
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:941
llvm::PreservedCFGCheckerInstrumentation::VerifyPreservedCFG
static cl::opt< bool > VerifyPreservedCFG
Definition: StandardInstrumentations.h:155
PrintCrashIR
static cl::opt< bool > PrintCrashIR("print-on-crash", cl::desc("Print the last form of the IR before crash"), cl::Hidden)
llvm::OptPassGateInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:791