LLVM  12.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"
23 #include "llvm/IR/Module.h"
25 #include "llvm/IR/PrintPasses.h"
26 #include "llvm/IR/Verifier.h"
28 #include "llvm/Support/Debug.h"
31 #include <unordered_set>
32 #include <vector>
33 
34 using namespace llvm;
35 
37  "verify-cfg-preserved", cl::Hidden,
38 #ifdef NDEBUG
39  cl::init(false));
40 #else
41  cl::init(false));
42 #endif
43 
44 // FIXME: Change `-debug-pass-manager` from boolean to enum type. Similar to
45 // `-debug-pass` in legacy PM.
46 static cl::opt<bool>
47  DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false),
48  cl::desc("Print all pass management debugging information. "
49  "`-debug-pass-manager` must also be specified"));
50 
51 // An option that prints out the IR after passes, similar to
52 // -print-after-all except that it only prints the IR after passes that
53 // change the IR. Those passes that do not make changes to the IR are
54 // reported as not making any changes. In addition, the initial IR is
55 // also reported. Other hidden options affect the output from this
56 // option. -filter-passes will limit the output to the named passes
57 // that actually change the IR and other passes are reported as filtered out.
58 // The specified passes will either be reported as making no changes (with
59 // no IR reported) or the changed IR will be reported. Also, the
60 // -filter-print-funcs and -print-module-scope options will do similar
61 // filtering based on function name, reporting changed IRs as functions(or
62 // modules if -print-module-scope is specified) for a particular function
63 // or indicating that the IR has been filtered out. The extra options
64 // can be combined, allowing only changed IRs for certain passes on certain
65 // functions to be reported in different formats, with the rest being
66 // reported as filtered out. The -print-before-changed option will print
67 // the IR as it was before each pass that changed it. The optional
68 // value of quiet will only report when the IR changes, suppressing
69 // all other messages, including the initial IR.
72  "print-changed", cl::desc("Print changed IRs"), cl::Hidden,
74  cl::values(clEnumValN(PrintChangedQuiet, "quiet", "Run in quiet mode"),
75  // Sentinel value for unspecified option.
77 
78 // An option that supports the -print-changed option. See
79 // the description for -print-changed for an explanation of the use
80 // of this option. Note that this option has no effect without -print-changed.
82  PrintPassesList("filter-passes", cl::value_desc("pass names"),
83  cl::desc("Only consider IR changes for passes whose names "
84  "match for the print-changed option"),
86 // An option that supports the -print-changed option. See
87 // the description for -print-changed for an explanation of the use
88 // of this option. Note that this option has no effect without -print-changed.
89 static cl::opt<bool>
90  PrintChangedBefore("print-before-changed",
91  cl::desc("Print before passes that change them"),
92  cl::init(false), cl::Hidden);
93 
94 namespace {
95 
96 /// Extracting Module out of \p IR unit. Also fills a textual description
97 /// of \p IR for use in header when printing.
99 unwrapModule(Any IR, bool Force = false) {
100  if (any_isa<const Module *>(IR))
101  return std::make_pair(any_cast<const Module *>(IR), std::string());
102 
103  if (any_isa<const Function *>(IR)) {
104  const Function *F = any_cast<const Function *>(IR);
105  if (!Force && !isFunctionInPrintList(F->getName()))
106  return None;
107 
108  const Module *M = F->getParent();
109  return std::make_pair(M, formatv(" (function: {0})", F->getName()).str());
110  }
111 
112  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
113  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
114  for (const LazyCallGraph::Node &N : *C) {
115  const Function &F = N.getFunction();
116  if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) {
117  const Module *M = F.getParent();
118  return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str());
119  }
120  }
121  assert(!Force && "Expected to have made a pair when forced.");
122  return None;
123  }
124 
125  if (any_isa<const Loop *>(IR)) {
126  const Loop *L = any_cast<const Loop *>(IR);
127  const Function *F = L->getHeader()->getParent();
128  if (!Force && !isFunctionInPrintList(F->getName()))
129  return None;
130  const Module *M = F->getParent();
131  std::string LoopName;
132  raw_string_ostream ss(LoopName);
133  L->getHeader()->printAsOperand(ss, false);
134  return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str());
135  }
136 
137  llvm_unreachable("Unknown IR unit");
138 }
139 
140 void printIR(raw_ostream &OS, const Function *F, StringRef Banner,
141  StringRef Extra = StringRef(), bool Brief = false) {
142  if (Brief) {
143  OS << F->getName() << '\n';
144  return;
145  }
146 
147  if (!isFunctionInPrintList(F->getName()))
148  return;
149  OS << Banner << Extra << "\n" << static_cast<const Value &>(*F);
150 }
151 
152 void printIR(raw_ostream &OS, const Module *M, StringRef Banner,
153  StringRef Extra = StringRef(), bool Brief = false,
154  bool ShouldPreserveUseListOrder = false) {
155  if (Brief) {
156  OS << M->getName() << '\n';
157  return;
158  }
159 
161  OS << Banner << Extra << "\n";
162  M->print(OS, nullptr, ShouldPreserveUseListOrder);
163  } else {
164  for (const auto &F : M->functions()) {
165  printIR(OS, &F, Banner, Extra);
166  }
167  }
168 }
169 
170 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C, StringRef Banner,
171  StringRef Extra = StringRef(), bool Brief = false) {
172  if (Brief) {
173  OS << *C << '\n';
174  return;
175  }
176 
177  bool BannerPrinted = false;
178  for (const LazyCallGraph::Node &N : *C) {
179  const Function &F = N.getFunction();
180  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
181  if (!BannerPrinted) {
182  OS << Banner << Extra << "\n";
183  BannerPrinted = true;
184  }
185  F.print(OS);
186  }
187  }
188 }
189 
190 void printIR(raw_ostream &OS, const Loop *L, StringRef Banner,
191  bool Brief = false) {
192  if (Brief) {
193  OS << *L;
194  return;
195  }
196 
197  const Function *F = L->getHeader()->getParent();
198  if (!isFunctionInPrintList(F->getName()))
199  return;
200  printLoop(const_cast<Loop &>(*L), OS, std::string(Banner));
201 }
202 
203 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
204 /// llvm::Any and does actual print job.
205 void unwrapAndPrint(raw_ostream &OS, Any IR, StringRef Banner,
206  bool ForceModule = false, bool Brief = false,
207  bool ShouldPreserveUseListOrder = false) {
208  if (ForceModule) {
209  if (auto UnwrappedModule = unwrapModule(IR))
210  printIR(OS, UnwrappedModule->first, Banner, UnwrappedModule->second,
211  Brief, ShouldPreserveUseListOrder);
212  return;
213  }
214 
215  if (any_isa<const Module *>(IR)) {
216  const Module *M = any_cast<const Module *>(IR);
217  assert(M && "module should be valid for printing");
218  printIR(OS, M, Banner, "", Brief, ShouldPreserveUseListOrder);
219  return;
220  }
221 
222  if (any_isa<const Function *>(IR)) {
223  const Function *F = any_cast<const Function *>(IR);
224  assert(F && "function should be valid for printing");
225  printIR(OS, F, Banner, "", Brief);
226  return;
227  }
228 
229  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
230  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
231  assert(C && "scc should be valid for printing");
232  std::string Extra = std::string(formatv(" (scc: {0})", C->getName()));
233  printIR(OS, C, Banner, Extra, Brief);
234  return;
235  }
236 
237  if (any_isa<const Loop *>(IR)) {
238  const Loop *L = any_cast<const Loop *>(IR);
239  assert(L && "Loop should be valid for printing");
240  printIR(OS, L, Banner, Brief);
241  return;
242  }
243  llvm_unreachable("Unknown wrapped IR type");
244 }
245 
246 // Return true when this is a pass for which changes should be ignored
247 bool isIgnored(StringRef PassID) {
248  return isSpecialPass(PassID,
249  {"PassManager", "PassAdaptor", "AnalysisManagerProxy"});
250 }
251 
252 } // namespace
253 
254 template <typename IRUnitT>
256  assert(BeforeStack.empty() && "Problem with Change Printer stack.");
257 }
258 
259 template <typename IRUnitT>
261  return isFunctionInPrintList(F.getName());
262 }
263 
264 template <typename IRUnitT>
266  if (isIgnored(PassID))
267  return false;
268 
269  static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
270  PrintPassesList.end());
271  return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
272 }
273 
274 // Return true when this is a pass on IR for which printing
275 // of changes is desired.
276 template <typename IRUnitT>
278  if (!isInterestingPass(PassID))
279  return false;
280  if (any_isa<const Function *>(IR))
281  return isInterestingFunction(*any_cast<const Function *>(IR));
282  return true;
283 }
284 
285 template <typename IRUnitT>
287  // Always need to place something on the stack because invalidated passes
288  // are not given the IR so it cannot be determined whether the pass was for
289  // something that was filtered out.
290  BeforeStack.emplace_back();
291 
292  if (!isInteresting(IR, PassID))
293  return;
294  // Is this the initial IR?
295  if (InitialIR) {
296  InitialIR = false;
297  if (VerboseMode)
298  handleInitialIR(IR);
299  }
300 
301  // Save the IR representation on the stack.
302  IRUnitT &Data = BeforeStack.back();
303  generateIRRepresentation(IR, PassID, Data);
304 }
305 
306 template <typename IRUnitT>
308  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
309  std::string Name;
310 
311  // unwrapModule has inconsistent handling of names for function IRs.
312  if (any_isa<const Function *>(IR)) {
313  const Function *F = any_cast<const Function *>(IR);
314  Name = formatv(" (function: {0})", F->getName()).str();
315  } else {
316  if (auto UM = unwrapModule(IR))
317  Name = UM->second;
318  }
319  if (Name == "")
320  Name = " (module)";
321 
322  if (isIgnored(PassID)) {
323  if (VerboseMode)
324  handleIgnored(PassID, Name);
325  } else if (!isInteresting(IR, PassID)) {
326  if (VerboseMode)
327  handleFiltered(PassID, Name);
328  } else {
329  // Get the before rep from the stack
330  IRUnitT &Before = BeforeStack.back();
331  // Create the after rep
332  IRUnitT After;
333  generateIRRepresentation(IR, PassID, After);
334 
335  // Was there a change in IR?
336  if (same(Before, After)) {
337  if (VerboseMode)
338  omitAfter(PassID, Name);
339  } else
340  handleAfter(PassID, Name, Before, After, IR);
341  }
342  BeforeStack.pop_back();
343 }
344 
345 template <typename IRUnitT>
347  assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
348 
349  // Always flag it as invalidated as we cannot determine when
350  // a pass for a filtered function is invalidated since we do not
351  // get the IR in the call. Also, the output is just alternate
352  // forms of the banner anyway.
353  if (VerboseMode)
354  handleInvalidated(PassID);
355  BeforeStack.pop_back();
356 }
357 
358 template <typename IRUnitT>
362  [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); });
363 
365  [this](StringRef P, Any IR, const PreservedAnalyses &) {
366  handleIRAfterPass(IR, P);
367  });
369  [this](StringRef P, const PreservedAnalyses &) {
370  handleInvalidatedPass(P);
371  });
372 }
373 
374 template <typename IRUnitT>
376  : ChangeReporter<IRUnitT>(Verbose), Out(dbgs()) {}
377 
378 template <typename IRUnitT>
380  // Always print the module.
381  // Unwrap and print directly to avoid filtering problems in general routines.
382  auto UnwrappedModule = unwrapModule(IR, /*Force=*/true);
383  assert(UnwrappedModule && "Expected module to be unwrapped when forced.");
384  Out << "*** IR Dump At Start: ***" << UnwrappedModule->second << "\n";
385  UnwrappedModule->first->print(Out, nullptr,
386  /*ShouldPreserveUseListOrder=*/true);
387 }
388 
389 template <typename IRUnitT>
391  std::string &Name) {
392  Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n",
393  PassID, Name);
394 }
395 
396 template <typename IRUnitT>
398  Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
399 }
400 
401 template <typename IRUnitT>
403  std::string &Name) {
404  SmallString<20> Banner =
405  formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name);
406  Out << Banner;
407 }
408 
409 template <typename IRUnitT>
411  std::string &Name) {
412  Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name);
413 }
414 
415 IRChangedPrinter::~IRChangedPrinter() {}
416 
420 }
421 
423  std::string &Output) {
424  raw_string_ostream OS(Output);
425  // use the after banner for all cases so it will match
426  SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
427  unwrapAndPrint(OS, IR, Banner, forcePrintModuleIR(),
428  /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true);
429 
430  OS.str();
431 }
432 
433 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
434  const std::string &Before,
435  const std::string &After, Any) {
436  assert(After.find("*** IR Dump") == 0 && "Unexpected banner format.");
437  StringRef AfterRef = After;
438  StringRef Banner =
439  AfterRef.take_until([](char C) -> bool { return C == '\n'; });
440 
441  // Report the IR before the changes when requested.
442  if (PrintChangedBefore) {
443  Out << "*** IR Dump Before" << Banner.substr(17);
444  // LazyCallGraph::SCC already has "(scc:..." in banner so only add
445  // in the name if it isn't already there.
446  if (Name.substr(0, 6) != " (scc:" && !forcePrintModuleIR())
447  Out << Name;
448 
449  StringRef BeforeRef = Before;
450  Out << BeforeRef.substr(Banner.size());
451  }
452 
453  Out << Banner;
454 
455  // LazyCallGraph::SCC already has "(scc:..." in banner so only add
456  // in the name if it isn't already there.
457  if (Name.substr(0, 6) != " (scc:" && !forcePrintModuleIR())
458  Out << Name;
459 
460  Out << After.substr(Banner.size());
461 }
462 
463 bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) {
464  return S1 == S2;
465 }
466 
468  assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
469 }
470 
471 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
472  assert(StoreModuleDesc);
473  const Module *M = nullptr;
474  std::string Extra;
475  if (auto UnwrappedModule = unwrapModule(IR))
476  std::tie(M, Extra) = UnwrappedModule.getValue();
477  ModuleDescStack.emplace_back(M, Extra, PassID);
478 }
479 
480 PrintIRInstrumentation::PrintModuleDesc
481 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
482  assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
483  PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
484  assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
485  return ModuleDesc;
486 }
487 
488 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
489  if (isIgnored(PassID))
490  return;
491 
492  // Saving Module for AfterPassInvalidated operations.
493  // Note: here we rely on a fact that we do not change modules while
494  // traversing the pipeline, so the latest captured module is good
495  // for all print operations that has not happen yet.
496  if (StoreModuleDesc && shouldPrintAfterPass(PassID))
497  pushModuleDesc(PassID, IR);
498 
499  if (!shouldPrintBeforePass(PassID))
500  return;
501 
502  SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
503  unwrapAndPrint(dbgs(), IR, Banner, forcePrintModuleIR());
504 }
505 
506 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
507  if (isIgnored(PassID))
508  return;
509 
510  if (!shouldPrintAfterPass(PassID))
511  return;
512 
513  if (StoreModuleDesc)
514  popModuleDesc(PassID);
515 
516  SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
517  unwrapAndPrint(dbgs(), IR, Banner, forcePrintModuleIR());
518 }
519 
520 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
522  if (!StoreModuleDesc || !shouldPrintAfterPass(PassName))
523  return;
524 
525  if (isIgnored(PassID))
526  return;
527 
528  const Module *M;
529  std::string Extra;
530  StringRef StoredPassID;
531  std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
532  // Additional filtering (e.g. -filter-print-func) can lead to module
533  // printing being skipped.
534  if (!M)
535  return;
536 
537  SmallString<20> Banner =
538  formatv("*** IR Dump After {0} *** invalidated: ", PassID);
539  printIR(dbgs(), M, Banner, Extra);
540 }
541 
542 bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
543  if (shouldPrintBeforeAll())
544  return true;
545 
547  for (const auto &P : printBeforePasses()) {
548  if (PassName == P)
549  return true;
550  }
551  return false;
552 }
553 
554 bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {
555  if (shouldPrintAfterAll())
556  return true;
557 
559  for (const auto &P : printAfterPasses()) {
560  if (PassName == P)
561  return true;
562  }
563  return false;
564 }
565 
568  this->PIC = &PIC;
569 
570  // BeforePass callback is not just for printing, it also saves a Module
571  // for later use in AfterPassInvalidated.
572  StoreModuleDesc = forcePrintModuleIR() && shouldPrintAfterSomePass();
573  if (shouldPrintBeforeSomePass() || StoreModuleDesc)
575  [this](StringRef P, Any IR) { this->printBeforePass(P, IR); });
576 
577  if (shouldPrintAfterSomePass()) {
579  [this](StringRef P, Any IR, const PreservedAnalyses &) {
580  this->printAfterPass(P, IR);
581  });
583  [this](StringRef P, const PreservedAnalyses &) {
584  this->printAfterPassInvalidated(P);
585  });
586  }
587 }
588 
592  [this](StringRef P, Any IR) { return this->shouldRun(P, IR); });
593 }
594 
595 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {
596  const Function *F = nullptr;
597  if (any_isa<const Function *>(IR)) {
598  F = any_cast<const Function *>(IR);
599  } else if (any_isa<const Loop *>(IR)) {
600  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
601  }
602  bool ShouldRun = !(F && F->hasOptNone());
603  if (!ShouldRun && DebugLogging) {
604  errs() << "Skipping pass " << PassID << " on " << F->getName()
605  << " due to optnone attribute\n";
606  }
607  return ShouldRun;
608 }
609 
610 static std::string getBisectDescription(Any IR) {
611  if (any_isa<const Module *>(IR)) {
612  const Module *M = any_cast<const Module *>(IR);
613  assert(M && "module should be valid for printing");
614  return "module (" + M->getName().str() + ")";
615  }
616 
617  if (any_isa<const Function *>(IR)) {
618  const Function *F = any_cast<const Function *>(IR);
619  assert(F && "function should be valid for printing");
620  return "function (" + F->getName().str() + ")";
621  }
622 
623  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
624  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
625  assert(C && "scc should be valid for printing");
626  return "SCC " + C->getName();
627  }
628 
629  if (any_isa<const Loop *>(IR)) {
630  return "loop";
631  }
632 
633  llvm_unreachable("Unknown wrapped IR type");
634 }
635 
638  if (!OptBisector->isEnabled())
639  return;
641  return isIgnored(PassID) ||
642  OptBisector->checkPass(PassID, getBisectDescription(IR));
643  });
644 }
645 
648  if (!DebugLogging)
649  return;
650 
651  std::vector<StringRef> SpecialPasses = {"PassManager"};
652  if (!DebugPMVerbose)
653  SpecialPasses.emplace_back("PassAdaptor");
654 
656  [SpecialPasses](StringRef PassID, Any IR) {
657  assert(!isSpecialPass(PassID, SpecialPasses) &&
658  "Unexpectedly skipping special pass");
659 
660  dbgs() << "Skipping pass: " << PassID << " on ";
661  unwrapAndPrint(dbgs(), IR, "", false, true);
662  });
663 
665  [SpecialPasses](StringRef PassID, Any IR) {
666  if (isSpecialPass(PassID, SpecialPasses))
667  return;
668 
669  dbgs() << "Running pass: " << PassID << " on ";
670  unwrapAndPrint(dbgs(), IR, "", false, true);
671  });
672 
674  dbgs() << "Running analysis: " << PassID << " on ";
675  unwrapAndPrint(dbgs(), IR, "", false, true);
676  });
677 }
678 
680  bool TrackBBLifetime) {
681  if (TrackBBLifetime)
682  BBGuards = DenseMap<intptr_t, BBGuard>(F->size());
683  for (const auto &BB : *F) {
684  if (BBGuards)
685  BBGuards->try_emplace(intptr_t(&BB), &BB);
686  for (auto *Succ : successors(&BB)) {
687  Graph[&BB][Succ]++;
688  if (BBGuards)
689  BBGuards->try_emplace(intptr_t(Succ), Succ);
690  }
691  }
692 }
693 
694 static void printBBName(raw_ostream &out, const BasicBlock *BB) {
695  if (BB->hasName()) {
696  out << BB->getName() << "<" << BB << ">";
697  return;
698  }
699 
700  if (!BB->getParent()) {
701  out << "unnamed_removed<" << BB << ">";
702  return;
703  }
704 
705  if (BB == &BB->getParent()->getEntryBlock()) {
706  out << "entry"
707  << "<" << BB << ">";
708  return;
709  }
710 
711  unsigned FuncOrderBlockNum = 0;
712  for (auto &FuncBB : *BB->getParent()) {
713  if (&FuncBB == BB)
714  break;
715  FuncOrderBlockNum++;
716  }
717  out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";
718 }
719 
720 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
721  const CFG &Before,
722  const CFG &After) {
723  assert(!After.isPoisoned());
724 
725  // Print function name.
726  const CFG *FuncGraph = nullptr;
727  if (!After.Graph.empty())
728  FuncGraph = &After;
729  else if (!Before.isPoisoned() && !Before.Graph.empty())
730  FuncGraph = &Before;
731 
732  if (FuncGraph)
733  out << "In function @"
734  << FuncGraph->Graph.begin()->first->getParent()->getName() << "\n";
735 
736  if (Before.isPoisoned()) {
737  out << "Some blocks were deleted\n";
738  return;
739  }
740 
741  // Find and print graph differences.
742  if (Before.Graph.size() != After.Graph.size())
743  out << "Different number of non-leaf basic blocks: before="
744  << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";
745 
746  for (auto &BB : Before.Graph) {
747  auto BA = After.Graph.find(BB.first);
748  if (BA == After.Graph.end()) {
749  out << "Non-leaf block ";
750  printBBName(out, BB.first);
751  out << " is removed (" << BB.second.size() << " successors)\n";
752  }
753  }
754 
755  for (auto &BA : After.Graph) {
756  auto BB = Before.Graph.find(BA.first);
757  if (BB == Before.Graph.end()) {
758  out << "Non-leaf block ";
759  printBBName(out, BA.first);
760  out << " is added (" << BA.second.size() << " successors)\n";
761  continue;
762  }
763 
764  if (BB->second == BA.second)
765  continue;
766 
767  out << "Different successors of block ";
768  printBBName(out, BA.first);
769  out << " (unordered):\n";
770  out << "- before (" << BB->second.size() << "): ";
771  for (auto &SuccB : BB->second) {
772  printBBName(out, SuccB.first);
773  if (SuccB.second != 1)
774  out << "(" << SuccB.second << "), ";
775  else
776  out << ", ";
777  }
778  out << "\n";
779  out << "- after (" << BA.second.size() << "): ";
780  for (auto &SuccA : BA.second) {
781  printBBName(out, SuccA.first);
782  if (SuccA.second != 1)
783  out << "(" << SuccA.second << "), ";
784  else
785  out << ", ";
786  }
787  out << "\n";
788  }
789 }
790 
793  if (!VerifyPreservedCFG)
794  return;
795 
797  if (any_isa<const Function *>(IR))
798  GraphStackBefore.emplace_back(P, CFG(any_cast<const Function *>(IR)));
799  else
800  GraphStackBefore.emplace_back(P, None);
801  });
802 
804  [this](StringRef P, const PreservedAnalyses &PassPA) {
805  auto Before = GraphStackBefore.pop_back_val();
806  assert(Before.first == P &&
807  "Before and After callbacks must correspond");
808  (void)Before;
809  });
810 
812  const PreservedAnalyses &PassPA) {
813  auto Before = GraphStackBefore.pop_back_val();
814  assert(Before.first == P && "Before and After callbacks must correspond");
815  auto &GraphBefore = Before.second;
816 
817  if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>())
818  return;
819 
820  if (any_isa<const Function *>(IR)) {
821  assert(GraphBefore && "Must be built in BeforePassCallback");
822  CFG GraphAfter(any_cast<const Function *>(IR), false /* NeedsGuard */);
823  if (GraphAfter == *GraphBefore)
824  return;
825 
826  dbgs() << "Error: " << P
827  << " reported it preserved CFG, but changes detected:\n";
828  CFG::printDiff(dbgs(), *GraphBefore, GraphAfter);
829  report_fatal_error(Twine("Preserved CFG changed by ", P));
830  }
831  });
832 }
833 
837  [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
838  if (isIgnored(P) || P == "VerifierPass")
839  return;
840  if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) {
841  const Function *F;
842  if (any_isa<const Loop *>(IR))
843  F = any_cast<const Loop *>(IR)->getHeader()->getParent();
844  else
845  F = any_cast<const Function *>(IR);
846  if (DebugLogging)
847  dbgs() << "Verifying function " << F->getName() << "\n";
848 
849  if (verifyFunction(*F))
850  report_fatal_error("Broken function found, compilation aborted!");
851  } else if (any_isa<const Module *>(IR) ||
852  any_isa<const LazyCallGraph::SCC *>(IR)) {
853  const Module *M;
854  if (any_isa<const LazyCallGraph::SCC *>(IR))
855  M = any_cast<const LazyCallGraph::SCC *>(IR)
856  ->begin()
857  ->getFunction()
858  .getParent();
859  else
860  M = any_cast<const Module *>(IR);
861  if (DebugLogging)
862  dbgs() << "Verifying module " << M->getName() << "\n";
863 
864  if (verifyModule(*M))
865  report_fatal_error("Broken module found, compilation aborted!");
866  }
867  });
868 }
869 
871  bool VerifyEach)
872  : PrintPass(DebugLogging), OptNone(DebugLogging),
873  PrintChangedIR(PrintChanged != PrintChangedQuiet), Verify(DebugLogging),
874  VerifyEach(VerifyEach) {}
875 
878  PrintIR.registerCallbacks(PIC);
879  PrintPass.registerCallbacks(PIC);
880  TimePasses.registerCallbacks(PIC);
881  OptNone.registerCallbacks(PIC);
882  OptBisect.registerCallbacks(PIC);
883  PreservedCFGChecker.registerCallbacks(PIC);
884  PrintChangedIR.registerCallbacks(PIC);
885  if (VerifyEach)
886  Verify.registerCallbacks(PIC);
887 }
888 
889 namespace llvm {
890 
891 template class ChangeReporter<std::string>;
892 template class TextChangeReporter<std::string>;
893 
894 } // namespace llvm
const NoneType None
Definition: None.h:23
uint64_t CallInst * C
bool shouldPrintBeforeAll()
Definition: PrintPasses.cpp:61
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:856
Definition: Any.h:26
bool forcePrintModuleIR()
Definition: PrintPasses.cpp:81
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:248
void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static void printBBName(raw_ostream &out, const BasicBlock *BB)
LLVM_NODISCARD StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
Definition: StringRef.h:647
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:75
static std::string getBisectDescription(Any IR)
Implements a lazy call graph analysis and related passes for the new pass manager.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
bool isInterestingFunction(const Function &F)
F(f)
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleIRAfterPass(Any IR, StringRef PassID)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void saveIRBeforePass(Any IR, StringRef PassID)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
Definition: PrintPasses.cpp:48
std::vector< std::string > printBeforePasses()
Definition: PrintPasses.cpp:73
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:612
BlockT * getHeader() const
Definition: LoopInfo.h:104
ppc ctr loops PowerPC CTR Loops Verify
Definition: PPCCTRLoops.cpp:76
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:25
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
bool isInteresting(Any IR, StringRef PassID)
const BasicBlock & getEntryBlock() const
Definition: Function.h:731
This class implements a mechanism to disable passes and individual optimizations at compile time base...
Definition: OptBisect.h:44
#define P(N)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:427
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
bool hasName() const
Definition: Value.h:252
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:683
void registerShouldRunOptionalPassCallback(CallableT C)
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
StandardInstrumentations(bool DebugLogging, bool VerifyEach=false)
void handleInvalidatedPass(StringRef PassID)
A node in the call graph.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
ManagedStatic< OptBisect > OptBisector
Singleton instance of the OptBisect class, so multiple pass managers don't need to coordinate their u...
Definition: OptBisect.cpp:58
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
Definition: AsmWriter.cpp:4654
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:625
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
Definition: DenseMap.h:222
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
bool shouldPrintAfterSomePass()
Definition: PrintPasses.cpp:52
static const char PassName[]
Module.h This file contains the declarations for the Module class.
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:595
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
bool isFunctionInPrintList(StringRef FunctionName)
Definition: PrintPasses.cpp:83
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
#define NDEBUG
Definition: regutils.h:48
Represents analyses that only rely on functions' control flow.
Definition: PassManager.h:116
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
bool same(const std::string &Before, const std::string &After) override
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Definition: Verifier.cpp:5531
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Definition: CommandLine.h:658
bool shouldPrintAfterAll()
Definition: PrintPasses.cpp:63
std::vector< std::string > printAfterPasses()
Definition: PrintPasses.cpp:77
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
void registerAfterPassInvalidatedCallback(CallableT C)
Flatten the CFG
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:529
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:295
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
#define N
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
Definition: Verifier.cpp:5520
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
static cl::opt< bool > DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false), cl::desc("Print all pass management debugging information. " "`-debug-pass-manager` must also be specified"))
bool isInterestingPass(StringRef PassID)
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:607
An SCC of the call graph.
succ_range successors(Instruction *I)
Definition: CFG.h:260
void registerCallbacks(PassInstrumentationCallbacks &PIC)
static const Function * getParent(const Value *V)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
void registerCallbacks(PassInstrumentationCallbacks &PIC)
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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:959
Statically lint checks LLVM IR
Definition: Lint.cpp:742
void registerBeforeSkippedPassCallback(CallableT C)
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
Definition: PassManager.h:338
static cl::opt< ChangePrinter > PrintChanged("print-changed", cl::desc("Print changed IRs"), cl::Hidden, cl::ValueOptional, cl::init(NoChangePrinter), cl::values(clEnumValN(PrintChangedQuiet, "quiet", "Run in quiet mode"), clEnumValN(PrintChangedVerbose, "", "")))