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

source code of mlir/include/mlir/Pass/PassRegistry.h