xref: /llvm-project/mlir/include/mlir/Pass/PassRegistry.h (revision 5e6d5c01e0ec3a2bc104cba78e9fe8e58360fb6a)
1 //===- PassRegistry.h - Pass Registration Utilities -------------*- 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 //
9 // This file contains utilities for registering information about compiler
10 // passes.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_PASS_PASSREGISTRY_H_
15 #define MLIR_PASS_PASSREGISTRY_H_
16 
17 #include "mlir/Pass/PassOptions.h"
18 #include "mlir/Support/TypeID.h"
19 #include <functional>
20 #include <utility>
21 #include <optional>
22 
23 namespace mlir {
24 class OpPassManager;
25 class ParserConfig;
26 class Pass;
27 class PassManager;
28 
29 namespace detail {
30 class PassOptions;
31 } // namespace detail
32 
33 /// A registry function that adds passes to the given pass manager. This should
34 /// also parse options and return success() if parsing succeeded.
35 /// `errorHandler` is a functor used to emit errors during parsing.
36 /// parameter corresponds to the raw location within the pipeline string. This
37 /// should always return failure.
38 using PassRegistryFunction = std::function<LogicalResult(
39     OpPassManager &, StringRef options,
40     function_ref<LogicalResult(const Twine &)> errorHandler)>;
41 using PassAllocatorFunction = std::function<std::unique_ptr<Pass>()>;
42 
43 //===----------------------------------------------------------------------===//
44 // PassRegistry
45 //===----------------------------------------------------------------------===//
46 
47 /// Prints the passes that were previously registered and stored in passRegistry
48 void printRegisteredPasses();
49 
50 /// Structure to group information about a passes and pass pipelines (argument
51 /// to invoke via mlir-opt, description, pass pipeline builder).
52 class PassRegistryEntry {
53 public:
54   /// Adds this pass registry entry to the given pass manager. `options` is
55   /// an opaque string that will be parsed by the builder. The success of
56   /// parsing will be returned.
57   LogicalResult
58   addToPipeline(OpPassManager &pm, StringRef options,
59                 function_ref<LogicalResult(const Twine &)> errorHandler) const {
60     assert(builder &&
61            "cannot call addToPipeline on PassRegistryEntry without builder");
62     return builder(pm, options, errorHandler);
63   }
64 
65   /// Returns the command line option that may be passed to 'mlir-opt' that will
66   /// cause this pass to run or null if there is no such argument.
67   StringRef getPassArgument() const { return arg; }
68 
69   /// Returns a description for the pass, this never returns null.
70   StringRef getPassDescription() const { return description; }
71 
72   /// Print the help information for this pass. This includes the argument,
73   /// description, and any pass options. `descIndent` is the indent that the
74   /// descriptions should be aligned.
75   void printHelpStr(size_t indent, size_t descIndent) const;
76 
77   /// Return the maximum width required when printing the options of this entry.
78   size_t getOptionWidth() const;
79 
80 protected:
81   PassRegistryEntry(
82       StringRef arg, StringRef description, const PassRegistryFunction &builder,
83       std::function<void(function_ref<void(const detail::PassOptions &)>)>
84           optHandler)
85       : arg(arg), description(description), builder(builder),
86         optHandler(std::move(optHandler)) {}
87 
88 private:
89   /// The argument with which to invoke the pass via mlir-opt.
90   std::string arg;
91 
92   /// Description of the pass.
93   std::string description;
94 
95   /// Function to register this entry to a pass manager pipeline.
96   PassRegistryFunction builder;
97 
98   /// Function to invoke a handler for a pass options instance.
99   std::function<void(function_ref<void(const detail::PassOptions &)>)>
100       optHandler;
101 };
102 
103 /// A structure to represent the information of a registered pass pipeline.
104 class PassPipelineInfo : public PassRegistryEntry {
105 public:
106   PassPipelineInfo(
107       StringRef arg, StringRef description, const PassRegistryFunction &builder,
108       std::function<void(function_ref<void(const detail::PassOptions &)>)>
109           optHandler)
110       : PassRegistryEntry(arg, description, builder, std::move(optHandler)) {}
111 
112   /// Returns the pass pipeline info for the specified pass pipeline or null if
113   /// unknown.
114   static const PassPipelineInfo *lookup(StringRef pipelineArg);
115 };
116 
117 /// A structure to represent the information for a derived pass class.
118 class PassInfo : public PassRegistryEntry {
119 public:
120   /// PassInfo constructor should not be invoked directly, instead use
121   /// PassRegistration or registerPass.
122   PassInfo(StringRef arg, StringRef description,
123            const PassAllocatorFunction &allocator);
124 
125   /// Returns the pass info for the specified pass class or null if unknown.
126   static const PassInfo *lookup(StringRef passArg);
127 };
128 
129 //===----------------------------------------------------------------------===//
130 // PassRegistration
131 //===----------------------------------------------------------------------===//
132 
133 /// Register a specific dialect pipeline registry function with the system,
134 /// typically used through the PassPipelineRegistration template.
135 void registerPassPipeline(
136     StringRef arg, StringRef description, const PassRegistryFunction &function,
137     std::function<void(function_ref<void(const detail::PassOptions &)>)>
138         optHandler);
139 
140 /// Register a specific dialect pass allocator function with the system,
141 /// typically used through the PassRegistration template.
142 void registerPass(const PassAllocatorFunction &function);
143 
144 /// PassRegistration provides a global initializer that registers a Pass
145 /// allocation routine for a concrete pass instance. The argument is
146 /// optional and provides a callback to construct a pass that does not have
147 /// a default constructor.
148 ///
149 /// Usage:
150 ///
151 ///   /// At namespace scope.
152 ///   static PassRegistration<MyPass> reg;
153 ///
154 template <typename ConcretePass>
155 struct PassRegistration {
156   PassRegistration(const PassAllocatorFunction &constructor) {
157     registerPass(constructor);
158   }
159   PassRegistration()
160       : PassRegistration([] { return std::make_unique<ConcretePass>(); }) {}
161 };
162 
163 /// PassPipelineRegistration provides a global initializer that registers a Pass
164 /// pipeline builder routine.
165 ///
166 /// Usage:
167 ///
168 ///   // At namespace scope.
169 ///   void pipelineBuilder(OpPassManager &pm) {
170 ///      pm.addPass(new MyPass());
171 ///      pm.addPass(new MyOtherPass());
172 ///   }
173 ///
174 ///   static PassPipelineRegistration Unused("unused", "Unused pass",
175 ///                                          pipelineBuilder);
176 template <typename Options = EmptyPipelineOptions>
177 struct PassPipelineRegistration {
178   PassPipelineRegistration(
179       StringRef arg, StringRef description,
180       std::function<void(OpPassManager &, const Options &options)> builder) {
181     registerPassPipeline(
182         arg, description,
183         [builder](OpPassManager &pm, StringRef optionsStr,
184                   function_ref<LogicalResult(const Twine &)> errorHandler) {
185           Options options;
186           if (failed(options.parseFromString(optionsStr)))
187             return failure();
188           builder(pm, options);
189           return success();
190         },
191         [](function_ref<void(const detail::PassOptions &)> optHandler) {
192           optHandler(Options());
193         });
194   }
195 };
196 
197 /// Convenience specialization of PassPipelineRegistration for EmptyPassOptions
198 /// that does not pass an empty options struct to the pass builder function.
199 template <>
200 struct PassPipelineRegistration<EmptyPipelineOptions> {
201   PassPipelineRegistration(
202       StringRef arg, StringRef description,
203       const std::function<void(OpPassManager &)> &builder) {
204     registerPassPipeline(
205         arg, description,
206         [builder](OpPassManager &pm, StringRef optionsStr,
207                   function_ref<LogicalResult(const Twine &)> errorHandler) {
208           if (!optionsStr.empty())
209             return failure();
210           builder(pm);
211           return success();
212         },
213         [](function_ref<void(const detail::PassOptions &)>) {});
214   }
215 };
216 
217 /// Parse the textual representation of a pass pipeline, adding the result to
218 /// 'pm' on success. Returns failure if the given pipeline was invalid.
219 /// 'errorStream' is the output stream used to emit errors found during parsing.
220 LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm,
221                                 raw_ostream &errorStream = llvm::errs());
222 
223 /// Parse the given textual representation of a pass pipeline, and return the
224 /// parsed pipeline on success. The given pipeline string should be wrapped with
225 /// the desired type of operation to root the created operation, i.e.
226 /// `builtin.module(cse)` over `cse`. Returns failure if the given pipeline was
227 /// invalid. 'errorStream' is the output stream used to emit errors found during
228 /// parsing.
229 FailureOr<OpPassManager>
230 parsePassPipeline(StringRef pipeline, raw_ostream &errorStream = llvm::errs());
231 
232 //===----------------------------------------------------------------------===//
233 // PassPipelineCLParser
234 //===----------------------------------------------------------------------===//
235 
236 namespace detail {
237 struct PassPipelineCLParserImpl;
238 } // namespace detail
239 
240 /// This class implements a command-line parser for MLIR passes. It registers a
241 /// cl option with a given argument and description. This parser will register
242 /// options for each of the passes and pipelines that have been registered with
243 /// the pass registry; Meaning that `-cse` will refer to the CSE pass in MLIR.
244 /// It also registers an argument, `pass-pipeline`, that supports parsing a
245 /// textual description of a pipeline. This option is mutually exclusive with
246 /// the individual pass options.
247 class PassPipelineCLParser {
248 public:
249   /// Construct a pass pipeline parser with the given command line description.
250   /// Optionally registers an alias for the `pass-pipeline` option.
251   PassPipelineCLParser(StringRef arg, StringRef description);
252   PassPipelineCLParser(StringRef arg, StringRef description, StringRef alias);
253   ~PassPipelineCLParser();
254 
255   /// Returns true if this parser contains any valid options to add.
256   bool hasAnyOccurrences() const;
257 
258   /// Returns true if the given pass registry entry was registered at the
259   /// top-level of the parser, i.e. not within an explicit textual pipeline.
260   bool contains(const PassRegistryEntry *entry) const;
261 
262   /// Adds the passes defined by this parser entry to the given pass manager.
263   /// Returns failure() if the pass could not be properly constructed due
264   /// to options parsing.
265   LogicalResult
266   addToPipeline(OpPassManager &pm,
267                 function_ref<LogicalResult(const Twine &)> errorHandler) const;
268 
269 private:
270   std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
271 
272   llvm::cl::opt<std::string> passPipeline;
273   std::optional<llvm::cl::alias> passPipelineAlias;
274 };
275 
276 /// This class implements a command-line parser specifically for MLIR pass
277 /// names. It registers a cl option with a given argument and description that
278 /// accepts a comma delimited list of pass names.
279 class PassNameCLParser {
280 public:
281   /// Construct a parser with the given command line description.
282   PassNameCLParser(StringRef arg, StringRef description);
283   ~PassNameCLParser();
284 
285   /// Returns true if this parser contains any valid options to add.
286   bool hasAnyOccurrences() const;
287 
288   /// Returns true if the given pass registry entry was registered at the
289   /// top-level of the parser, i.e. not within an explicit textual pipeline.
290   bool contains(const PassRegistryEntry *entry) const;
291 
292 private:
293   std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
294 };
295 
296 //===----------------------------------------------------------------------===//
297 // Pass Reproducer
298 //===----------------------------------------------------------------------===//
299 
300 struct PassReproducerOptions {
301   /// Attach an assembly resource parser to 'config' that collects the MLIR
302   /// reproducer configuration into this instance.
303   void attachResourceParser(ParserConfig &config);
304 
305   /// Apply the reproducer options to 'pm' and its context.
306   LogicalResult apply(PassManager &pm) const;
307 
308 private:
309   std::optional<std::string> pipeline;
310   std::optional<bool> verifyEach;
311   std::optional<bool> disableThreading;
312 };
313 
314 } // namespace mlir
315 
316 #endif // MLIR_PASS_PASSREGISTRY_H_
317