LLVM 22.0.0git
PassInstrumentation.h
Go to the documentation of this file.
1//===- llvm/IR/PassInstrumentation.h ----------------------*- 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 the Pass Instrumentation classes that provide
11/// instrumentation points into the pass execution by PassManager.
12///
13/// There are two main classes:
14/// - PassInstrumentation provides a set of instrumentation points for
15/// pass managers to call on.
16///
17/// - PassInstrumentationCallbacks registers callbacks and provides access
18/// to them for PassInstrumentation.
19///
20/// PassInstrumentation object is being used as a result of
21/// PassInstrumentationAnalysis (so it is intended to be easily copyable).
22///
23/// Intended scheme of use for Pass Instrumentation is as follows:
24/// - register instrumentation callbacks in PassInstrumentationCallbacks
25/// instance. PassBuilder provides helper for that.
26///
27/// - register PassInstrumentationAnalysis with all the PassManagers.
28/// PassBuilder handles that automatically when registering analyses.
29///
30/// - Pass Manager requests PassInstrumentationAnalysis from analysis manager
31/// and gets PassInstrumentation as its result.
32///
33/// - Pass Manager invokes PassInstrumentation entry points appropriately,
34/// passing StringRef identification ("name") of the pass currently being
35/// executed and IRUnit it works on. There can be different schemes of
36/// providing names in future, currently it is just a name() of the pass.
37///
38/// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes
39/// control to all the registered callbacks. Note that we specifically wrap
40/// 'const IRUnitT*' so as to avoid any accidental changes to IR in
41/// instrumenting callbacks.
42///
43/// - Some instrumentation points (BeforePass) allow to control execution
44/// of a pass. For those callbacks returning false means pass will not be
45/// executed.
46///
47//===----------------------------------------------------------------------===//
48
49#ifndef LLVM_IR_PASSINSTRUMENTATION_H
50#define LLVM_IR_PASSINSTRUMENTATION_H
51
52#include "llvm/ADT/Any.h"
53#include "llvm/ADT/DenseMap.h"
56#include "llvm/IR/PassManager.h"
58#include <type_traits>
59#include <vector>
60
61namespace llvm {
62
63class PreservedAnalyses;
64class StringRef;
65class Module;
66class Loop;
67class Function;
68
69extern template struct LLVM_TEMPLATE_ABI Any::TypeId<const Module *>;
70extern template struct LLVM_TEMPLATE_ABI Any::TypeId<const Function *>;
71extern template struct LLVM_TEMPLATE_ABI Any::TypeId<const Loop *>;
72
73/// This class manages callbacks registration, as well as provides a way for
74/// PassInstrumentation to pass control to the registered callbacks.
76public:
77 // Before/After callbacks accept IRUnits whenever appropriate, so they need
78 // to take them as constant pointers, wrapped with llvm::Any.
79 // For the case when IRUnit has been invalidated there is a different
80 // callback to use - AfterPassInvalidated.
81 // We call all BeforePassFuncs to determine if a pass should run or not.
82 // BeforeNonSkippedPassFuncs are called only if the pass should run.
83 // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing
84 // already invalidated IRUnit is unsafe. There are ways to handle invalidated
85 // IRUnits in a safe way, and we might pursue that as soon as there is a
86 // useful instrumentation that needs it.
96
97public:
99
100 /// Copying PassInstrumentationCallbacks is not intended.
103
104 template <typename CallableT>
106 ShouldRunOptionalPassCallbacks.emplace_back(std::move(C));
107 }
108
109 template <typename CallableT>
111 BeforeSkippedPassCallbacks.emplace_back(std::move(C));
112 }
113
114 template <typename CallableT>
116 BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
117 }
118
119 template <typename CallableT>
120 void registerAfterPassCallback(CallableT C, bool ToFront = false) {
121 if (ToFront)
122 AfterPassCallbacks.insert(AfterPassCallbacks.begin(), std::move(C));
123 else
124 AfterPassCallbacks.emplace_back(std::move(C));
125 }
126
127 template <typename CallableT>
128 void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront = false) {
129 if (ToFront)
130 AfterPassInvalidatedCallbacks.insert(
131 AfterPassInvalidatedCallbacks.begin(), std::move(C));
132 else
133 AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
134 }
135
136 template <typename CallableT>
138 BeforeAnalysisCallbacks.emplace_back(std::move(C));
139 }
140
141 template <typename CallableT>
142 void registerAfterAnalysisCallback(CallableT C, bool ToFront = false) {
143 if (ToFront)
144 AfterAnalysisCallbacks.insert(AfterAnalysisCallbacks.begin(),
145 std::move(C));
146 else
147 AfterAnalysisCallbacks.emplace_back(std::move(C));
148 }
149
150 template <typename CallableT>
152 AnalysisInvalidatedCallbacks.emplace_back(std::move(C));
153 }
154
155 template <typename CallableT>
157 AnalysesClearedCallbacks.emplace_back(std::move(C));
158 }
159
160 template <typename CallableT>
162 ClassToPassNameCallbacks.emplace_back(std::move(C));
163 }
164
165 /// Add a class name to pass name mapping for use by pass instrumentation.
166 LLVM_ABI void addClassToPassName(StringRef ClassName, StringRef PassName);
167 /// Get the pass name for a given pass class name. Empty if no match found.
168 LLVM_ABI StringRef getPassNameForClassName(StringRef ClassName);
169
170private:
172
173 /// These are only run on passes that are not required. They return false when
174 /// an optional pass should be skipped.
176 ShouldRunOptionalPassCallbacks;
177 /// These are run on passes that are skipped.
179 BeforeSkippedPassCallbacks;
180 /// These are run on passes that are about to be run.
182 BeforeNonSkippedPassCallbacks;
183 /// These are run on passes that have just run.
185 /// These are run on passes that have just run on invalidated IR.
187 AfterPassInvalidatedCallbacks;
188 /// These are run on analyses that are about to be run.
190 BeforeAnalysisCallbacks;
191 /// These are run on analyses that have been run.
193 AfterAnalysisCallbacks;
194 /// These are run on analyses that have been invalidated.
196 AnalysisInvalidatedCallbacks;
197 /// These are run on analyses that have been cleared.
199 AnalysesClearedCallbacks;
200
201 SmallVector<llvm::unique_function<void ()>, 4> ClassToPassNameCallbacks;
202 DenseMap<StringRef, std::string> ClassToPassName;
203};
204
205/// This class provides instrumentation entry points for the Pass Manager,
206/// doing calls to callbacks registered in PassInstrumentationCallbacks.
209
210 // Template argument PassT of PassInstrumentation::runBeforePass could be two
211 // kinds: (1) a regular pass inherited from PassInfoMixin (happen when
212 // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept
213 // created from (1). Here we want to make case (1) skippable unconditionally
214 // since they are regular passes. We call PassConcept::isRequired to decide
215 // for case (2).
216 template <typename PassT>
217 using has_required_t = decltype(std::declval<PassT &>().isRequired());
218
219 template <typename PassT> static bool isRequired(const PassT &Pass) {
221 return Pass.isRequired();
222 return false;
223 }
224
225public:
226 /// Callbacks object is not owned by PassInstrumentation, its life-time
227 /// should at least match the life-time of corresponding
228 /// PassInstrumentationAnalysis (which usually is till the end of current
229 /// compilation).
231 : Callbacks(CB) {}
232
233 /// BeforePass instrumentation point - takes \p Pass instance to be executed
234 /// and constant reference to IR it operates on. \Returns true if pass is
235 /// allowed to be executed. These are only run on optional pass since required
236 /// passes must always be run. This allows these callbacks to print info when
237 /// they want to skip a pass.
238 template <typename IRUnitT, typename PassT>
239 bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
240 if (!Callbacks)
241 return true;
242
243 bool ShouldRun = true;
244 if (!isRequired(Pass)) {
245 for (auto &C : Callbacks->ShouldRunOptionalPassCallbacks)
246 ShouldRun &= C(Pass.name(), llvm::Any(&IR));
247 }
248
249 if (ShouldRun) {
250 for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
251 C(Pass.name(), llvm::Any(&IR));
252 } else {
253 for (auto &C : Callbacks->BeforeSkippedPassCallbacks)
254 C(Pass.name(), llvm::Any(&IR));
255 }
256
257 return ShouldRun;
258 }
259
260 /// AfterPass instrumentation point - takes \p Pass instance that has
261 /// just been executed and constant reference to \p IR it operates on.
262 /// \p IR is guaranteed to be valid at this point.
263 template <typename IRUnitT, typename PassT>
264 void runAfterPass(const PassT &Pass, const IRUnitT &IR,
265 const PreservedAnalyses &PA) const {
266 if (Callbacks)
267 for (auto &C : Callbacks->AfterPassCallbacks)
268 C(Pass.name(), llvm::Any(&IR), PA);
269 }
270
271 /// AfterPassInvalidated instrumentation point - takes \p Pass instance
272 /// that has just been executed. For use when IR has been invalidated
273 /// by \p Pass execution.
274 template <typename IRUnitT, typename PassT>
275 void runAfterPassInvalidated(const PassT &Pass,
276 const PreservedAnalyses &PA) const {
277 if (Callbacks)
278 for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
279 C(Pass.name(), PA);
280 }
281
282 /// BeforeAnalysis instrumentation point - takes \p Analysis instance
283 /// to be executed and constant reference to IR it operates on.
284 template <typename IRUnitT, typename PassT>
285 void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
286 if (Callbacks)
287 for (auto &C : Callbacks->BeforeAnalysisCallbacks)
288 C(Analysis.name(), llvm::Any(&IR));
289 }
290
291 /// AfterAnalysis instrumentation point - takes \p Analysis instance
292 /// that has just been executed and constant reference to IR it operated on.
293 template <typename IRUnitT, typename PassT>
294 void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
295 if (Callbacks)
296 for (auto &C : Callbacks->AfterAnalysisCallbacks)
297 C(Analysis.name(), llvm::Any(&IR));
298 }
299
300 /// AnalysisInvalidated instrumentation point - takes \p Analysis instance
301 /// that has just been invalidated and constant reference to IR it operated
302 /// on.
303 template <typename IRUnitT, typename PassT>
304 void runAnalysisInvalidated(const PassT &Analysis, const IRUnitT &IR) const {
305 if (Callbacks)
306 for (auto &C : Callbacks->AnalysisInvalidatedCallbacks)
307 C(Analysis.name(), llvm::Any(&IR));
308 }
309
310 /// AnalysesCleared instrumentation point - takes name of IR that analyses
311 /// operated on.
313 if (Callbacks)
314 for (auto &C : Callbacks->AnalysesClearedCallbacks)
315 C(Name);
316 }
317
318 /// Handle invalidation from the pass manager when PassInstrumentation
319 /// is used as the result of PassInstrumentationAnalysis.
320 ///
321 /// On attempt to invalidate just return false. There is nothing to become
322 /// invalid here.
323 template <typename IRUnitT, typename... ExtraArgsT>
324 bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
325 ExtraArgsT...) {
326 return false;
327 }
328
329 template <typename CallableT>
331 if (Callbacks)
332 Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
333 }
335 if (Callbacks)
336 Callbacks->BeforeNonSkippedPassCallbacks.pop_back();
337 }
338
339 /// Get the pass name for a given pass class name.
341 if (Callbacks)
342 return Callbacks->getPassNameForClassName(ClassName);
343 return {};
344 }
345};
346
347LLVM_ABI bool isSpecialPass(StringRef PassID,
348 const std::vector<StringRef> &Specials);
349
350/// Pseudo-analysis pass that exposes the \c PassInstrumentation to pass
351/// managers.
353 : public AnalysisInfoMixin<PassInstrumentationAnalysis> {
355 LLVM_ABI static AnalysisKey Key;
356
358
359public:
360 /// PassInstrumentationCallbacks object is shared, owned by something else,
361 /// not this analysis.
363 : Callbacks(Callbacks) {}
364
366
367 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
368 Result run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) {
369 return PassInstrumentation(Callbacks);
370 }
371};
372
373
374} // namespace llvm
375
376#endif
This file provides Any, a non-template class modeled in the spirit of std::any.
block Block Frequency Analysis
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_TEMPLATE_ABI
Definition: Compiler.h:214
This file defines the DenseMap class.
std::string Name
This file provides a collection of function (or more generally, callable) type erasure utilities supp...
This header defines various interfaces for pass management in LLVM.
Legalize the Machine IR a function s Machine IR
Definition: Legalizer.cpp:80
Machine Check Debug Module
This file defines the SmallVector class.
static const char PassName[]
Definition: Any.h:28
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
Result run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...)
PassInstrumentationAnalysis(PassInstrumentationCallbacks *Callbacks=nullptr)
PassInstrumentationCallbacks object is shared, owned by something else, not this analysis.
This class provides instrumentation entry points for the Pass Manager, doing calls to callbacks regis...
void runAfterPassInvalidated(const PassT &Pass, const PreservedAnalyses &PA) const
AfterPassInvalidated instrumentation point - takes Pass instance that has just been executed.
void pushBeforeNonSkippedPassCallback(CallableT C)
PassInstrumentation(PassInstrumentationCallbacks *CB=nullptr)
Callbacks object is not owned by PassInstrumentation, its life-time should at least match the life-ti...
bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &, ExtraArgsT...)
Handle invalidation from the pass manager when PassInstrumentation is used as the result of PassInstr...
void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const
BeforeAnalysis instrumentation point - takes Analysis instance to be executed and constant reference ...
void runAnalysisInvalidated(const PassT &Analysis, const IRUnitT &IR) const
AnalysisInvalidated instrumentation point - takes Analysis instance that has just been invalidated an...
void runAnalysesCleared(StringRef Name) const
AnalysesCleared instrumentation point - takes name of IR that analyses operated on.
StringRef getPassNameForClassName(StringRef ClassName) const
Get the pass name for a given pass class name.
void runAfterPass(const PassT &Pass, const IRUnitT &IR, const PreservedAnalyses &PA) const
AfterPass instrumentation point - takes Pass instance that has just been executed and constant refere...
void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const
AfterAnalysis instrumentation point - takes Analysis instance that has just been executed and constan...
bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const
BeforePass instrumentation point - takes Pass instance to be executed and constant reference to IR it...
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:99
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
unique_function is a type-erasing functor similar to std::function.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
typename detail::detector< void, Op, Args... >::value_t is_detected
Detects if a given trait holds for some set of arguments 'Args'.
Definition: STLExtras.h:79
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:93
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:29
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
void registerAnalysisInvalidatedCallback(CallableT C)
LLVM_ABI StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name. Empty if no match found.
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
void(StringRef, const PreservedAnalyses &) AfterPassInvalidatedFunc
void(StringRef, Any) BeforeNonSkippedPassFunc
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerBeforeSkippedPassCallback(CallableT C)
PassInstrumentationCallbacks(const PassInstrumentationCallbacks &)=delete
Copying PassInstrumentationCallbacks is not intended.
void registerShouldRunOptionalPassCallback(CallableT C)
void(StringRef, Any) BeforeSkippedPassFunc
void operator=(const PassInstrumentationCallbacks &)=delete
void(StringRef, Any) AnalysisInvalidatedFunc
void(StringRef, Any, const PreservedAnalyses &) AfterPassFunc
void registerAfterPassCallback(CallableT C, bool ToFront=false)