blob: 3718b53c45348f3fbcb00ab23e22ca8f5b384c1a [file] [log] [blame]
Andrew Scull0372a572018-11-16 15:47:06 +00001//===- llvm/IR/PassInstrumentation.h ----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10///
11/// This file defines the Pass Instrumentation classes that provide
12/// instrumentation points into the pass execution by PassManager.
13///
14/// There are two main classes:
15/// - PassInstrumentation provides a set of instrumentation points for
16/// pass managers to call on.
17///
18/// - PassInstrumentationCallbacks registers callbacks and provides access
19/// to them for PassInstrumentation.
20///
21/// PassInstrumentation object is being used as a result of
22/// PassInstrumentationAnalysis (so it is intended to be easily copyable).
23///
24/// Intended scheme of use for Pass Instrumentation is as follows:
25/// - register instrumentation callbacks in PassInstrumentationCallbacks
26/// instance. PassBuilder provides helper for that.
27///
28/// - register PassInstrumentationAnalysis with all the PassManagers.
29/// PassBuilder handles that automatically when registering analyses.
30///
31/// - Pass Manager requests PassInstrumentationAnalysis from analysis manager
32/// and gets PassInstrumentation as its result.
33///
34/// - Pass Manager invokes PassInstrumentation entry points appropriately,
35/// passing StringRef identification ("name") of the pass currently being
36/// executed and IRUnit it works on. There can be different schemes of
37/// providing names in future, currently it is just a name() of the pass.
38///
39/// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes
40/// control to all the registered callbacks. Note that we specifically wrap
41/// 'const IRUnitT*' so as to avoid any accidental changes to IR in
42/// instrumenting callbacks.
43///
44/// - Some instrumentation points (BeforePass) allow to control execution
45/// of a pass. For those callbacks returning false means pass will not be
46/// executed.
47///
48/// TODO: currently there is no way for a pass to opt-out of execution control
49/// (e.g. become unskippable). PassManager is the only entity that determines
50/// how pass instrumentation affects pass execution.
51///
52//===----------------------------------------------------------------------===//
53
54#ifndef LLVM_IR_PASSINSTRUMENTATION_H
55#define LLVM_IR_PASSINSTRUMENTATION_H
56
57#include "llvm/ADT/Any.h"
58#include "llvm/ADT/FunctionExtras.h"
59#include "llvm/ADT/SmallVector.h"
60#include "llvm/Support/TypeName.h"
61#include <type_traits>
62
63namespace llvm {
64
65class PreservedAnalyses;
66
67/// This class manages callbacks registration, as well as provides a way for
68/// PassInstrumentation to pass control to the registered callbacks.
69class PassInstrumentationCallbacks {
70public:
71 // Before/After callbacks accept IRUnits, so they need to take them
72 // as pointers, wrapped with llvm::Any
73 using BeforePassFunc = bool(StringRef, Any);
74 using AfterPassFunc = void(StringRef, Any);
75 using BeforeAnalysisFunc = void(StringRef, Any);
76 using AfterAnalysisFunc = void(StringRef, Any);
77
78public:
79 PassInstrumentationCallbacks() {}
80
81 /// Copying PassInstrumentationCallbacks is not intended.
82 PassInstrumentationCallbacks(const PassInstrumentationCallbacks &) = delete;
83 void operator=(const PassInstrumentationCallbacks &) = delete;
84
85 template <typename CallableT> void registerBeforePassCallback(CallableT C) {
86 BeforePassCallbacks.emplace_back(std::move(C));
87 }
88
89 template <typename CallableT> void registerAfterPassCallback(CallableT C) {
90 AfterPassCallbacks.emplace_back(std::move(C));
91 }
92
93 template <typename CallableT>
94 void registerBeforeAnalysisCallback(CallableT C) {
95 BeforeAnalysisCallbacks.emplace_back(std::move(C));
96 }
97
98 template <typename CallableT>
99 void registerAfterAnalysisCallback(CallableT C) {
100 AfterAnalysisCallbacks.emplace_back(std::move(C));
101 }
102
103private:
104 friend class PassInstrumentation;
105
106 SmallVector<llvm::unique_function<BeforePassFunc>, 4> BeforePassCallbacks;
107 SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
108 SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
109 BeforeAnalysisCallbacks;
110 SmallVector<llvm::unique_function<AfterAnalysisFunc>, 4>
111 AfterAnalysisCallbacks;
112};
113
114/// This class provides instrumentation entry points for the Pass Manager,
115/// doing calls to callbacks registered in PassInstrumentationCallbacks.
116class PassInstrumentation {
117 PassInstrumentationCallbacks *Callbacks;
118
119public:
120 /// Callbacks object is not owned by PassInstrumentation, its life-time
121 /// should at least match the life-time of corresponding
122 /// PassInstrumentationAnalysis (which usually is till the end of current
123 /// compilation).
124 PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr)
125 : Callbacks(CB) {}
126
127 /// BeforePass instrumentation point - takes \p Pass instance to be executed
128 /// and constant reference to IR it operates on. \Returns true if pass is
129 /// allowed to be executed.
130 template <typename IRUnitT, typename PassT>
131 bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
132 if (!Callbacks)
133 return true;
134
135 bool ShouldRun = true;
136 for (auto &C : Callbacks->BeforePassCallbacks)
137 ShouldRun &= C(Pass.name(), llvm::Any(&IR));
138 return ShouldRun;
139 }
140
141 /// AfterPass instrumentation point - takes \p Pass instance that has
142 /// just been executed and constant reference to IR it operates on.
143 template <typename IRUnitT, typename PassT>
144 void runAfterPass(const PassT &Pass, const IRUnitT &IR) const {
145 if (Callbacks)
146 for (auto &C : Callbacks->AfterPassCallbacks)
147 C(Pass.name(), llvm::Any(&IR));
148 }
149
150 /// BeforeAnalysis instrumentation point - takes \p Analysis instance
151 /// to be executed and constant reference to IR it operates on.
152 template <typename IRUnitT, typename PassT>
153 void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
154 if (Callbacks)
155 for (auto &C : Callbacks->BeforeAnalysisCallbacks)
156 C(Analysis.name(), llvm::Any(&IR));
157 }
158
159 /// AfterAnalysis instrumentation point - takes \p Analysis instance
160 /// that has just been executed and constant reference to IR it operated on.
161 template <typename IRUnitT, typename PassT>
162 void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
163 if (Callbacks)
164 for (auto &C : Callbacks->AfterAnalysisCallbacks)
165 C(Analysis.name(), llvm::Any(&IR));
166 }
167
168 /// Handle invalidation from the pass manager when PassInstrumentation
169 /// is used as the result of PassInstrumentationAnalysis.
170 ///
171 /// On attempt to invalidate just return false. There is nothing to become
172 /// invalid here.
173 template <typename IRUnitT, typename... ExtraArgsT>
174 bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
175 ExtraArgsT...) {
176 return false;
177 }
178};
179
180} // namespace llvm
181
182#endif