Line data Source code
1 : //===- 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 :
63 : namespace llvm {
64 :
65 : class PreservedAnalyses;
66 :
67 : /// This class manages callbacks registration, as well as provides a way for
68 : /// PassInstrumentation to pass control to the registered callbacks.
69 : class PassInstrumentationCallbacks {
70 : public:
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 :
78 : public:
79 955 : 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 12 : BeforePassCallbacks.emplace_back(std::move(C));
87 : }
88 :
89 : template <typename CallableT> void registerAfterPassCallback(CallableT C) {
90 18 : AfterPassCallbacks.emplace_back(std::move(C));
91 : }
92 :
93 : template <typename CallableT>
94 : void registerBeforeAnalysisCallback(CallableT C) {
95 11 : BeforeAnalysisCallbacks.emplace_back(std::move(C));
96 : }
97 :
98 : template <typename CallableT>
99 : void registerAfterAnalysisCallback(CallableT C) {
100 11 : AfterAnalysisCallbacks.emplace_back(std::move(C));
101 : }
102 :
103 : private:
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.
116 : class PassInstrumentation {
117 : PassInstrumentationCallbacks *Callbacks;
118 :
119 : public:
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 31741 : : 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 28243 : bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
132 28243 : if (!Callbacks)
133 0 : return true;
134 :
135 : bool ShouldRun = true;
136 20527 : for (auto &C : Callbacks->BeforePassCallbacks)
137 634 : ShouldRun &= C(Pass.name(), llvm::Any(&IR));
138 : return ShouldRun;
139 : }
140 12918 :
141 12918 : /// 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 3216 : void runAfterPass(const PassT &Pass, const IRUnitT &IR) const {
145 11455 : if (Callbacks)
146 2945 : for (auto &C : Callbacks->AfterPassCallbacks)
147 68 : C(Pass.name(), llvm::Any(&IR));
148 3216 : }
149 7945 :
150 7945 : /// 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 5143 : void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
154 11533 : if (Callbacks)
155 4145 : for (auto &C : Callbacks->BeforeAnalysisCallbacks)
156 60 : C(Analysis.name(), llvm::Any(&IR));
157 5143 : }
158 387 :
159 387 : /// AfterAnalysis instrumentation point - takes \p Analysis instance
160 120 : /// that has just been executed and constant reference to IR it operated on.
161 0 : template <typename IRUnitT, typename PassT>
162 23828 : void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
163 26919 : if (Callbacks)
164 18998 : for (auto &C : Callbacks->AfterAnalysisCallbacks)
165 3237 : C(Analysis.name(), llvm::Any(&IR));
166 23698 : }
167 16182 :
168 12991 : /// Handle invalidation from the pass manager when PassInstrumentation
169 8205 : /// is used as the result of PassInstrumentationAnalysis.
170 378 : ///
171 12857 : /// On attempt to invalidate just return false. There is nothing to become
172 11975 : /// invalid here.
173 11915 : template <typename IRUnitT, typename... ExtraArgsT>
174 8861 : bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
175 214 : ExtraArgsT...) {
176 11914 : return false;
177 490 : }
178 487 : };
179 402 :
180 35 : } // namespace llvm
181 24263 :
182 27765 : #endif
|