//===- PassRegistry.h - Pass Registration Utilities -------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains utilities for registering information about compiler // passes. // //===----------------------------------------------------------------------===// #ifndef MLIR_PASS_PASSREGISTRY_H_ #define MLIR_PASS_PASSREGISTRY_H_ #include "mlir/Pass/PassOptions.h" #include "mlir/Support/TypeID.h" #include #include #include namespace mlir { class OpPassManager; class ParserConfig; class Pass; class PassManager; namespace detail { class PassOptions; } // namespace detail /// A registry function that adds passes to the given pass manager. This should /// also parse options and return success() if parsing succeeded. /// `errorHandler` is a functor used to emit errors during parsing. /// parameter corresponds to the raw location within the pipeline string. This /// should always return failure. using PassRegistryFunction = std::function errorHandler)>; using PassAllocatorFunction = std::function()>; //===----------------------------------------------------------------------===// // PassRegistry //===----------------------------------------------------------------------===// /// Prints the passes that were previously registered and stored in passRegistry void printRegisteredPasses(); /// Structure to group information about a passes and pass pipelines (argument /// to invoke via mlir-opt, description, pass pipeline builder). class PassRegistryEntry { public: /// Adds this pass registry entry to the given pass manager. `options` is /// an opaque string that will be parsed by the builder. The success of /// parsing will be returned. LogicalResult addToPipeline(OpPassManager &pm, StringRef options, function_ref errorHandler) const { assert(builder && "cannot call addToPipeline on PassRegistryEntry without builder"); return builder(pm, options, errorHandler); } /// Returns the command line option that may be passed to 'mlir-opt' that will /// cause this pass to run or null if there is no such argument. StringRef getPassArgument() const { return arg; } /// Returns a description for the pass, this never returns null. StringRef getPassDescription() const { return description; } /// Print the help information for this pass. This includes the argument, /// description, and any pass options. `descIndent` is the indent that the /// descriptions should be aligned. void printHelpStr(size_t indent, size_t descIndent) const; /// Return the maximum width required when printing the options of this entry. size_t getOptionWidth() const; protected: PassRegistryEntry( StringRef arg, StringRef description, const PassRegistryFunction &builder, std::function)> optHandler) : arg(arg), description(description), builder(builder), optHandler(std::move(optHandler)) {} private: /// The argument with which to invoke the pass via mlir-opt. std::string arg; /// Description of the pass. std::string description; /// Function to register this entry to a pass manager pipeline. PassRegistryFunction builder; /// Function to invoke a handler for a pass options instance. std::function)> optHandler; }; /// A structure to represent the information of a registered pass pipeline. class PassPipelineInfo : public PassRegistryEntry { public: PassPipelineInfo( StringRef arg, StringRef description, const PassRegistryFunction &builder, std::function)> optHandler) : PassRegistryEntry(arg, description, builder, std::move(optHandler)) {} /// Returns the pass pipeline info for the specified pass pipeline or null if /// unknown. static const PassPipelineInfo *lookup(StringRef pipelineArg); }; /// A structure to represent the information for a derived pass class. class PassInfo : public PassRegistryEntry { public: /// PassInfo constructor should not be invoked directly, instead use /// PassRegistration or registerPass. PassInfo(StringRef arg, StringRef description, const PassAllocatorFunction &allocator); /// Returns the pass info for the specified pass class or null if unknown. static const PassInfo *lookup(StringRef passArg); }; //===----------------------------------------------------------------------===// // PassRegistration //===----------------------------------------------------------------------===// /// Register a specific dialect pipeline registry function with the system, /// typically used through the PassPipelineRegistration template. void registerPassPipeline( StringRef arg, StringRef description, const PassRegistryFunction &function, std::function)> optHandler); /// Register a specific dialect pass allocator function with the system, /// typically used through the PassRegistration template. void registerPass(const PassAllocatorFunction &function); /// PassRegistration provides a global initializer that registers a Pass /// allocation routine for a concrete pass instance. The argument is /// optional and provides a callback to construct a pass that does not have /// a default constructor. /// /// Usage: /// /// /// At namespace scope. /// static PassRegistration reg; /// template struct PassRegistration { PassRegistration(const PassAllocatorFunction &constructor) { registerPass(constructor); } PassRegistration() : PassRegistration([] { return std::make_unique(); }) {} }; /// PassPipelineRegistration provides a global initializer that registers a Pass /// pipeline builder routine. /// /// Usage: /// /// // At namespace scope. /// void pipelineBuilder(OpPassManager &pm) { /// pm.addPass(new MyPass()); /// pm.addPass(new MyOtherPass()); /// } /// /// static PassPipelineRegistration Unused("unused", "Unused pass", /// pipelineBuilder); template struct PassPipelineRegistration { PassPipelineRegistration( StringRef arg, StringRef description, std::function builder) { registerPassPipeline( arg, description, [builder](OpPassManager &pm, StringRef optionsStr, function_ref errorHandler) { Options options; if (failed(options.parseFromString(optionsStr))) return failure(); builder(pm, options); return success(); }, [](function_ref optHandler) { optHandler(Options()); }); } }; /// Convenience specialization of PassPipelineRegistration for EmptyPassOptions /// that does not pass an empty options struct to the pass builder function. template <> struct PassPipelineRegistration { PassPipelineRegistration( StringRef arg, StringRef description, const std::function &builder) { registerPassPipeline( arg, description, [builder](OpPassManager &pm, StringRef optionsStr, function_ref errorHandler) { if (!optionsStr.empty()) return failure(); builder(pm); return success(); }, [](function_ref) {}); } }; /// Parse the textual representation of a pass pipeline, adding the result to /// 'pm' on success. Returns failure if the given pipeline was invalid. /// 'errorStream' is the output stream used to emit errors found during parsing. LogicalResult parsePassPipeline(StringRef pipeline, OpPassManager &pm, raw_ostream &errorStream = llvm::errs()); /// Parse the given textual representation of a pass pipeline, and return the /// parsed pipeline on success. The given pipeline string should be wrapped with /// the desired type of operation to root the created operation, i.e. /// `builtin.module(cse)` over `cse`. Returns failure if the given pipeline was /// invalid. 'errorStream' is the output stream used to emit errors found during /// parsing. FailureOr parsePassPipeline(StringRef pipeline, raw_ostream &errorStream = llvm::errs()); //===----------------------------------------------------------------------===// // PassPipelineCLParser //===----------------------------------------------------------------------===// namespace detail { struct PassPipelineCLParserImpl; } // namespace detail /// This class implements a command-line parser for MLIR passes. It registers a /// cl option with a given argument and description. This parser will register /// options for each of the passes and pipelines that have been registered with /// the pass registry; Meaning that `-cse` will refer to the CSE pass in MLIR. /// It also registers an argument, `pass-pipeline`, that supports parsing a /// textual description of a pipeline. This option is mutually exclusive with /// the individual pass options. class PassPipelineCLParser { public: /// Construct a pass pipeline parser with the given command line description. /// Optionally registers an alias for the `pass-pipeline` option. PassPipelineCLParser(StringRef arg, StringRef description); PassPipelineCLParser(StringRef arg, StringRef description, StringRef alias); ~PassPipelineCLParser(); /// Returns true if this parser contains any valid options to add. bool hasAnyOccurrences() const; /// Returns true if the given pass registry entry was registered at the /// top-level of the parser, i.e. not within an explicit textual pipeline. bool contains(const PassRegistryEntry *entry) const; /// Adds the passes defined by this parser entry to the given pass manager. /// Returns failure() if the pass could not be properly constructed due /// to options parsing. LogicalResult addToPipeline(OpPassManager &pm, function_ref errorHandler) const; private: std::unique_ptr impl; llvm::cl::opt passPipeline; std::optional passPipelineAlias; }; /// This class implements a command-line parser specifically for MLIR pass /// names. It registers a cl option with a given argument and description that /// accepts a comma delimited list of pass names. class PassNameCLParser { public: /// Construct a parser with the given command line description. PassNameCLParser(StringRef arg, StringRef description); ~PassNameCLParser(); /// Returns true if this parser contains any valid options to add. bool hasAnyOccurrences() const; /// Returns true if the given pass registry entry was registered at the /// top-level of the parser, i.e. not within an explicit textual pipeline. bool contains(const PassRegistryEntry *entry) const; private: std::unique_ptr impl; }; //===----------------------------------------------------------------------===// // Pass Reproducer //===----------------------------------------------------------------------===// struct PassReproducerOptions { /// Attach an assembly resource parser to 'config' that collects the MLIR /// reproducer configuration into this instance. void attachResourceParser(ParserConfig &config); /// Apply the reproducer options to 'pm' and its context. LogicalResult apply(PassManager &pm) const; private: std::optional pipeline; std::optional verifyEach; std::optional disableThreading; }; } // namespace mlir #endif // MLIR_PASS_PASSREGISTRY_H_