LLVM  10.0.0svn
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/Optional.h"
19 #include "llvm/Analysis/LoopInfo.h"
20 #include "llvm/IR/Function.h"
22 #include "llvm/IR/Module.h"
24 #include "llvm/Support/Debug.h"
27 
28 using namespace llvm;
29 
30 namespace {
31 
32 /// Extracting Module out of \p IR unit. Also fills a textual description
33 /// of \p IR for use in header when printing.
35  if (any_isa<const Module *>(IR))
36  return std::make_pair(any_cast<const Module *>(IR), std::string());
37 
38  if (any_isa<const Function *>(IR)) {
39  const Function *F = any_cast<const Function *>(IR);
41  return None;
42  const Module *M = F->getParent();
43  return std::make_pair(M, formatv(" (function: {0})", F->getName()).str());
44  }
45 
46  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
48  for (const LazyCallGraph::Node &N : *C) {
49  const Function &F = N.getFunction();
50  if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
51  const Module *M = F.getParent();
52  return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str());
53  }
54  }
55  return None;
56  }
57 
58  if (any_isa<const Loop *>(IR)) {
59  const Loop *L = any_cast<const Loop *>(IR);
60  const Function *F = L->getHeader()->getParent();
61  if (!isFunctionInPrintList(F->getName()))
62  return None;
63  const Module *M = F->getParent();
64  std::string LoopName;
65  raw_string_ostream ss(LoopName);
66  L->getHeader()->printAsOperand(ss, false);
67  return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str());
68  }
69 
70  llvm_unreachable("Unknown IR unit");
71 }
72 
73 void printIR(const Module *M, StringRef Banner, StringRef Extra = StringRef()) {
74  dbgs() << Banner << Extra << "\n";
75  M->print(dbgs(), nullptr, false);
76 }
77 void printIR(const Function *F, StringRef Banner,
78  StringRef Extra = StringRef()) {
80  return;
81  dbgs() << Banner << Extra << "\n" << static_cast<const Value &>(*F);
82 }
83 void printIR(const LazyCallGraph::SCC *C, StringRef Banner,
84  StringRef Extra = StringRef()) {
85  bool BannerPrinted = false;
86  for (const LazyCallGraph::Node &N : *C) {
87  const Function &F = N.getFunction();
89  if (!BannerPrinted) {
90  dbgs() << Banner << Extra << "\n";
91  BannerPrinted = true;
92  }
93  F.print(dbgs());
94  }
95  }
96 }
97 void printIR(const Loop *L, StringRef Banner) {
98  const Function *F = L->getHeader()->getParent();
100  return;
101  llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner);
102 }
103 
104 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
105 /// llvm::Any and does actual print job.
106 void unwrapAndPrint(Any IR, StringRef Banner, bool ForceModule = false) {
107  if (ForceModule) {
108  if (auto UnwrappedModule = unwrapModule(IR))
109  printIR(UnwrappedModule->first, Banner, UnwrappedModule->second);
110  return;
111  }
112 
113  if (any_isa<const Module *>(IR)) {
114  const Module *M = any_cast<const Module *>(IR);
115  assert(M && "module should be valid for printing");
116  printIR(M, Banner);
117  return;
118  }
119 
120  if (any_isa<const Function *>(IR)) {
121  const Function *F = any_cast<const Function *>(IR);
122  assert(F && "function should be valid for printing");
123  printIR(F, Banner);
124  return;
125  }
126 
127  if (any_isa<const LazyCallGraph::SCC *>(IR)) {
128  const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
129  assert(C && "scc should be valid for printing");
130  std::string Extra = formatv(" (scc: {0})", C->getName());
131  printIR(C, Banner, Extra);
132  return;
133  }
134 
135  if (any_isa<const Loop *>(IR)) {
136  const Loop *L = any_cast<const Loop *>(IR);
137  assert(L && "Loop should be valid for printing");
138  printIR(L, Banner);
139  return;
140  }
141  llvm_unreachable("Unknown wrapped IR type");
142 }
143 
144 } // namespace
145 
147  assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
148 }
149 
150 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
151  assert(StoreModuleDesc);
152  const Module *M = nullptr;
153  std::string Extra;
154  if (auto UnwrappedModule = unwrapModule(IR))
155  std::tie(M, Extra) = UnwrappedModule.getValue();
156  ModuleDescStack.emplace_back(M, Extra, PassID);
157 }
158 
159 PrintIRInstrumentation::PrintModuleDesc
160 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
161  assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
162  PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
163  assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
164  return ModuleDesc;
165 }
166 
167 bool PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
168  if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
169  return true;
170 
171  // Saving Module for AfterPassInvalidated operations.
172  // Note: here we rely on a fact that we do not change modules while
173  // traversing the pipeline, so the latest captured module is good
174  // for all print operations that has not happen yet.
175  if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID))
176  pushModuleDesc(PassID, IR);
177 
178  if (!llvm::shouldPrintBeforePass(PassID))
179  return true;
180 
181  SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
182  unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
183  return true;
184 }
185 
186 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
187  if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
188  return;
189 
190  if (!llvm::shouldPrintAfterPass(PassID))
191  return;
192 
193  if (StoreModuleDesc)
194  popModuleDesc(PassID);
195 
196  SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
197  unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
198 }
199 
200 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
201  if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID))
202  return;
203 
204  if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
205  return;
206 
207  const Module *M;
208  std::string Extra;
209  StringRef StoredPassID;
210  std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
211  // Additional filtering (e.g. -filter-print-func) can lead to module
212  // printing being skipped.
213  if (!M)
214  return;
215 
216  SmallString<20> Banner =
217  formatv("*** IR Dump After {0} *** invalidated: ", PassID);
218  printIR(M, Banner, Extra);
219 }
220 
223  // BeforePass callback is not just for printing, it also saves a Module
224  // for later use in AfterPassInvalidated.
225  StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass();
226  if (llvm::shouldPrintBeforePass() || StoreModuleDesc)
228  [this](StringRef P, Any IR) { return this->printBeforePass(P, IR); });
229 
232  [this](StringRef P, Any IR) { this->printAfterPass(P, IR); });
234  [this](StringRef P) { this->printAfterPassInvalidated(P); });
235  }
236 }
237 
240  PrintIR.registerCallbacks(PIC);
241  TimePasses.registerCallbacks(PIC);
242 }
const NoneType None
Definition: None.h:23
uint64_t CallInst * C
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:641
Definition: Any.h:26
bool shouldPrintAfterPass()
bool forcePrintModuleIR()
forcePrintModuleIR - returns true if IR printing passes should
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:66
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:270
bool shouldPrintBeforePass()
This is a helper to determine whether to print IR before or after a pass.
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))...))>
F(f)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
BlockT * getHeader() const
Definition: LoopInfo.h:105
T any_cast(const Any &Value)
Definition: Any.h:122
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW=nullptr, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the function to an output stream with an optional AssemblyAnnotationWriter. ...
Definition: AsmWriter.cpp:4185
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 ...
#define P(N)
A node in the call graph.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_NODISCARD bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:446
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:4356
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the module to an output stream with an optional AssemblyAnnotationWriter.
Definition: AsmWriter.cpp:4196
Module.h This file contains the declarations for the Module class.
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:374
bool isFunctionInPrintList(StringRef FunctionName)
isFunctionInPrintList - returns true if a function should be printed via
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
void registerAfterPassInvalidatedCallback(CallableT C)
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:509
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:106
#define N
This file defines passes to print out IR in various granularities.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:231
std::string getName() const
Provide a short name by printing this SCC to a std::string.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:503
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
LLVM Value Representation.
Definition: Value.h:74
An SCC of the call graph.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop&#39;s contents as LLVM&#39;s text IR assembly.
Definition: LoopInfo.cpp:936
Statically lint checks LLVM IR
Definition: Lint.cpp:192