1/**
2 * Copyright (c) Glow Contributors. See CONTRIBUTORS file.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef GLOW_PASSMANAGER_PASSMANAGER_H
17#define GLOW_PASSMANAGER_PASSMANAGER_H
18
19#include "glow/Backend/Backend.h"
20
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/CommandLine.h"
23
24#include <atomic>
25
26namespace glow {
27
28struct CompilationContext;
29class IRContainer;
30class PassBase;
31
32/// A set of options and command-line options for a pass manager.
33struct PassManagerOptions {
34 /// The unique pass manager id.
35 const std::string passManagerID;
36 /// Command-line options category to be used for this pass manager.
37 llvm::cl::OptionCategory passManagerCat;
38
39 llvm::cl::opt<bool> verifyBeforeAllPassesOpt;
40
41 llvm::cl::list<std::string> verifyBeforePassesOpt;
42
43 llvm::cl::opt<bool> verifyAfterAllPassesOpt;
44
45 llvm::cl::list<std::string> verifyAfterPassesOpt;
46
47 llvm::cl::opt<bool> dumpIRBeforeAllPassesOpt;
48
49 llvm::cl::list<std::string> dumpIRBeforePassesOpt;
50
51 llvm::cl::opt<bool> dumpIRAfterAllPassesOpt;
52
53 llvm::cl::list<std::string> dumpIRAfterPassesOpt;
54
55 llvm::cl::opt<bool> printPassesOpt;
56
57 llvm::cl::opt<unsigned> stopAfterPassNumOpt;
58
59 PassManagerOptions(const char *id);
60 /// Helper to check if \p otherStr is in \p strList.
61 static bool listContainsString(const llvm::cl::list<std::string> &strList,
62 llvm::StringRef otherStr);
63};
64
65/// The base class for pass managers. It contains most of the logic common for
66/// all pass managers, but provides a number of hooks that can be overridden by
67/// concrete pass manager to customize the behavior.
68class PassManagerBase : public Named {
69
70private:
71 /// The index of pass iteration
72 int iterationCount_ = 0;
73
74protected:
75 /// The index of the current pass being executed in the pipeline.
76 size_t passIdx_ = 0;
77 /// The Backend we have for backend-specific verification.
78 const Backend *backend_;
79
80 /// Logic to execute before pass \p P is run on \p C, given \p cctx. \returns
81 /// if \p C was modified.
82 bool runPrePass(IRContainer *C, const CompilationContext &cctx,
83 const PassBase &P);
84
85 /// A runPrePass customization point for the derived classes.
86 virtual void runPrePassHook(IRContainer *C, const CompilationContext &cctx,
87 const PassBase &P);
88
89 /// Logic to execute after pass \p P is run on \p C, given \p cctx. \returns
90 /// if \p C was modified.
91 bool runPostPass(IRContainer *C, const CompilationContext &cctx,
92 const PassBase &P);
93
94 /// A runPostPass customization point for the derived classes.
95 virtual void runPostPassHook(IRContainer *C, const CompilationContext &cctx,
96 const PassBase &P);
97
98 // /// Runs a FunctionPass described by \p passConfig over \p C given \p cctx.
99 /// Run a pass configured by \p passConfig over IR \p C given \p cctx.
100 virtual bool runPass(const PassConfigBase &passConfig, IRContainer *C,
101 const CompilationContext &cctx);
102
103 /// A runPass customization point for the derived classes.
104 virtual bool runPassHook(const PassConfigBase &passConfig, glow::PassBase &P,
105 IRContainer *C, const CompilationContext &cctx) = 0;
106
107 /// Runs a pass corresponding to the provided \p passConfig on the IR
108 /// container \p C given \p cctx.
109 virtual bool runPassWithConfig(const PassConfigBase &passConfig,
110 IRContainer *C,
111 const CompilationContext &cctx) = 0;
112
113 /// \returns the name of the pass corresponding to \p passConfig.
114 virtual llvm::StringRef
115 getNameOfPass(const PassConfigBase &passConfig) const = 0;
116
117 /// Creates and \returns a Pass given a provided \p passConfig.
118 virtual std::unique_ptr<PassBase>
119 createFunctionPass(const PassConfigBase &passConfig) const = 0;
120
121 /// Run the PassPipeline given the \ref pipeline_ and
122 /// \p cctx. \returns whether \p C was modified.
123 bool run(IRContainer *C, const CompilationContext &cctx);
124
125 /// \returns the size of the pass pipeline.
126 virtual size_t getPipelineSize() const = 0;
127
128 /// \returns the \p idx of the pass pipeline.
129 virtual const PassConfigBase &getPipelineElement(size_t idx) const = 0;
130
131 /// Dump the IR of \p C into the output stream \p or into a file \p
132 /// outputFileName, depending on the backend type.
133 virtual void dumpIR(IRContainer *C, llvm::raw_ostream &os,
134 const std::string &outputFileName) const = 0;
135
136public:
137 /// Constructor.
138 PassManagerBase(llvm::StringRef name) : Named(name) {}
139 virtual ~PassManagerBase() = default;
140
141 /// Dump a textual representation of the Manager to \p os.
142 void dump(llvm::raw_ostream &os = llvm::outs()) const;
143
144 /// \returns the result of verification for a provided IR container \p C.
145 virtual bool verify(IRContainer &C) const = 0;
146
147 /// \returns the result of a backend-specific verification for a provided IR
148 /// container \p C.
149 virtual bool verify(const Backend &B, IRContainer &C) const = 0;
150
151 /// Get options of this pass manager.
152 virtual const PassManagerOptions &getOptions() const = 0;
153 /// Get the global pass counter associated with the pass manager.
154 virtual std::atomic<unsigned> &globalPassCounter() = 0;
155 /// Get the global pass counter associated with the pass manager.
156 virtual const std::atomic<unsigned> &globalPassCounter() const = 0;
157};
158
159template <typename IRPassTy, typename PassIDTy>
160std::unique_ptr<IRPassTy> createFunctionPass(PassIDTy);
161
162/// Manager for running a series of FunctionPasses. Given some Function,
163/// CompilationContext, and provided Pipeline, it will run all passes on the
164/// Function. Enables easier debugging given runPrePass() and runPostPass()
165/// calls, which can be modified to run some code before or before every pass.
166template <typename IRPASS_PIPELINE, typename IRPASS>
167class PassManager : public PassManagerBase {
168public:
169 using IRPassTy = IRPASS;
170 using IRPassPipelineTy = IRPASS_PIPELINE;
171 using IRContainerTy = typename IRPassTy::IRContainerTy;
172 using PassIDTy = typename IRPassTy::PassIDTy;
173 using IRPassConfigTy = typename IRPassPipelineTy::IRPassConfigTy;
174
175private:
176 /// The pipeline of passes to run.
177 std::unique_ptr<IRPassPipelineTy> pipeline_;
178 /// Options and command-line options for this pass manager.
179 static PassManagerOptions &options_;
180
181 /// Global pass counter used to identify each pass.
182 std::atomic<unsigned> globalPassCounter_;
183
184 /// Creates and \returns a Pass given a provided \p passID.
185 std::unique_ptr<IRPassTy> createFunctionPass(PassIDTy passID) const;
186
187 std::unique_ptr<PassBase>
188 createFunctionPass(const PassConfigBase &passConfig) const override {
189 return createFunctionPass(
190 static_cast<const IRPassConfigTy *>(&passConfig)->getPassID());
191 }
192
193 bool runPassHook(const PassConfigBase &passConfig, PassBase &P,
194 IRContainer *C, const CompilationContext &cctx) override;
195
196 bool runPassWithConfig(const PassConfigBase &passConfig, IRContainer *C,
197 const CompilationContext &cctx) override {
198 return runPass(*static_cast<const IRPassConfigTy *>(&passConfig),
199 static_cast<IRContainerTy *>(C), cctx);
200 }
201
202 llvm::StringRef
203 getNameOfPass(const PassConfigBase &passConfig) const override {
204 return glow::getNameOfPass(
205 static_cast<const IRPassConfigTy *>(&passConfig)->getPassID());
206 }
207
208 size_t getPipelineSize() const override { return getPipeline().size(); }
209
210 const PassConfigBase &getPipelineElement(size_t idx) const override {
211 return getPipeline().at(idx);
212 }
213
214 bool verify(IRContainer &C) const override {
215 return static_cast<IRContainerTy *>(&C)->verify();
216 }
217
218 bool verify(const Backend &B, IRContainer &C) const override {
219 return B.verify(*static_cast<IRContainerTy *>(&C));
220 }
221
222public:
223 /// Constructor.
224 /// Create a pass manager with a given \p name, provided the \p pipeline and
225 /// an optional \p backend.
226 PassManager(llvm::StringRef name, std::unique_ptr<IRPassPipelineTy> pipeline,
227 const Backend *backend = nullptr)
228 : PassManagerBase(name), pipeline_(std::move(pipeline)) {
229 backend_ = backend;
230 passIdx_ = 0;
231 }
232
233 PassManager(llvm::StringRef name,
234 const std::initializer_list<IRPassConfigTy> &configs,
235 const Backend *backend = nullptr)
236 : PassManagerBase(name) {
237 backend_ = backend;
238 passIdx_ = 0;
239 pipeline_ = glow::make_unique<IRPassPipelineTy>(configs);
240 }
241
242 /// Constructor.
243 /// Create a pass with a given \p name, provided the pipeline definition in
244 /// file \p pipelineDefFilename and an optional \p backend.
245 PassManager(llvm::StringRef name, llvm::StringRef pipelineDefFilename,
246 const Backend *backend = nullptr)
247 : PassManagerBase(name),
248 pipeline_(glow::make_unique<IRPassPipelineTy>()) {
249 backend_ = backend;
250 passIdx_ = 0;
251 pipeline_->initFromFile(pipelineDefFilename);
252 }
253
254 virtual ~PassManager() = default;
255
256 /// Run the PassPipeline pipeline_ on the IR container \p C and
257 /// \p cctx. \returns whether \p C was modified.
258 bool run(IRContainerTy *C, const CompilationContext &cctx) {
259 return PassManagerBase::run(C, cctx);
260 }
261
262 /// Getter for a reference to the Pipeline used by this PassManager.
263 const IRPassPipelineTy &getPipeline() const { return *pipeline_; };
264
265 /// Dump a textual representation of the PassManager to \p os.
266 void dump(llvm::raw_ostream &os = llvm::outs()) const {
267 PassManagerBase::dump(os);
268 getPipeline().dump();
269 }
270
271 void dumpIR(IRContainer *C, llvm::raw_ostream &os,
272 const std::string &outputFileName) const override;
273
274 /// Get options of this pass manager.
275 const PassManagerOptions &getOptions() const override { return options_; }
276
277 std::atomic<unsigned> &globalPassCounter() override {
278 return globalPassCounter_;
279 }
280
281 const std::atomic<unsigned> &globalPassCounter() const override {
282 return globalPassCounter_;
283 }
284};
285
286} // namespace glow
287
288#endif // GLOW_PASSMANAGER_PASSMANAGER_H
289