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