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