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