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