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