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