LLVM  14.0.0git
StandardInstrumentations.cpp
Go to the documentation of this file.
1 //===- Standard pass instrumentations handling ----------------*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines IR-printing pass instrumentation callbacks as well as
11 /// StandardInstrumentations class that manages standard pass instrumentations.
12 ///
13 //===----------------------------------------------------------------------===//
14 
16 #include "llvm/ADT/Any.h"
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Analysis/LoopInfo.h"
22 #include "llvm/IR/Function.h"
24 #include "llvm/IR/Module.h"
26 #include "llvm/IR/PassManager.h"
27 #include "llvm/IR/PrintPasses.h"
28 #include "llvm/IR/Verifier.h"
30 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/Program.h"
35 #include <unordered_set>
36 #include <vector>
37 
38 using namespace llvm;
39 
41  "verify-cfg-preserved", cl::Hidden,
42 #ifdef NDEBUG
43  cl::init(false));
44 #else
45  cl::init(true));
46 #endif
47 
48 // An option that prints out the IR after passes, similar to
49 // -print-after-all except that it only prints the IR after passes that
50 // change the IR. Those passes that do not make changes to the IR are
51 // reported as not making any changes. In addition, the initial IR is
52 // also reported. Other hidden options affect the output from this
53 // option. -filter-passes will limit the output to the named passes
54 // that actually change the IR and other passes are reported as filtered out.
55 // The specified passes will either be reported as making no changes (with
56 // no IR reported) or the changed IR will be reported. Also, the
57 // -filter-print-funcs and -print-module-scope options will do similar
58 // filtering based on function name, reporting changed IRs as functions(or
59 // modules if -print-module-scope is specified) for a particular function
60 // or indicating that the IR has been filtered out. The extra options
61 // can be combined, allowing only changed IRs for certain passes on certain
62 // functions to be reported in different formats, with the rest being
63 // reported as filtered out. The -print-before-changed option will print
64 // the IR as it was before each pass that changed it. The optional
65 // value of quiet will only report when the IR changes, suppressing
66 // all other messages, including the initial IR. The values "diff" and
67 // "diff-quiet" will present the changes in a form similar to a patch, in
68 // either verbose or quiet mode, respectively. The lines that are removed
69 // and added are prefixed with '-' and '+', respectively. The
70 // -filter-print-funcs and -filter-passes can be used to filter the output.
71 // This reporter relies on the linux diff utility to do comparisons and
72 // insert the prefixes. For systems that do not have the necessary
73 // facilities, the error message will be shown in place of the expected output.
74 //
75 enum class ChangePrinter {
83 };
85  "print-changed", cl::desc("Print changed IRs"), cl::Hidden,
87  cl::values(
89  "Run in quiet mode"),
91  "Display patch-like changes"),
93  "Display patch-like changes in quiet mode"),
95  "Display patch-like changes with color"),
97  "Display patch-like changes in quiet mode with color"),
98  // Sentinel value for unspecified option.
100 
101 // An option that supports the -print-changed option. See
102 // the description for -print-changed for an explanation of the use
103 // of this option. Note that this option has no effect without -print-changed.
105  PrintPassesList("filter-passes", cl::value_desc("pass names"),
106  cl::desc("Only consider IR changes for passes whose names "
107  "match for the print-changed option"),
109 // An option that supports the -print-changed option. See
110 // the description for -print-changed for an explanation of the use
111 // of this option. Note that this option has no effect without -print-changed.
112 static cl::opt<bool>
113  PrintChangedBefore("print-before-changed",
114  cl::desc("Print before passes that change them"),
115  cl::init(false), cl::Hidden);
116 
117 // An option for specifying the diff used by print-changed=[diff | diff-quiet]
119  DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
120  cl::desc("system diff used by change reporters"));
121 
122 namespace {
123 
124 // Perform a system based diff between \p Before and \p After, using
125 // \p OldLineFormat, \p NewLineFormat, and \p UnchangedLineFormat
126 // to control the formatting of the output. Return an error message
127 // for any failures instead of the diff.
128 std::string doSystemDiff(StringRef Before, StringRef After,
129  StringRef OldLineFormat, StringRef NewLineFormat,
130  StringRef UnchangedLineFormat) {
131  StringRef SR[2]{Before, After};
132  // Store the 2 bodies into temporary files and call diff on them
133  // to get the body of the node.
134  const unsigned NumFiles = 3;
135  static std::string FileName[NumFiles];
136  static int FD[NumFiles]{-1, -1, -1};
137  for (unsigned I = 0; I < NumFiles; ++I) {
138  if (FD[I] == -1) {
140  std::error_code EC =
141  sys::fs::createTemporaryFile("tmpdiff", "txt", FD[I], SV);
142  if (EC)
143  return "Unable to create temporary file.";
144  FileName[I] = Twine(SV).str();
145  }
146  // The third file is used as the result of the diff.
147  if (I == NumFiles - 1)
148  break;
149 
150  std::error_code EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
151  if (EC)
152  return "Unable to open temporary file for writing.";
153 
154  raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
155  if (FD[I] == -1)
156  return "Error opening file for writing.";
157  OutStream << SR[I];
158  }
159 
161  if (!DiffExe)
162  return "Unable to find diff executable.";
163 
164  SmallString<128> OLF = formatv("--old-line-format={0}", OldLineFormat);
165  SmallString<128> NLF = formatv("--new-line-format={0}", NewLineFormat);
166  SmallString<128> ULF =
167  formatv("--unchanged-line-format={0}", UnchangedLineFormat);
168 
169  StringRef Args[] = {"-w", "-d", OLF, NLF, ULF, FileName[0], FileName[1]};
170  Optional<StringRef> Redirects[] = {None, StringRef(FileName[2]), None};
171  int Result = sys::ExecuteAndWait(*DiffExe, Args, None, Redirects);
172  if (Result < 0)
173  return "Error executing system diff.";
174  std::string Diff;
175  auto B = MemoryBuffer::getFile(FileName[2]);
176  if (B && *B)
177  Diff = (*B)->getBuffer().str();
178  else
179  return "Unable to read result.";
180 
181  // Clean up.
182  for (unsigned I = 0; I < NumFiles; ++I) {
183  std::error_code EC = sys::fs::remove(FileName[I]);
184  if (EC)
185  return "Unable to remove temporary file.";
186  }
187  return Diff;
188 }
189 
190 /// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
191 /// certain global filters. Will never return nullptr if \p Force is true.
192 const Module *unwrapModule(Any IR, bool Force = false) {
193  if (any_isa<const Module *>(IR))
194  return any_cast<const Module *>(IR);
195 
196  if (any_isa<const Function *>(IR)) {
197  const Function *F = any_cast<const Function *>(IR);
198  if (!Force && !isFunctionInPrintList(F->getName()))
199  return nullptr;
200 
201  return F->getParent();
202  }
203 
204  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
205  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
206  for (const LazyCallGraph::Node &N : *C) {
207  const Function &F = N.getFunction();
208  if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
209  return F.getParent();
210  }
211  }
212  assert(!Force && "Expected a module");
213  return nullptr;
214  }
215 
216  if (any_isa<const Loop *>(IR)) {
217  const Loop *L = any_cast<const Loop *>(IR);
218  const Function *F = L->getHeader()->getParent();
219  if (!Force && !isFunctionInPrintList(F->getName()))
220  return nullptr;
221  return F->getParent();
222  }
223 
224  llvm_unreachable("Unknown IR unit");
225 }
226 
227 void printIR(raw_ostream &OS, const Function *F) {
228  if (!isFunctionInPrintList(F->getName()))
229  return;
230  OS << *F;
231 }
232 
233 void printIR(raw_ostream &OS, const Module *M,
234  bool ShouldPreserveUseListOrder = false) {
236  M->print(OS, nullptr, ShouldPreserveUseListOrder);
237  } else {
238  for (const auto &F : M->functions()) {
239  printIR(OS, &F);
240  }
241  }
242 }
243 
244 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C) {
245  for (const LazyCallGraph::Node &N : *C) {
246  const Function &F = N.getFunction();
247  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
248  F.print(OS);
249  }
250  }
251 }
252 
253 void printIR(raw_ostream &OS, const Loop *L) {
254  const Function *F = L->getHeader()->getParent();
255  if (!isFunctionInPrintList(F->getName()))
256  return;
257  printLoop(const_cast<Loop &>(*L), OS);
258 }
259 
260 std::string getIRName(Any IR) {
261  if (any_isa<const Module *>(IR))
262  return "[module]";
263 
264  if (any_isa<const Function *>(IR)) {
265  const Function *F = any_cast<const Function *>(IR);
266  return F->getName().str();
267  }
268 
269  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
270  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
271  return C->getName();
272  }
273 
274  if (any_isa<const Loop *>(IR)) {
275  const Loop *L = any_cast<const Loop *>(IR);
276  std::string S;
277  raw_string_ostream OS(S);
278  L->print(OS, /*Verbose*/ false, /*PrintNested*/ false);
279  return OS.str();
280  }
281 
282  llvm_unreachable("Unknown wrapped IR type");
283 }
284 
285 bool moduleContainsFilterPrintFunc(const Module &M) {
286  return any_of(M.functions(),
287  [](const Function &F) {
288  return isFunctionInPrintList(F.getName());
289  }) ||
291 }
292 
293 bool sccContainsFilterPrintFunc(const LazyCallGraph::SCC &C) {
294  return any_of(C,
295  [](const LazyCallGraph::Node &N) {
296  return isFunctionInPrintList(N.getName());
297  }) ||
299 }
300 
301 bool shouldPrintIR(Any IR) {
302  if (any_isa<const Module *>(IR)) {
303  const Module *M = any_cast<const Module *>(IR);
304  return moduleContainsFilterPrintFunc(*M);
305  }
306 
307  if (any_isa<const Function *>(IR)) {
308  const Function *F = any_cast<const Function *>(IR);
309  return isFunctionInPrintList(F->getName());
310  }
311 
312  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
313  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
314  return sccContainsFilterPrintFunc(*C);
315  }
316 
317  if (any_isa<const Loop *>(IR)) {
318  const Loop *L = any_cast<const Loop *>(IR);
320  }
321  llvm_unreachable("Unknown wrapped IR type");
322 }
323 
324 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
325 /// llvm::Any and does actual print job.
326 void unwrapAndPrint(raw_ostream &OS, Any IR,
327  bool ShouldPreserveUseListOrder = false) {
328  if (!shouldPrintIR(IR))
329  return;
330 
331  if (forcePrintModuleIR()) {
332  auto *M = unwrapModule(IR);
333  assert(M && "should have unwrapped module");
334  printIR(OS, M, ShouldPreserveUseListOrder);
335  return;
336  }
337 
338  if (any_isa<const Module *>(IR)) {
339  const Module *M = any_cast<const Module *>(IR);
340  printIR(OS, M, ShouldPreserveUseListOrder);
341  return;
342  }
343 
344  if (any_isa<const Function *>(IR)) {
345  const Function *F = any_cast<const Function *>(IR);
346  printIR(OS, F);
347  return;
348  }
349 
350  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
351  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
352  printIR(OS, C);
353  return;
354  }
355 
356  if (any_isa<const Loop *>(IR)) {
357  const Loop *L = any_cast<const Loop *>(IR);
358  printIR(OS, L);
359  return;
360  }
361  llvm_unreachable("Unknown wrapped IR type");
362 }
363 
364 // Return true when this is a pass for which changes should be ignored
365 bool isIgnored(StringRef PassID) {
366  return isSpecialPass(PassID,
367  {"PassManager", "PassAdaptor", "AnalysisManagerProxy",
368  "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass"});
369 }
370 
371 } // namespace
372 
373 template <typename IRUnitT>
375  assert(BeforeStack.empty() && "Problem with Change Printer stack.");
376 }
377 
378 template <typename IRUnitT>
380  return isFunctionInPrintList(F.getName());
381 }
382 
383 template <typename IRUnitT>
385  if (isIgnored(PassID))
386  return false;
387 
388  static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
389  PrintPassesList.end());
390  return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
391 }
392 
393 // Return true when this is a pass on IR for which printing
394 // of changes is desired.
395 template <typename IRUnitT>
397  if (!isInterestingPass(PassID))
398  return false;
399  if (any_isa<const Function *>(IR))
400  return isInterestingFunction(*any_cast<const Function *>(IR));
401  return true;
402 }
403 
404 template <typename IRUnitT>
406  // Always need to place something on the stack because invalidated passes
407  // are not given the IR so it cannot be determined whether the pass was for
408  // something that was filtered out.
409  BeforeStack.emplace_back();
410 
411  if (!isInteresting(IR, PassID))
412  return;
413  // Is this the initial IR?
414  if (InitialIR) {
415  InitialIR = false;
416  if (VerboseMode)
417  handleInitialIR(IR);
418  }
419 
420  // Save the IR representation on the stack.
421  IRUnitT &Data = BeforeStack.back();
422  generateIRRepresentation(IR, PassID, Data);
423 }
424 
425 template <typename IRUnitT>
427  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
428 
429  std::string Name = getIRName(IR);
430 
431  if (isIgnored(PassID)) {
432  if (VerboseMode)
433  handleIgnored(PassID, Name);
434  } else if (!isInteresting(IR, PassID)) {
435  if (VerboseMode)
436  handleFiltered(PassID, Name);
437  } else {
438  // Get the before rep from the stack
439  IRUnitT &Before = BeforeStack.back();
440  // Create the after rep
441  IRUnitT After;
442  generateIRRepresentation(IR, PassID, After);
443 
444  // Was there a change in IR?
445  if (same(Before, After)) {
446  if (VerboseMode)
447  omitAfter(PassID, Name);
448  } else
449  handleAfter(PassID, Name, Before, After, IR);
450  }
451  BeforeStack.pop_back();
452 }
453 
454 template <typename IRUnitT>
456  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
457 
458  // Always flag it as invalidated as we cannot determine when
459  // a pass for a filtered function is invalidated since we do not
460  // get the IR in the call. Also, the output is just alternate
461  // forms of the banner anyway.
462  if (VerboseMode)
463  handleInvalidated(PassID);
464  BeforeStack.pop_back();
465 }
466 
467 template <typename IRUnitT>
471  [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); });
472 
474  [this](StringRef P, Any IR, const PreservedAnalyses &) {
475  handleIRAfterPass(IR, P);
476  });
478  [this](StringRef P, const PreservedAnalyses &) {
479  handleInvalidatedPass(P);
480  });
481 }
482 
484  : Label(B.getName().str()) {
486  B.print(SS, nullptr, true, true);
487 }
488 
489 template <typename IRUnitT>
491  : ChangeReporter<IRUnitT>(Verbose), Out(dbgs()) {}
492 
493 template <typename IRUnitT>
495  // Always print the module.
496  // Unwrap and print directly to avoid filtering problems in general routines.
497  auto *M = unwrapModule(IR, /*Force=*/true);
498  assert(M && "Expected module to be unwrapped when forced.");
499  Out << "*** IR Dump At Start ***\n";
500  M->print(Out, nullptr,
501  /*ShouldPreserveUseListOrder=*/true);
502 }
503 
504 template <typename IRUnitT>
506  std::string &Name) {
507  Out << formatv("*** IR Dump After {0} on {1} omitted because no change ***\n",
508  PassID, Name);
509 }
510 
511 template <typename IRUnitT>
513  Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
514 }
515 
516 template <typename IRUnitT>
518  std::string &Name) {
519  SmallString<20> Banner =
520  formatv("*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
521  Out << Banner;
522 }
523 
524 template <typename IRUnitT>
526  std::string &Name) {
527  Out << formatv("*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
528 }
529 
530 IRChangedPrinter::~IRChangedPrinter() {}
531 
536 }
537 
539  std::string &Output) {
540  raw_string_ostream OS(Output);
541  unwrapAndPrint(OS, IR,
542  /*ShouldPreserveUseListOrder=*/true);
543  OS.str();
544 }
545 
546 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
547  const std::string &Before,
548  const std::string &After, Any) {
549  // Report the IR before the changes when requested.
550  if (PrintChangedBefore)
551  Out << "*** IR Dump Before " << PassID << " on " << Name << " ***\n"
552  << Before;
553 
554  // We might not get anything to print if we only want to print a specific
555  // function but it gets deleted.
556  if (After.empty()) {
557  Out << "*** IR Deleted After " << PassID << " on " << Name << " ***\n";
558  return;
559  }
560 
561  Out << "*** IR Dump After " << PassID << " on " << Name << " ***\n" << After;
562 }
563 
564 bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) {
565  return S1 == S2;
566 }
567 
568 template <typename IRData>
570  const OrderedChangedData &Before, const OrderedChangedData &After,
571  function_ref<void(const IRData *, const IRData *)> HandlePair) {
572  const auto &BFD = Before.getData();
573  const auto &AFD = After.getData();
574  std::vector<std::string>::const_iterator BI = Before.getOrder().begin();
575  std::vector<std::string>::const_iterator BE = Before.getOrder().end();
576  std::vector<std::string>::const_iterator AI = After.getOrder().begin();
577  std::vector<std::string>::const_iterator AE = After.getOrder().end();
578 
579  auto handlePotentiallyRemovedIRData = [&](std::string S) {
580  // The order in LLVM may have changed so check if still exists.
581  if (!AFD.count(S)) {
582  // This has been removed.
583  HandlePair(&BFD.find(*BI)->getValue(), nullptr);
584  }
585  };
586  auto handleNewIRData = [&](std::vector<const IRData *> &Q) {
587  // Print out any queued up new sections
588  for (const IRData *NBI : Q)
589  HandlePair(nullptr, NBI);
590  Q.clear();
591  };
592 
593  // Print out the IRData in the after order, with before ones interspersed
594  // appropriately (ie, somewhere near where they were in the before list).
595  // Start at the beginning of both lists. Loop through the
596  // after list. If an element is common, then advance in the before list
597  // reporting the removed ones until the common one is reached. Report any
598  // queued up new ones and then report the common one. If an element is not
599  // common, then enqueue it for reporting. When the after list is exhausted,
600  // loop through the before list, reporting any removed ones. Finally,
601  // report the rest of the enqueued new ones.
602  std::vector<const IRData *> NewIRDataQueue;
603  while (AI != AE) {
604  if (!BFD.count(*AI)) {
605  // This section is new so place it in the queue. This will cause it
606  // to be reported after deleted sections.
607  NewIRDataQueue.emplace_back(&AFD.find(*AI)->getValue());
608  ++AI;
609  continue;
610  }
611  // This section is in both; advance and print out any before-only
612  // until we get to it.
613  while (*BI != *AI) {
614  handlePotentiallyRemovedIRData(*BI);
615  ++BI;
616  }
617  // Report any new sections that were queued up and waiting.
618  handleNewIRData(NewIRDataQueue);
619 
620  const IRData &AData = AFD.find(*AI)->getValue();
621  const IRData &BData = BFD.find(*AI)->getValue();
622  HandlePair(&BData, &AData);
623  ++BI;
624  ++AI;
625  }
626 
627  // Check any remaining before sections to see if they have been removed
628  while (BI != BE) {
629  handlePotentiallyRemovedIRData(*BI);
630  ++BI;
631  }
632 
633  handleNewIRData(NewIRDataQueue);
634 }
635 
637  StringRef Name) {
638  if (!getModuleForComparison(IR)) {
639  // Not a module so just handle the single function.
640  assert(Before.getData().size() == 1 && "Expected only one function.");
641  assert(After.getData().size() == 1 && "Expected only one function.");
642  handleFunctionCompare(Name, Prefix, PassID, false,
643  Before.getData().begin()->getValue(),
644  After.getData().begin()->getValue());
645  return;
646  }
647 
649  Before, After, [&](const ChangedFuncData *B, const ChangedFuncData *A) {
650  ChangedFuncData Missing;
651  if (!B)
652  B = &Missing;
653  else if (!A)
654  A = &Missing;
655  assert(B != &Missing && A != &Missing &&
656  "Both functions cannot be missing.");
657  handleFunctionCompare(Name, Prefix, PassID, true, *B, *A);
658  });
659 }
660 
662  if (const Module *M = getModuleForComparison(IR)) {
663  // Create data for each existing/interesting function in the module.
664  for (const Function &F : *M)
666  return;
667  }
668 
669  const Function *F = nullptr;
670  if (any_isa<const Function *>(IR))
671  F = any_cast<const Function *>(IR);
672  else {
673  assert(any_isa<const Loop *>(IR) && "Unknown IR unit.");
674  const Loop *L = any_cast<const Loop *>(IR);
675  F = L->getHeader()->getParent();
676  }
677  assert(F && "Unknown IR unit.");
679 }
680 
682  if (any_isa<const Module *>(IR))
683  return any_cast<const Module *>(IR);
684  if (any_isa<const LazyCallGraph::SCC *>(IR))
685  return any_cast<const LazyCallGraph::SCC *>(IR)
686  ->begin()
687  ->getFunction()
688  .getParent();
689  return nullptr;
690 }
691 
693  const Function &F) {
694  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
695  ChangedFuncData CFD;
696  for (const auto &B : F) {
697  CFD.getOrder().emplace_back(B.getName());
698  CFD.getData().insert({B.getName(), B});
699  }
700  Data.getOrder().emplace_back(F.getName());
701  Data.getData().insert({F.getName(), CFD});
702  return true;
703  }
704  return false;
705 }
706 
708  assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
709 }
710 
711 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
712  const Module *M = unwrapModule(IR);
713  ModuleDescStack.emplace_back(M, getIRName(IR), PassID);
714 }
715 
716 PrintIRInstrumentation::PrintModuleDesc
717 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
718  assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
719  PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
720  assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
721  return ModuleDesc;
722 }
723 
724 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
725  if (isIgnored(PassID))
726  return;
727 
728  // Saving Module for AfterPassInvalidated operations.
729  // Note: here we rely on a fact that we do not change modules while
730  // traversing the pipeline, so the latest captured module is good
731  // for all print operations that has not happen yet.
732  if (shouldPrintAfterPass(PassID))
733  pushModuleDesc(PassID, IR);
734 
735  if (!shouldPrintBeforePass(PassID))
736  return;
737 
738  if (!shouldPrintIR(IR))
739  return;
740 
741  dbgs() << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
742  << " ***\n";
743  unwrapAndPrint(dbgs(), IR);
744 }
745 
746 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
747  if (isIgnored(PassID))
748  return;
749 
750  if (!shouldPrintAfterPass(PassID))
751  return;
752 
753  const Module *M;
754  std::string IRName;
755  StringRef StoredPassID;
756  std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
757  assert(StoredPassID == PassID && "mismatched PassID");
758 
759  if (!shouldPrintIR(IR))
760  return;
761 
762  dbgs() << "*** IR Dump After " << PassID << " on " << IRName << " ***\n";
763  unwrapAndPrint(dbgs(), IR);
764 }
765 
766 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
768  if (!shouldPrintAfterPass(PassName))
769  return;
770 
771  if (isIgnored(PassID))
772  return;
773 
774  const Module *M;
775  std::string IRName;
776  StringRef StoredPassID;
777  std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
778  assert(StoredPassID == PassID && "mismatched PassID");
779  // Additional filtering (e.g. -filter-print-func) can lead to module
780  // printing being skipped.
781  if (!M)
782  return;
783 
784  SmallString<20> Banner =
785  formatv("*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
786  dbgs() << Banner << "\n";
787  printIR(dbgs(), M);
788 }
789 
790 bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
791  if (shouldPrintBeforeAll())
792  return true;
793 
796 }
797 
798 bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
799  if (shouldPrintAfterAll())
800  return true;
801 
804 }
805 
808  this->PIC = &PIC;
809 
810  // BeforePass callback is not just for printing, it also saves a Module
811  // for later use in AfterPassInvalidated.
814  [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
815 
816  if (shouldPrintAfterSomePass()) {
818  [this](StringRef P, Any IR, const PreservedAnalyses &) {
819  this->printAfterPass(P, IR);
820  });
822  [this](StringRef P, const PreservedAnalyses &) {
823  this->printAfterPassInvalidated(P);
824  });
825  }
826 }
827 
831  [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
832 }
833 
834 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
835  const Function *F = nullptr;
836  if (any_isa<const Function *>(IR)) {
837  F = any_cast<const Function *>(IR);
838  } else if (any_isa<const Loop *>(IR)) {
839  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
840  }
841  bool ShouldRun = !(F && F->hasOptNone());
842  if (!ShouldRun && DebugLogging) {
843  errs() << "Skipping pass " << PassID << " on " << F->getName()
844  << " due to optnone attribute\n";
845  }
846  return ShouldRun;
847 }
848 
851  if (!OptBisector->isEnabled())
852  return;
854  return isIgnored(PassID) || OptBisector->checkPass(PassID, getIRName(IR));
855  });
856 }
857 
858 raw_ostream &PrintPassInstrumentation::print() {
859  if (Opts.Indent) {
860  assert(Indent >= 0);
861  dbgs().indent(Indent);
862  }
863  return dbgs();
864 }
865 
868  if (!Enabled)
869  return;
870 
871  std::vector<StringRef> SpecialPasses;
872  if (!Opts.Verbose) {
873  SpecialPasses.emplace_back("PassManager");
874  SpecialPasses.emplace_back("PassAdaptor");
875  }
876 
878  [this, SpecialPasses](StringRef PassID, Any IR) {
879  assert(!isSpecialPass(PassID, SpecialPasses) &&
880  "Unexpectedly skipping special pass");
881 
882  print() << "Skipping pass: " << PassID << " on " << getIRName(IR)
883  << "\n";
884  });
885  PIC.registerBeforeNonSkippedPassCallback([this, SpecialPasses](
886  StringRef PassID, Any IR) {
887  if (isSpecialPass(PassID, SpecialPasses))
888  return;
889 
890  print() << "Running pass: " << PassID << " on " << getIRName(IR) << "\n";
891  Indent += 2;
892  });
894  [this, SpecialPasses](StringRef PassID, Any IR,
895  const PreservedAnalyses &) {
896  if (isSpecialPass(PassID, SpecialPasses))
897  return;
898 
899  Indent -= 2;
900  });
902  [this, SpecialPasses](StringRef PassID, Any IR) {
903  if (isSpecialPass(PassID, SpecialPasses))
904  return;
905 
906  Indent -= 2;
907  });
908 
909  if (!Opts.SkipAnalyses) {
911  print() << "Running analysis: " << PassID << " on " << getIRName(IR)
912  << "\n";
913  Indent += 2;
914  });
916  [this](StringRef PassID, Any IR) { Indent -= 2; });
918  print() << "Invalidating analysis: " << PassID << " on " << getIRName(IR)
919  << "\n";
920  });
922  print() << "Clearing all analysis results for: " << IRName << "\n";
923  });
924  }
925 }
926 
928  bool TrackBBLifetime) {
929  if (TrackBBLifetime)
931  for (const auto &BB : *F) {
932  if (BBGuards)
933  BBGuards->try_emplace(intptr_t(&BB), &BB);
934  for (auto *Succ : successors(&BB)) {
935  Graph[&BB][Succ]++;
936  if (BBGuards)
937  BBGuards->try_emplace(intptr_t(Succ), Succ);
938  }
939  }
940 }
941 
942 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
943  if (BB->hasName()) {
944  out << BB->getName() << "<" << BB << ">";
945  return;
946  }
947 
948  if (!BB->getParent()) {
949  out << "unnamed_removed<" << BB << ">";
950  return;
951  }
952 
953  if (BB->isEntryBlock()) {
954  out << "entry"
955  << "<" << BB << ">";
956  return;
957  }
958 
959  unsigned FuncOrderBlockNum = 0;
960  for (auto &FuncBB : *BB->getParent()) {
961  if (&FuncBB == BB)
962  break;
963  FuncOrderBlockNum++;
964  }
965  out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
966 }
967 
969  const CFG &Before,
970  const CFG &After) {
971  assert(!After.isPoisoned());
972  if (Before.isPoisoned()) {
973  out << "Some blocks were deleted\n";
974  return;
975  }
976 
977  // Find and print graph differences.
978  if (Before.Graph.size() != After.Graph.size())
979  out << "Different number of non-leaf basic blocks: before="
980  << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
981 
982  for (auto &BB : Before.Graph) {
983  auto BA = After.Graph.find(BB.first);
984  if (BA == After.Graph.end()) {
985  out << "Non-leaf block ";
986  printBBName(out, BB.first);
987  out << " is removed (" << BB.second.size() << " successors)\n";
988  }
989  }
990 
991  for (auto &BA : After.Graph) {
992  auto BB = Before.Graph.find(BA.first);
993  if (BB == Before.Graph.end()) {
994  out << "Non-leaf block ";
995  printBBName(out, BA.first);
996  out << " is added (" << BA.second.size() << " successors)\n";
997  continue;
998  }
999 
1000  if (BB->second == BA.second)
1001  continue;
1002 
1003  out << "Different successors of block ";
1004  printBBName(out, BA.first);
1005  out << " (unordered):\n";
1006  out << "- before (" << BB->second.size() << "): ";
1007  for (auto &SuccB : BB->second) {
1008  printBBName(out, SuccB.first);
1009  if (SuccB.second != 1)
1010  out << "(" << SuccB.second << "), ";
1011  else
1012  out << ", ";
1013  }
1014  out << "\n";
1015  out << "- after (" << BA.second.size() << "): ";
1016  for (auto &SuccA : BA.second) {
1017  printBBName(out, SuccA.first);
1018  if (SuccA.second != 1)
1019  out << "(" << SuccA.second << "), ";
1020  else
1021  out << ", ";
1022  }
1023  out << "\n";
1024  }
1025 }
1026 
1027 // PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
1028 // passes, that reported they kept CFG analyses up-to-date, did not actually
1029 // change CFG. This check is done as follows. Before every functional pass in
1030 // BeforeNonSkippedPassCallback a CFG snapshot (an instance of
1031 // PreservedCFGCheckerInstrumentation::CFG) is requested from
1032 // FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
1033 // functional pass finishes and reports that CFGAnalyses or AllAnalyses are
1034 // up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
1035 // available) is checked to be equal to a freshly created CFG snapshot.
1037  : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {
1039 
1041 
1042 public:
1043  /// Provide the result type for this analysis pass.
1045 
1046  /// Run the analysis pass over a function and produce CFG.
1048  return Result(&F, /* TrackBBLifetime */ true);
1049  }
1050 };
1051 
1053 
1055  Function &F, const PreservedAnalyses &PA,
1057  auto PAC = PA.getChecker<PreservedCFGCheckerAnalysis>();
1058  return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
1059  PAC.preservedSet<CFGAnalyses>());
1060 }
1061 
1064  if (!VerifyPreservedCFG)
1065  return;
1066 
1067  FAM.registerPass([&] { return PreservedCFGCheckerAnalysis(); });
1068 
1069  auto checkCFG = [](StringRef Pass, StringRef FuncName, const CFG &GraphBefore,
1070  const CFG &GraphAfter) {
1071  if (GraphAfter == GraphBefore)
1072  return;
1073 
1074  dbgs() << "Error: " << Pass
1075  << " does not invalidate CFG analyses but CFG changes detected in "
1076  "function @"
1077  << FuncName << ":\n";
1078  CFG::printDiff(dbgs(), GraphBefore, GraphAfter);
1079  report_fatal_error(Twine("CFG unexpectedly changed by ", Pass));
1080  };
1081 
1083  [this, &FAM](StringRef P, Any IR) {
1084 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1085  assert(&PassStack.emplace_back(P));
1086 #endif
1087  (void)this;
1088  if (!any_isa<const Function *>(IR))
1089  return;
1090 
1091  const auto *F = any_cast<const Function *>(IR);
1092  // Make sure a fresh CFG snapshot is available before the pass.
1094  });
1095 
1097  [this](StringRef P, const PreservedAnalyses &PassPA) {
1098 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1099  assert(PassStack.pop_back_val() == P &&
1100  "Before and After callbacks must correspond");
1101 #endif
1102  (void)this;
1103  });
1104 
1106  checkCFG](StringRef P, Any IR,
1107  const PreservedAnalyses &PassPA) {
1108 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1109  assert(PassStack.pop_back_val() == P &&
1110  "Before and After callbacks must correspond");
1111 #endif
1112  (void)this;
1113 
1114  if (!any_isa<const Function *>(IR))
1115  return;
1116 
1117  if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>() &&
1119  return;
1120 
1121  const auto *F = any_cast<const Function *>(IR);
1122  if (auto *GraphBefore = FAM.getCachedResult<PreservedCFGCheckerAnalysis>(
1123  *const_cast<Function *>(F)))
1124  checkCFG(P, F->getName(), *GraphBefore,
1125  CFG(F, /* TrackBBLifetime */ false));
1126  });
1127 }
1128 
1132  [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
1133  if (isIgnored(P) || P == "VerifierPass")
1134  return;
1135  if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
1136  const Function *F;
1137  if (any_isa<const Loop *>(IR))
1138  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
1139  else
1140  F = any_cast<const Function *>(IR);
1141  if (DebugLogging)
1142  dbgs() << "Verifying function " << F->getName() << "\n";
1143 
1144  if (verifyFunction(*F))
1145  report_fatal_error("Broken function found, compilation aborted!");
1146  } else if (any_isa<const Module *>(IR) ||
1147  any_isa<const LazyCallGraph::SCC *>(IR)) {
1148  const Module *M;
1149  if (any_isa<const LazyCallGraph::SCC *>(IR))
1150  M = any_cast<const LazyCallGraph::SCC *>(IR)
1151  ->begin()
1152  ->getFunction()
1153  .getParent();
1154  else
1155  M = any_cast<const Module *>(IR);
1156  if (DebugLogging)
1157  dbgs() << "Verifying module " << M->getName() << "\n";
1158 
1159  if (verifyModule(*M))
1160  report_fatal_error("Broken module found, compilation aborted!");
1161  }
1162  });
1163 }
1164 
1166 
1168  ChangedIRData &D) {
1170 }
1171 
1173  const ChangedIRData &Before,
1174  const ChangedIRData &After, Any IR) {
1175  SmallString<20> Banner =
1176  formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);
1177  Out << Banner;
1178  ChangedIRComparer(Out, Before, After, UseColour)
1179  .compare(IR, "", PassID, Name);
1180  Out << "\n";
1181 }
1182 
1184  const ChangedIRData &D2) {
1185  return D1 == D2;
1186 }
1187 
1189  StringRef PassID, bool InModule,
1190  const ChangedFuncData &Before,
1191  const ChangedFuncData &After) {
1192  // Print a banner when this is being shown in the context of a module
1193  if (InModule)
1194  Out << "\n*** IR for function " << Name << " ***\n";
1195 
1197  Before, After, [&](const ChangedBlockData *B, const ChangedBlockData *A) {
1198  StringRef BStr = B ? B->getBody() : "\n";
1199  StringRef AStr = A ? A->getBody() : "\n";
1200  const std::string Removed =
1201  UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";
1202  const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";
1203  const std::string NoChange = " %l\n";
1204  Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1205  });
1206 }
1207 
1214 }
1215 
1217  bool DebugLogging, bool VerifyEach, PrintPassOptions PrintPassOpts)
1218  : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
1219  PrintChangedIR(PrintChanged == ChangePrinter::PrintChangedVerbose),
1220  PrintChangedDiff(
1225  Verify(DebugLogging), VerifyEach(VerifyEach) {}
1226 
1229  PrintIR.registerCallbacks(PIC);
1230  PrintPass.registerCallbacks(PIC);
1231  TimePasses.registerCallbacks(PIC);
1232  OptNone.registerCallbacks(PIC);
1233  OptBisect.registerCallbacks(PIC);
1234  if (FAM)
1235  PreservedCFGChecker.registerCallbacks(PIC, *FAM);
1236  PrintChangedIR.registerCallbacks(PIC);
1237  PseudoProbeVerification.registerCallbacks(PIC);
1238  if (VerifyEach)
1239  Verify.registerCallbacks(PIC);
1240  PrintChangedDiff.registerCallbacks(PIC);
1241 }
1242 
1243 namespace llvm {
1244 
1245 template class ChangeReporter<std::string>;
1246 template class TextChangeReporter<std::string>;
1247 
1248 template class ChangeReporter<ChangedIRData>;
1249 template class TextChangeReporter<ChangedIRData>;
1250 
1251 } // namespace llvm
llvm::OrderedChangedData
Definition: StandardInstrumentations.h:305
DiffBinary
static cl::opt< std::string > DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"), cl::desc("system diff used by change reporters"))
llvm::sys::findProgramByName
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
llvm::InLineChangePrinter::~InLineChangePrinter
~InLineChangePrinter() override
Definition: StandardInstrumentations.cpp:1165
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
MemoryBuffer.h
llvm::StringRef::back
LLVM_NODISCARD char back() const
back - Get the last character in the string.
Definition: StringRef.h:168
llvm::sys::fs::openFileForWrite
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
Definition: FileSystem.h:1040
getName
static StringRef getName(Value *V)
Definition: ProvenanceAnalysisEvaluator.cpp:42
PreservedCFGCheckerAnalysis
Definition: StandardInstrumentations.cpp:1036
llvm::InLineChangePrinter::handleAfter
virtual void handleAfter(StringRef PassID, std::string &Name, const ChangedIRData &Before, const ChangedIRData &After, Any) override
Definition: StandardInstrumentations.cpp:1172
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
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:1966
Optional.h
intptr_t
llvm::ChangedIRComparer::generateFunctionData
static bool generateFunctionData(ChangedIRData &Data, const Function &F)
Definition: StandardInstrumentations.cpp:692
ChangePrinter::PrintChangedDiffQuiet
@ PrintChangedDiffQuiet
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:769
llvm::cl::Prefix
@ Prefix
Definition: CommandLine.h:164
llvm::IRChangedPrinter::same
bool same(const std::string &Before, const std::string &After) override
Definition: StandardInstrumentations.cpp:564
llvm::Function
Definition: Function.h:61
llvm::Loop
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:530
StringRef.h
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
ChangePrinter
ChangePrinter
Definition: StandardInstrumentations.cpp:75
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:623
ChangePrinter::PrintChangedQuiet
@ PrintChangedQuiet
llvm::TextChangeReporter::TextChangeReporter
TextChangeReporter(bool Verbose)
Definition: StandardInstrumentations.cpp:490
llvm::InlinerFunctionImportStatsOpts::Verbose
@ Verbose
llvm::PassInstrumentationCallbacks::registerBeforeNonSkippedPassCallback
void registerBeforeNonSkippedPassCallback(CallableT C)
Definition: PassInstrumentation.h:106
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
PrintPassesList
static cl::list< std::string > PrintPassesList("filter-passes", cl::value_desc("pass names"), cl::desc("Only consider IR changes for passes whose names " "match for the print-changed option"), cl::CommaSeparated, cl::Hidden)
llvm::cl::CommaSeparated
@ CommaSeparated
Definition: CommandLine.h:169
llvm::cl::ValueOptional
@ ValueOptional
Definition: CommandLine.h:136
llvm::AllAnalysesOn
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
Definition: PassManager.h:93
llvm::PrintIRInstrumentation::~PrintIRInstrumentation
~PrintIRInstrumentation()
Definition: StandardInstrumentations.cpp:707
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:5727
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
Module.h
llvm::PassInstrumentationCallbacks::registerAnalysesClearedCallback
void registerAnalysesClearedCallback(CallableT C)
Definition: PassInstrumentation.h:135
llvm::ChangeReporter::isInterestingFunction
bool isInterestingFunction(const Function &F)
Definition: StandardInstrumentations.cpp:379
llvm::IRChangedPrinter::generateIRRepresentation
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
Definition: StandardInstrumentations.cpp:538
PIC
PassInstrumentationCallbacks PIC
Definition: PassBuilderBindings.cpp:55
llvm::ChangedBlockData::ChangedBlockData
ChangedBlockData(const BasicBlock &B)
Definition: StandardInstrumentations.cpp:483
llvm::Optional
Definition: APInt.h:33
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:635
llvm::PreservedCFGCheckerInstrumentation::CFG::printDiff
static void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
Definition: StandardInstrumentations.cpp:968
llvm::successors
succ_range successors(Instruction *I)
Definition: CFG.h:262
llvm::ChangeReporter::saveIRBeforePass
void saveIRBeforePass(Any IR, StringRef PassID)
Definition: StandardInstrumentations.cpp:405
LegacyPassManager.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:56
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:1062
llvm::ChangeReporter::registerRequiredCallbacks
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:468
llvm::shouldPrintBeforeAll
bool shouldPrintBeforeAll()
Definition: PrintPasses.cpp:61
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::OrderedChangedData::getData
StringMap< IRData > & getData()
Definition: StandardInstrumentations.h:312
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::shouldPrintAfterSomePass
bool shouldPrintAfterSomePass()
Definition: PrintPasses.cpp:52
CommandLine.h
llvm::TextChangeReporter< std::string >::Out
raw_ostream & Out
Definition: StandardInstrumentations.h:250
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:250
llvm::PrintPassOptions::SkipAnalyses
bool SkipAnalyses
Don't print information for analyses.
Definition: StandardInstrumentations.h:86
llvm::StandardInstrumentations::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM=nullptr)
Definition: StandardInstrumentations.cpp:1227
llvm::MemoryBuffer::getFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Definition: MemoryBuffer.cpp:246
llvm::PrintIRInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:806
llvm::OptNoneInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:828
llvm::LazyCallGraph::SCC
An SCC of the call graph.
Definition: LazyCallGraph.h:422
llvm::PrintPassOptions
Definition: StandardInstrumentations.h:82
llvm::OptBisect
This class implements a mechanism to disable passes and individual optimizations at compile time base...
Definition: OptBisect.h:44
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::StringMap::insert
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:276
llvm::VerifyInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:1129
PassInstrumentation.h
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::OrderedChangedData::getOrder
std::vector< std::string > & getOrder()
Definition: StandardInstrumentations.h:308
PreservedCFGCheckerAnalysis::Key
static AnalysisKey Key
Definition: StandardInstrumentations.cpp:1040
llvm::isSpecialPass
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
Definition: PassInstrumentation.cpp:33
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::printLoop
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
Definition: LoopInfo.cpp:979
llvm::ChangedIRComparer::getModuleForComparison
static const Module * getModuleForComparison(Any IR)
Definition: StandardInstrumentations.cpp:681
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:140
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::shouldPrintBeforeSomePass
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
Definition: PrintPasses.cpp:48
IR
Statically lint checks LLVM IR
Definition: Lint.cpp:744
llvm::AnalysisManager::Invalidator
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:656
llvm::PassInstrumentationCallbacks::registerShouldRunOptionalPassCallback
void registerShouldRunOptionalPassCallback(CallableT C)
Definition: PassInstrumentation.h:96
LazyCallGraph.h
FormatVariadic.h
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:245
PrintPasses.h
llvm::None
const NoneType None
Definition: None.h:23
llvm::PrintPassOptions::Indent
bool Indent
Indent based on hierarchy.
Definition: StandardInstrumentations.h:88
llvm::InLineChangePrinter::generateIRRepresentation
virtual void generateIRRepresentation(Any IR, StringRef PassID, ChangedIRData &Output) override
Definition: StandardInstrumentations.cpp:1167
llvm::SmallString< 128 >
LoopInfo.h
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
ChangePrinter::PrintChangedColourDiffQuiet
@ PrintChangedColourDiffQuiet
llvm::PassInstrumentationCallbacks::registerBeforeAnalysisCallback
void registerBeforeAnalysisCallback(CallableT C)
Definition: PassInstrumentation.h:120
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::cl::opt< bool >
llvm::ChangeReporter
Definition: StandardInstrumentations.h:171
Verify
ppc ctr loops PowerPC CTR Loops Verify
Definition: PPCCTRLoops.cpp:77
llvm::cl::values
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:699
llvm::PassInstrumentationCallbacks::registerAnalysisInvalidatedCallback
void registerAnalysisInvalidatedCallback(CallableT C)
Definition: PassInstrumentation.h:130
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
PrintChangedBefore
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
isInteresting
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
Definition: IVUsers.cpp:60
llvm::shouldPrintAfterAll
bool shouldPrintAfterAll()
Definition: PrintPasses.cpp:63
llvm::ChangedIRComparer::analyzeIR
static void analyzeIR(Any IR, ChangedIRData &Data)
Definition: StandardInstrumentations.cpp:661
llvm::DenseMap
Definition: DenseMap.h:714
llvm::AnalysisKey
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: PassManager.h:72
llvm::OrderedChangedData::report
static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const IRData *, const IRData *)> HandlePair)
Definition: StandardInstrumentations.cpp:569
llvm::TextChangeReporter
Definition: StandardInstrumentations.h:233
llvm::ChangeReporter::isInteresting
bool isInteresting(Any IR, StringRef PassID)
Definition: StandardInstrumentations.cpp:396
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
llvm::PreservedCFGCheckerInstrumentation::CFG::BBGuards
Optional< DenseMap< intptr_t, BBGuard > > BBGuards
Definition: StandardInstrumentations.h:126
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1612
llvm::isFunctionInPrintList
bool isFunctionInPrintList(StringRef FunctionName)
Definition: PrintPasses.cpp:83
llvm::StringMap::begin
iterator begin()
Definition: StringMap.h:204
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ChangeReporter::handleIRAfterPass
void handleIRAfterPass(Any IR, StringRef PassID)
Definition: StandardInstrumentations.cpp:426
llvm::codeview::CompileSym2Flags::EC
@ EC
PreservedCFGCheckerAnalysis::run
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
Definition: StandardInstrumentations.cpp:1047
llvm::printBeforePasses
std::vector< std::string > printBeforePasses()
Definition: PrintPasses.cpp:73
llvm::PreservedAnalyses::allAnalysesInSetPreserved
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
Definition: PassManager.h:338
llvm::PreservedCFGCheckerInstrumentation::CFG::invalidate
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
Definition: StandardInstrumentations.cpp:1054
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
NDEBUG
#define NDEBUG
Definition: regutils.h:48
llvm::StringMapImpl::size
unsigned size() const
Definition: StringMap.h:93
llvm::PreservedCFGCheckerInstrumentation::CFG
Definition: StandardInstrumentations.h:125
llvm::AnalysisInfoMixin
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:391
llvm::LazyCallGraph::Node
A node in the call graph.
Definition: LazyCallGraph.h:318
llvm::ChangedIRComparer::compare
void compare(Any IR, StringRef Prefix, StringRef PassID, StringRef Name)
Definition: StandardInstrumentations.cpp:636
llvm::printAfterPasses
std::vector< std::string > printAfterPasses()
Definition: PrintPasses.cpp:77
llvm::ChangedIRComparer::After
const ChangedIRData & After
Definition: StandardInstrumentations.h:370
llvm::IRChangedPrinter::handleAfter
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
Definition: StandardInstrumentations.cpp:546
llvm::sys::fs::remove
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
llvm::sys::fs::createTemporaryFile
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
Definition: Path.cpp:858
llvm::PassInstrumentationCallbacks::registerAfterAnalysisCallback
void registerAfterAnalysisCallback(CallableT C)
Definition: PassInstrumentation.h:125
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:1554
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
ChangePrinter::NoChangePrinter
@ NoChangePrinter
llvm::TimePassesHandler::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: PassTimingInfo.cpp:273
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::CFGAnalyses
Represents analyses that only rely on functions' control flow.
Definition: PassManager.h:116
VerifyEach
bool VerifyEach
Definition: PassBuilderBindings.cpp:52
getParent
static const Function * getParent(const Value *V)
Definition: BasicAliasAnalysis.cpp:776
llvm::PseudoProbeVerifier::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: SampleProfileProbe.cpp:88
clEnumValN
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Definition: CommandLine.h:674
llvm::PreservedCFGCheckerInstrumentation::CFG::isPoisoned
bool isPoisoned() const
Definition: StandardInstrumentations.h:135
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::InLineChangePrinter::same
virtual bool same(const ChangedIRData &Before, const ChangedIRData &After) override
Definition: StandardInstrumentations.cpp:1183
llvm::ChangedBlockData::Body
std::string Body
Definition: StandardInstrumentations.h:302
CallGraphSCCPass.h
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:297
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:441
llvm::PassInstrumentationCallbacks::registerAfterPassInvalidatedCallback
void registerAfterPassInvalidatedCallback(CallableT C)
Definition: PassInstrumentation.h:115
llvm::PrintPassOptions::Verbose
bool Verbose
Print adaptors and pass managers.
Definition: StandardInstrumentations.h:84
CFG
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to CFG
Definition: README.txt:39
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::Any
Definition: Any.h:26
Verifier.h
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::StandardInstrumentations::StandardInstrumentations
StandardInstrumentations(bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
Definition: StandardInstrumentations.cpp:1216
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:788
Function.h
llvm::LoopBase::getHeader
BlockT * getHeader() const
Definition: LoopInfo.h:104
PassManager.h
llvm::OptBisector
ManagedStatic< OptBisect > OptBisector
Singleton instance of the OptBisect class, so multiple pass managers don't need to coordinate their u...
Definition: OptBisect.cpp:56
llvm::PassInstrumentationCallbacks::registerBeforeSkippedPassCallback
void registerBeforeSkippedPassCallback(CallableT C)
Definition: PassInstrumentation.h:101
llvm::cl::value_desc
Definition: CommandLine.h:424
llvm::InLineChangePrinter::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:1208
llvm::OptBisectInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:849
llvm::AnalysisManager::registerPass
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
Definition: PassManager.h:831
PrintChanged
static cl::opt< ChangePrinter > PrintChanged("print-changed", cl::desc("Print changed IRs"), cl::Hidden, cl::ValueOptional, cl::init(ChangePrinter::NoChangePrinter), cl::values(clEnumValN(ChangePrinter::PrintChangedQuiet, "quiet", "Run in quiet mode"), clEnumValN(ChangePrinter::PrintChangedDiffVerbose, "diff", "Display patch-like changes"), clEnumValN(ChangePrinter::PrintChangedDiffQuiet, "diff-quiet", "Display patch-like changes in quiet mode"), clEnumValN(ChangePrinter::PrintChangedColourDiffVerbose, "cdiff", "Display patch-like changes with color"), clEnumValN(ChangePrinter::PrintChangedColourDiffQuiet, "cdiff-quiet", "Display patch-like changes in quiet mode with color"), clEnumValN(ChangePrinter::PrintChangedVerbose, "", "")))
llvm::ChangeReporter::handleInvalidatedPass
void handleInvalidatedPass(StringRef PassID)
Definition: StandardInstrumentations.cpp:455
Any.h
llvm::PassInstrumentationCallbacks::registerAfterPassCallback
void registerAfterPassCallback(CallableT C)
Definition: PassInstrumentation.h:110
llvm::PreservedCFGCheckerInstrumentation::CFG::CFG
CFG(const Function *F, bool TrackBBLifetime)
Definition: StandardInstrumentations.cpp:927
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition: raw_ostream.cpp:497
llvm::PassInstrumentationCallbacks
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
Definition: PassInstrumentation.h:66
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:32
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::ChangedIRComparer
Definition: StandardInstrumentations.h:343
ChangePrinter::PrintChangedDiffVerbose
@ PrintChangedDiffVerbose
llvm::forcePrintModuleIR
bool forcePrintModuleIR()
Definition: PrintPasses.cpp:81
llvm::PreservedAnalyses::getChecker
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition: PassManager.h:313
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::ChangeReporter::isInterestingPass
bool isInterestingPass(StringRef PassID)
Definition: StandardInstrumentations.cpp:384
llvm::IRChangedPrinter::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:532
llvm::LoopBase::print
void print(raw_ostream &OS, bool Verbose=false, bool PrintNested=true, unsigned Depth=0) const
Print loop with all the BBs inside it.
Definition: LoopInfoImpl.h:384
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::X86AS::SS
@ SS
Definition: X86.h:189
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
llvm::cl::desc
Definition: CommandLine.h:414
raw_ostream.h
ChangePrinter::PrintChangedVerbose
@ PrintChangedVerbose
llvm::raw_string_ostream::str
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:641
llvm::ChangedIRComparer::handleFunctionCompare
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, bool InModule, const ChangedFuncData &Before, const ChangedFuncData &After)
Definition: StandardInstrumentations.cpp:1188
Debug.h
printBBName
static void printBBName(raw_ostream &out, const BasicBlock *BB)
Definition: StandardInstrumentations.cpp:942
PassName
static const char PassName[]
Definition: X86LowerAMXIntrinsics.cpp:669
llvm::ChangedBlockData
Definition: StandardInstrumentations.h:284
llvm::PreservedCFGCheckerInstrumentation::CFG::Graph
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
Definition: StandardInstrumentations.h:127
ChangePrinter::PrintChangedColourDiffVerbose
@ PrintChangedColourDiffVerbose
llvm::verifyModule
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Definition: Verifier.cpp:5738
llvm::PrintPassInstrumentation::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: StandardInstrumentations.cpp:866
StandardInstrumentations.h
llvm::SmallVectorImpl::emplace_back
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:908
llvm::PreservedCFGCheckerInstrumentation::VerifyPreservedCFG
static cl::opt< bool > VerifyPreservedCFG
Definition: StandardInstrumentations.h:151
llvm::ChangedIRComparer::Before
const ChangedIRData & Before
Definition: StandardInstrumentations.h:369
llvm::cl::list
Definition: CommandLine.h:1630