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