442 lines
16 KiB
C++
442 lines
16 KiB
C++
//===- MlirOptMain.h - MLIR Optimizer Driver main ---------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Main entry function for mlir-opt for when built as standalone binary.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_TOOLS_MLIROPT_MLIROPTMAIN_H
|
|
#define MLIR_TOOLS_MLIROPT_MLIROPTMAIN_H
|
|
|
|
#include "mlir/Debug/CLOptionsSetup.h"
|
|
#include "mlir/Support/ToolUtilities.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include <cstdlib>
|
|
#include <functional>
|
|
#include <memory>
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
class MemoryBuffer;
|
|
} // namespace llvm
|
|
|
|
namespace mlir {
|
|
class DialectRegistry;
|
|
class PassPipelineCLParser;
|
|
class PassManager;
|
|
|
|
/// enum class to indicate the verbosity level of the diagnostic filter.
|
|
enum class VerbosityLevel {
|
|
ErrorsOnly = 0,
|
|
ErrorsAndWarnings,
|
|
ErrorsWarningsAndRemarks
|
|
};
|
|
|
|
enum class RemarkFormat {
|
|
REMARK_FORMAT_STDOUT,
|
|
REMARK_FORMAT_YAML,
|
|
REMARK_FORMAT_BITSTREAM,
|
|
};
|
|
|
|
enum class RemarkPolicy {
|
|
REMARK_POLICY_ALL,
|
|
REMARK_POLICY_FINAL,
|
|
};
|
|
|
|
/// Configuration options for the mlir-opt tool.
|
|
/// This is intended to help building tools like mlir-opt by collecting the
|
|
/// supported options.
|
|
/// The API is fluent, and the options are sorted in alphabetical order below.
|
|
/// The options can be exposed to the LLVM command line by registering them
|
|
/// with `MlirOptMainConfig::registerCLOptions(DialectRegistry &);` and creating
|
|
/// a config using `auto config = MlirOptMainConfig::createFromCLOptions();`.
|
|
class MlirOptMainConfig {
|
|
public:
|
|
/// Register the options as global LLVM command line options.
|
|
static void registerCLOptions(DialectRegistry &dialectRegistry);
|
|
|
|
/// Create a new config with the default set from the CL options.
|
|
static MlirOptMainConfig createFromCLOptions();
|
|
|
|
///
|
|
/// Options.
|
|
///
|
|
|
|
/// Allow operation with no registered dialects.
|
|
/// This option is for convenience during testing only and discouraged in
|
|
/// general.
|
|
MlirOptMainConfig &allowUnregisteredDialects(bool allow) {
|
|
allowUnregisteredDialectsFlag = allow;
|
|
return *this;
|
|
}
|
|
bool shouldAllowUnregisteredDialects() const {
|
|
return allowUnregisteredDialectsFlag;
|
|
}
|
|
|
|
/// Set the debug configuration to use.
|
|
MlirOptMainConfig &setDebugConfig(tracing::DebugConfig config) {
|
|
debugConfig = std::move(config);
|
|
return *this;
|
|
}
|
|
tracing::DebugConfig &getDebugConfig() { return debugConfig; }
|
|
const tracing::DebugConfig &getDebugConfig() const { return debugConfig; }
|
|
|
|
/// Print the pass-pipeline as text before executing.
|
|
MlirOptMainConfig &dumpPassPipeline(bool dump) {
|
|
dumpPassPipelineFlag = dump;
|
|
return *this;
|
|
}
|
|
|
|
VerbosityLevel getDiagnosticVerbosityLevel() const {
|
|
return diagnosticVerbosityLevelFlag;
|
|
}
|
|
|
|
bool shouldDumpPassPipeline() const { return dumpPassPipelineFlag; }
|
|
|
|
/// Set the output format to bytecode instead of textual IR.
|
|
MlirOptMainConfig &emitBytecode(bool emit) {
|
|
emitBytecodeFlag = emit;
|
|
return *this;
|
|
}
|
|
bool shouldEmitBytecode() const { return emitBytecodeFlag; }
|
|
|
|
bool shouldElideResourceDataFromBytecode() const {
|
|
return elideResourceDataFromBytecodeFlag;
|
|
}
|
|
|
|
bool shouldShowNotes() const { return !disableDiagnosticNotesFlag; }
|
|
|
|
/// Set the IRDL file to load before processing the input.
|
|
MlirOptMainConfig &setIrdlFile(StringRef file) {
|
|
irdlFileFlag = file;
|
|
return *this;
|
|
}
|
|
StringRef getIrdlFile() const { return irdlFileFlag; }
|
|
|
|
/// Set the bytecode version to emit.
|
|
MlirOptMainConfig &setEmitBytecodeVersion(int64_t version) {
|
|
emitBytecodeVersion = version;
|
|
return *this;
|
|
}
|
|
std::optional<int64_t> bytecodeVersionToEmit() const {
|
|
return emitBytecodeVersion;
|
|
}
|
|
|
|
/// Set the bytecode producer to use.
|
|
MlirOptMainConfig &emitBytecodeProducer(StringRef producer) {
|
|
emitBytecodeProducerFlag = producer.str();
|
|
return *this;
|
|
}
|
|
std::optional<StringRef> bytecodeProducerToEmit() const {
|
|
if (emitBytecodeProducerFlag.empty())
|
|
return std::nullopt;
|
|
return emitBytecodeProducerFlag;
|
|
}
|
|
|
|
/// Set the callback to populate the pass manager.
|
|
MlirOptMainConfig &
|
|
setPassPipelineSetupFn(std::function<LogicalResult(PassManager &)> callback) {
|
|
passPipelineCallback = std::move(callback);
|
|
return *this;
|
|
}
|
|
|
|
/// Set the parser to use to populate the pass manager.
|
|
MlirOptMainConfig &setPassPipelineParser(const PassPipelineCLParser &parser);
|
|
|
|
/// Populate the passmanager, if any callback was set.
|
|
LogicalResult setupPassPipeline(PassManager &pm) const {
|
|
if (passPipelineCallback)
|
|
return passPipelineCallback(pm);
|
|
return success();
|
|
}
|
|
|
|
/// List the registered passes and return.
|
|
MlirOptMainConfig &listPasses(bool list) {
|
|
listPassesFlag = list;
|
|
return *this;
|
|
}
|
|
bool shouldListPasses() const { return listPassesFlag; }
|
|
|
|
/// Enable running the reproducer information stored in resources (if
|
|
/// present).
|
|
MlirOptMainConfig &runReproducer(bool enableReproducer) {
|
|
runReproducerFlag = enableReproducer;
|
|
return *this;
|
|
};
|
|
|
|
/// Return true if the reproducer should be run.
|
|
bool shouldRunReproducer() const { return runReproducerFlag; }
|
|
|
|
/// Show the registered dialects before trying to load the input file.
|
|
MlirOptMainConfig &showDialects(bool show) {
|
|
showDialectsFlag = show;
|
|
return *this;
|
|
}
|
|
bool shouldShowDialects() const { return showDialectsFlag; }
|
|
|
|
/// Set the marker on which to split the input into chunks and process each
|
|
/// chunk independently. Input is not split if empty.
|
|
MlirOptMainConfig &
|
|
splitInputFile(std::string splitMarker = kDefaultSplitMarker) {
|
|
splitInputFileFlag = std::move(splitMarker);
|
|
return *this;
|
|
}
|
|
StringRef inputSplitMarker() const { return splitInputFileFlag; }
|
|
|
|
/// Set whether to merge the output chunks into one file using the given
|
|
/// marker.
|
|
MlirOptMainConfig &
|
|
outputSplitMarker(std::string splitMarker = kDefaultSplitMarker) {
|
|
outputSplitMarkerFlag = std::move(splitMarker);
|
|
return *this;
|
|
}
|
|
StringRef outputSplitMarker() const { return outputSplitMarkerFlag; }
|
|
|
|
/// Disable implicit addition of a top-level module op during parsing.
|
|
MlirOptMainConfig &useExplicitModule(bool useExplicitModule) {
|
|
useExplicitModuleFlag = useExplicitModule;
|
|
return *this;
|
|
}
|
|
bool shouldUseExplicitModule() const { return useExplicitModuleFlag; }
|
|
|
|
/// Set whether to check that emitted diagnostics match `expected-*` lines on
|
|
/// the corresponding line. This is meant for implementing diagnostic tests.
|
|
MlirOptMainConfig &
|
|
verifyDiagnostics(SourceMgrDiagnosticVerifierHandler::Level verify) {
|
|
verifyDiagnosticsFlag = verify;
|
|
return *this;
|
|
}
|
|
|
|
bool shouldVerifyDiagnostics() const {
|
|
return verifyDiagnosticsFlag !=
|
|
SourceMgrDiagnosticVerifierHandler::Level::None;
|
|
}
|
|
|
|
SourceMgrDiagnosticVerifierHandler::Level verifyDiagnosticsLevel() const {
|
|
return verifyDiagnosticsFlag;
|
|
}
|
|
|
|
/// Set whether to run the verifier after each transformation pass.
|
|
MlirOptMainConfig &verifyPasses(bool verify) {
|
|
verifyPassesFlag = verify;
|
|
return *this;
|
|
}
|
|
bool shouldVerifyPasses() const { return verifyPassesFlag; }
|
|
|
|
/// Set whether to run the verifier on parsing.
|
|
MlirOptMainConfig &verifyOnParsing(bool verify) {
|
|
disableVerifierOnParsingFlag = !verify;
|
|
return *this;
|
|
}
|
|
bool shouldVerifyOnParsing() const { return !disableVerifierOnParsingFlag; }
|
|
|
|
/// Set whether to run the verifier after each transformation pass.
|
|
MlirOptMainConfig &verifyRoundtrip(bool verify) {
|
|
verifyRoundtripFlag = verify;
|
|
return *this;
|
|
}
|
|
bool shouldVerifyRoundtrip() const { return verifyRoundtripFlag; }
|
|
|
|
/// Checks if any remark filters are set.
|
|
bool shouldEmitRemarks() const {
|
|
// Emit all remarks only when no filters are specified.
|
|
const bool hasFilters =
|
|
!getRemarksAllFilter().empty() || !getRemarksPassedFilter().empty() ||
|
|
!getRemarksFailedFilter().empty() ||
|
|
!getRemarksMissedFilter().empty() || !getRemarksAnalyseFilter().empty();
|
|
return hasFilters;
|
|
}
|
|
|
|
/// Reproducer file generation (no crash required).
|
|
StringRef getReproducerFilename() const { return generateReproducerFileFlag; }
|
|
|
|
/// Set the reproducer output filename
|
|
RemarkFormat getRemarkFormat() const { return remarkFormatFlag; }
|
|
/// Set the remark policy to use.
|
|
RemarkPolicy getRemarkPolicy() const { return remarkPolicyFlag; }
|
|
/// Set the remark format to use.
|
|
std::string getRemarksAllFilter() const { return remarksAllFilterFlag; }
|
|
/// Set the remark output file.
|
|
std::string getRemarksOutputFile() const { return remarksOutputFileFlag; }
|
|
/// Set the remark passed filters.
|
|
std::string getRemarksPassedFilter() const { return remarksPassedFilterFlag; }
|
|
/// Set the remark failed filters.
|
|
std::string getRemarksFailedFilter() const { return remarksFailedFilterFlag; }
|
|
/// Set the remark missed filters.
|
|
std::string getRemarksMissedFilter() const { return remarksMissedFilterFlag; }
|
|
/// Set the remark analyse filters.
|
|
std::string getRemarksAnalyseFilter() const {
|
|
return remarksAnalyseFilterFlag;
|
|
}
|
|
|
|
protected:
|
|
/// Allow operation with no registered dialects.
|
|
/// This option is for convenience during testing only and discouraged in
|
|
/// general.
|
|
bool allowUnregisteredDialectsFlag = false;
|
|
|
|
/// Remark format
|
|
RemarkFormat remarkFormatFlag = RemarkFormat::REMARK_FORMAT_STDOUT;
|
|
/// Remark policy
|
|
RemarkPolicy remarkPolicyFlag = RemarkPolicy::REMARK_POLICY_ALL;
|
|
/// Remark file to output to
|
|
std::string remarksOutputFileFlag = "";
|
|
/// Remark filters
|
|
std::string remarksAllFilterFlag = "";
|
|
std::string remarksPassedFilterFlag = "";
|
|
std::string remarksFailedFilterFlag = "";
|
|
std::string remarksMissedFilterFlag = "";
|
|
std::string remarksAnalyseFilterFlag = "";
|
|
|
|
/// Configuration for the debugging hooks.
|
|
tracing::DebugConfig debugConfig;
|
|
|
|
/// Verbosity level of diagnostic information. 0: Errors only,
|
|
/// 1: Errors and warnings, 2: Errors, warnings and remarks.
|
|
VerbosityLevel diagnosticVerbosityLevelFlag =
|
|
VerbosityLevel::ErrorsWarningsAndRemarks;
|
|
|
|
/// Print the pipeline that will be run.
|
|
bool dumpPassPipelineFlag = false;
|
|
|
|
/// Emit bytecode instead of textual assembly when generating output.
|
|
bool emitBytecodeFlag = false;
|
|
|
|
/// Elide resources when generating bytecode.
|
|
bool elideResourceDataFromBytecodeFlag = false;
|
|
|
|
/// IRDL file to register before processing the input.
|
|
std::string irdlFileFlag = "";
|
|
|
|
/// Location Breakpoints to filter the action logging.
|
|
std::vector<tracing::BreakpointManager *> logActionLocationFilter;
|
|
|
|
/// Emit bytecode at given version.
|
|
std::optional<int64_t> emitBytecodeVersion = std::nullopt;
|
|
|
|
/// Emit bytecode with given producer.
|
|
std::string emitBytecodeProducerFlag = "";
|
|
|
|
/// The callback to populate the pass manager.
|
|
std::function<LogicalResult(PassManager &)> passPipelineCallback;
|
|
|
|
/// List the registered passes and return.
|
|
bool listPassesFlag = false;
|
|
|
|
/// Enable running the reproducer.
|
|
bool runReproducerFlag = false;
|
|
|
|
/// Show the registered dialects before trying to load the input file.
|
|
bool showDialectsFlag = false;
|
|
|
|
/// Show the notes in diagnostic information. Notes can be included in
|
|
/// any diagnostic information, so it is not specified in the verbosity
|
|
/// level.
|
|
bool disableDiagnosticNotesFlag = true;
|
|
|
|
/// Split the input file based on the given marker into chunks and process
|
|
/// each chunk independently. Input is not split if empty.
|
|
std::string splitInputFileFlag = "";
|
|
|
|
/// Merge output chunks into one file using the given marker.
|
|
std::string outputSplitMarkerFlag = "";
|
|
|
|
/// Use an explicit top-level module op during parsing.
|
|
bool useExplicitModuleFlag = false;
|
|
|
|
/// Set whether to check that emitted diagnostics match `expected-*` lines on
|
|
/// the corresponding line. This is meant for implementing diagnostic tests.
|
|
SourceMgrDiagnosticVerifierHandler::Level verifyDiagnosticsFlag =
|
|
SourceMgrDiagnosticVerifierHandler::Level::None;
|
|
|
|
/// Run the verifier after each transformation pass.
|
|
bool verifyPassesFlag = true;
|
|
|
|
/// Disable the verifier on parsing.
|
|
bool disableVerifierOnParsingFlag = false;
|
|
|
|
/// Verify that the input IR round-trips perfectly.
|
|
bool verifyRoundtripFlag = false;
|
|
|
|
/// The reproducer output filename (no crash required).
|
|
std::string generateReproducerFileFlag = "";
|
|
};
|
|
|
|
/// This defines the function type used to setup the pass manager. This can be
|
|
/// used to pass in a callback to setup a default pass pipeline to be applied on
|
|
/// the loaded IR.
|
|
using PassPipelineFn = llvm::function_ref<LogicalResult(PassManager &pm)>;
|
|
|
|
/// Register basic command line options.
|
|
/// - toolName is used for the header displayed by `--help`.
|
|
/// - registry should contain all the dialects that can be parsed in the source.
|
|
/// - return std::string for help header.
|
|
std::string registerCLIOptions(llvm::StringRef toolName,
|
|
DialectRegistry ®istry);
|
|
|
|
/// Parse command line options.
|
|
/// - helpHeader is used for the header displayed by `--help`.
|
|
/// - return std::pair<std::string, std::string> for
|
|
/// inputFilename and outputFilename command line option values.
|
|
std::pair<std::string, std::string> parseCLIOptions(int argc, char **argv,
|
|
llvm::StringRef helpHeader);
|
|
|
|
/// Register and parse command line options.
|
|
/// - toolName is used for the header displayed by `--help`.
|
|
/// - registry should contain all the dialects that can be parsed in the source.
|
|
/// - return std::pair<std::string, std::string> for
|
|
/// inputFilename and outputFilename command line option values.
|
|
std::pair<std::string, std::string>
|
|
registerAndParseCLIOptions(int argc, char **argv, llvm::StringRef toolName,
|
|
DialectRegistry ®istry);
|
|
|
|
/// Perform the core processing behind `mlir-opt`.
|
|
/// - outputStream is the stream where the resulting IR is printed.
|
|
/// - buffer is the in-memory file to parser and process.
|
|
/// - registry should contain all the dialects that can be parsed in the source.
|
|
/// - config contains the configuration options for the tool.
|
|
LogicalResult MlirOptMain(llvm::raw_ostream &outputStream,
|
|
std::unique_ptr<llvm::MemoryBuffer> buffer,
|
|
DialectRegistry ®istry,
|
|
const MlirOptMainConfig &config);
|
|
|
|
/// Implementation for tools like `mlir-opt`.
|
|
/// - toolName is used for the header displayed by `--help`.
|
|
/// - registry should contain all the dialects that can be parsed in the source.
|
|
LogicalResult MlirOptMain(int argc, char **argv, llvm::StringRef toolName,
|
|
DialectRegistry ®istry);
|
|
|
|
/// Implementation for tools like `mlir-opt`.
|
|
/// This function can be used with registerAndParseCLIOptions so that
|
|
/// CLI options can be accessed before running MlirOptMain.
|
|
/// - inputFilename is the name of the input mlir file.
|
|
/// - outputFilename is the name of the output file.
|
|
/// - registry should contain all the dialects that can be parsed in the source.
|
|
LogicalResult MlirOptMain(int argc, char **argv, llvm::StringRef inputFilename,
|
|
llvm::StringRef outputFilename,
|
|
DialectRegistry ®istry);
|
|
|
|
/// Helper wrapper to return the result of MlirOptMain directly from main.
|
|
///
|
|
/// Example:
|
|
///
|
|
/// int main(int argc, char **argv) {
|
|
/// // ...
|
|
/// return mlir::asMainReturnCode(mlir::MlirOptMain(
|
|
/// argc, argv, /* ... */);
|
|
/// }
|
|
///
|
|
inline int asMainReturnCode(LogicalResult r) {
|
|
return r.succeeded() ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|
|
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_TOOLS_MLIROPT_MLIROPTMAIN_H
|