mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Implement Pass and Dialect plugins for mlir-opt
Implementation of Pass and Dialect Plugins that mirrors LLVM Pass Plugin implementation from the new pass manager. Currently the implementation only supports using the pass-pipeline option for adding passes. This restriction is imposed by the `PassPipelineCLParser` variable in mlir/lib/Tools/mlir-opt/MlirOptMain.cpp:114 that loads the parse options statically before parsing the cmd line args. ``` mlir-opt stanalone-plugin.mlir --load-dialect-plugin=lib/libStandalonePlugin.so --pass-pipeline="builtin.module(standalone-switch-bar-foo)" ``` Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D147053
This commit is contained in:
committed by
Jacques Pienaar
parent
77313ddfb2
commit
d4c873b044
@@ -52,4 +52,5 @@ if(MLIR_ENABLE_BINDINGS_PYTHON)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(standalone-opt)
|
||||
add_subdirectory(standalone-plugin)
|
||||
add_subdirectory(standalone-translate)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
add_mlir_dialect(StandaloneOps standalone)
|
||||
add_mlir_doc(StandaloneDialect StandaloneDialect Standalone/ -gen-dialect-doc)
|
||||
add_mlir_doc(StandaloneOps StandaloneOps Standalone/ -gen-op-doc)
|
||||
|
||||
set(LLVM_TARGET_DEFINITIONS StandalonePasses.td)
|
||||
mlir_tablegen(StandalonePasses.h.inc --gen-pass-decls)
|
||||
add_public_tablegen_target(MLIRStandalonePassesIncGen)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//===- StandalonePasses.h - Standalone passes ------------------*- C++ -*-===//
|
||||
//
|
||||
// This file is licensed 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef STANDALONE_STANDALONEPASSES_H
|
||||
#define STANDALONE_STANDALONEPASSES_H
|
||||
|
||||
#include "Standalone/StandaloneDialect.h"
|
||||
#include "Standalone/StandaloneOps.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include <memory>
|
||||
|
||||
namespace mlir {
|
||||
namespace standalone {
|
||||
#define GEN_PASS_DECL
|
||||
#include "Standalone/StandalonePasses.h.inc"
|
||||
|
||||
#define GEN_PASS_REGISTRATION
|
||||
#include "Standalone/StandalonePasses.h.inc"
|
||||
} // namespace standalone
|
||||
} // namespace mlir
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
//===- StandalonePsss.td - Standalone dialect passes -------*- tablegen -*-===//
|
||||
//
|
||||
// This file is licensed 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef STANDALONE_PASS
|
||||
#define STANDALONE_PASS
|
||||
|
||||
include "mlir/Pass/PassBase.td"
|
||||
|
||||
def StandaloneSwitchBarFoo: Pass<"standalone-switch-bar-foo", "::mlir::ModuleOp"> {
|
||||
let summary = "Switches the name of a FuncOp named `bar` to `foo` and folds.";
|
||||
let description = [{
|
||||
Switches the name of a FuncOp named `bar` to `foo` and folds.
|
||||
```
|
||||
func.func @bar() {
|
||||
return
|
||||
}
|
||||
// Gets transformed to:
|
||||
func.func @foo() {
|
||||
return
|
||||
}
|
||||
```
|
||||
}];
|
||||
}
|
||||
|
||||
#endif // STANDALONE_PASS
|
||||
@@ -2,14 +2,17 @@ add_mlir_dialect_library(MLIRStandalone
|
||||
StandaloneTypes.cpp
|
||||
StandaloneDialect.cpp
|
||||
StandaloneOps.cpp
|
||||
StandalonePasses.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${PROJECT_SOURCE_DIR}/include/Standalone
|
||||
|
||||
DEPENDS
|
||||
MLIRStandaloneOpsIncGen
|
||||
MLIRStandalonePassesIncGen
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRIR
|
||||
MLIRInferTypeOpInterface
|
||||
MLIRFuncDialect
|
||||
)
|
||||
|
||||
48
mlir/examples/standalone/lib/Standalone/StandalonePasses.cpp
Normal file
48
mlir/examples/standalone/lib/Standalone/StandalonePasses.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//===- StandalonePasses.cpp - Standalone passes -----------------*- C++ -*-===//
|
||||
//
|
||||
// This file is licensed 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mlir/Dialect/Func/IR/FuncOps.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/PatternMatch.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
|
||||
|
||||
#include "Standalone/StandalonePasses.h"
|
||||
|
||||
namespace mlir::standalone {
|
||||
#define GEN_PASS_DEF_STANDALONESWITCHBARFOO
|
||||
#include "Standalone/StandalonePasses.h.inc"
|
||||
|
||||
namespace {
|
||||
class StandaloneSwitchBarFooRewriter : public OpRewritePattern<func::FuncOp> {
|
||||
public:
|
||||
using OpRewritePattern<func::FuncOp>::OpRewritePattern;
|
||||
LogicalResult matchAndRewrite(func::FuncOp op,
|
||||
PatternRewriter &rewriter) const final {
|
||||
if (op.getSymName() == "bar") {
|
||||
rewriter.updateRootInPlace(op, [&op]() { op.setSymName("foo"); });
|
||||
return success();
|
||||
}
|
||||
return failure();
|
||||
}
|
||||
};
|
||||
|
||||
class StandaloneSwitchBarFoo
|
||||
: public impl::StandaloneSwitchBarFooBase<StandaloneSwitchBarFoo> {
|
||||
public:
|
||||
using impl::StandaloneSwitchBarFooBase<
|
||||
StandaloneSwitchBarFoo>::StandaloneSwitchBarFooBase;
|
||||
void runOnOperation() final {
|
||||
RewritePatternSet patterns(&getContext());
|
||||
patterns.add<StandaloneSwitchBarFooRewriter>(&getContext());
|
||||
FrozenRewritePatternSet patternSet(std::move(patterns));
|
||||
if (failed(applyPatternsAndFoldGreedily(getOperation(), patternSet)))
|
||||
signalPassFailure();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
} // namespace mlir::standalone
|
||||
@@ -21,9 +21,11 @@
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
|
||||
#include "Standalone/StandaloneDialect.h"
|
||||
#include "Standalone/StandalonePasses.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
mlir::registerAllPasses();
|
||||
mlir::standalone::registerPasses();
|
||||
// TODO: Register standalone passes here.
|
||||
|
||||
mlir::DialectRegistry registry;
|
||||
|
||||
21
mlir/examples/standalone/standalone-plugin/CMakeLists.txt
Normal file
21
mlir/examples/standalone/standalone-plugin/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
|
||||
get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
|
||||
set(LIBS
|
||||
MLIRIR
|
||||
MLIRPass
|
||||
MLIRStandalone
|
||||
MLIRTransformUtils
|
||||
)
|
||||
|
||||
add_mlir_dialect_library(StandalonePlugin
|
||||
SHARED
|
||||
standalone-plugin.cpp
|
||||
|
||||
DEPENDS
|
||||
MLIRStandalone
|
||||
)
|
||||
|
||||
llvm_update_compile_flags(StandalonePlugin)
|
||||
target_link_libraries(StandalonePlugin PRIVATE ${LIBS})
|
||||
|
||||
mlir_check_all_link_libraries(StandalonePlugin)
|
||||
@@ -0,0 +1,39 @@
|
||||
//===- standalone-plugin.cpp ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This file is licensed 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Dialect/Arith/IR/Arith.h"
|
||||
#include "mlir/IR/Dialect.h"
|
||||
#include "mlir/IR/DialectPlugin.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/InitAllDialects.h"
|
||||
#include "mlir/InitAllPasses.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
|
||||
#include "Standalone/StandaloneDialect.h"
|
||||
#include "Standalone/StandalonePasses.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
/// Dialect plugin registration mechanism.
|
||||
/// Observe that it also allows to register passes.
|
||||
/// Necessary symbol to register the dialect plugin.
|
||||
extern "C" LLVM_ATTRIBUTE_WEAK DialectPluginLibraryInfo
|
||||
mlirGetDialectPluginInfo() {
|
||||
return {MLIR_PLUGIN_API_VERSION, "Standalone", LLVM_VERSION_STRING,
|
||||
[](DialectRegistry *registry) {
|
||||
registry->insert<mlir::standalone::StandaloneDialect>();
|
||||
mlir::standalone::registerPasses();
|
||||
}};
|
||||
}
|
||||
|
||||
/// Pass plugin registration mechanism.
|
||||
/// Necessary symbol to register the pass plugin.
|
||||
extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo mlirGetPassPluginInfo() {
|
||||
return {MLIR_PLUGIN_API_VERSION, "StandalonePasses", LLVM_VERSION_STRING,
|
||||
[]() { mlir::standalone::registerPasses(); }};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// RUN: mlir-opt %s --load-pass-plugin=%standalone_libs/libStandalonePlugin.so --pass-pipeline="builtin.module(standalone-switch-bar-foo)" | FileCheck %s
|
||||
|
||||
module {
|
||||
// CHECK-LABEL: func @foo()
|
||||
func.func @bar() {
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @abar()
|
||||
func.func @abar() {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// RUN: mlir-opt %s --load-dialect-plugin=%standalone_libs/libStandalonePlugin.so --pass-pipeline="builtin.module(standalone-switch-bar-foo)" | FileCheck %s
|
||||
|
||||
module {
|
||||
// CHECK-LABEL: func @foo()
|
||||
func.func @bar() {
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @standalone_types(%arg0: !standalone.custom<"10">)
|
||||
func.func @standalone_types(%arg0: !standalone.custom<"10">) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -44,12 +44,16 @@ config.excludes = ['Inputs', 'Examples', 'CMakeLists.txt', 'README.txt', 'LICENS
|
||||
# test_exec_root: The root path where tests should be run.
|
||||
config.test_exec_root = os.path.join(config.standalone_obj_root, 'test')
|
||||
config.standalone_tools_dir = os.path.join(config.standalone_obj_root, 'bin')
|
||||
config.standalone_libs_dir = os.path.join(config.standalone_obj_root, 'lib')
|
||||
|
||||
config.substitutions.append(('%standalone_libs', config.standalone_libs_dir))
|
||||
|
||||
# Tweak the PATH to include the tools dir.
|
||||
llvm_config.with_environment('PATH', config.llvm_tools_dir, append_path=True)
|
||||
|
||||
tool_dirs = [config.standalone_tools_dir, config.llvm_tools_dir]
|
||||
tools = [
|
||||
'mlir-opt',
|
||||
'standalone-capi-test',
|
||||
'standalone-opt',
|
||||
'standalone-translate',
|
||||
|
||||
106
mlir/include/mlir/IR/DialectPlugin.h
Normal file
106
mlir/include/mlir/IR/DialectPlugin.h
Normal file
@@ -0,0 +1,106 @@
|
||||
//===- mlir/IR/DialectPlugin.h - Public Plugin API -----------------------===//
|
||||
//
|
||||
// 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 defines the public entry point for dialect plugins.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_IR_DIALECTPLUGIN_H
|
||||
#define MLIR_IR_DIALECTPLUGIN_H
|
||||
|
||||
#include "mlir/IR/DialectRegistry.h"
|
||||
#include "mlir/Pass/PassPlugin.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace mlir {
|
||||
extern "C" {
|
||||
/// Information about the plugin required to load its dialects & passes
|
||||
///
|
||||
/// This struct defines the core interface for dialect plugins and is supposed
|
||||
/// to be filled out by plugin implementors. MLIR-side users of a plugin are
|
||||
/// expected to use the \c DialectPlugin class below to interface with it.
|
||||
struct DialectPluginLibraryInfo {
|
||||
/// The API version understood by this plugin, usually
|
||||
/// \c MLIR_PLUGIN_API_VERSION
|
||||
uint32_t apiVersion;
|
||||
/// A meaningful name of the plugin.
|
||||
const char *pluginName;
|
||||
/// The version of the plugin.
|
||||
const char *pluginVersion;
|
||||
|
||||
/// The callback for registering dialect plugin with a \c DialectRegistry
|
||||
/// instance
|
||||
void (*registerDialectRegistryCallbacks)(DialectRegistry *);
|
||||
};
|
||||
}
|
||||
|
||||
/// A loaded dialect plugin.
|
||||
///
|
||||
/// An instance of this class wraps a loaded dialect plugin and gives access to
|
||||
/// its interface defined by the \c DialectPluginLibraryInfo it exposes.
|
||||
class DialectPlugin {
|
||||
public:
|
||||
/// Attempts to load a dialect plugin from a given file.
|
||||
///
|
||||
/// \returns Returns an error if either the library cannot be found or loaded,
|
||||
/// there is no public entry point, or the plugin implements the wrong API
|
||||
/// version.
|
||||
static llvm::Expected<DialectPlugin> load(const std::string &filename);
|
||||
|
||||
/// Get the filename of the loaded plugin.
|
||||
StringRef getFilename() const { return filename; }
|
||||
|
||||
/// Get the plugin name
|
||||
StringRef getPluginName() const { return info.pluginName; }
|
||||
|
||||
/// Get the plugin version
|
||||
StringRef getPluginVersion() const { return info.pluginVersion; }
|
||||
|
||||
/// Get the plugin API version
|
||||
uint32_t getAPIVersion() const { return info.apiVersion; }
|
||||
|
||||
/// Invoke the DialectRegistry callback registration
|
||||
void
|
||||
registerDialectRegistryCallbacks(DialectRegistry &dialectRegistry) const {
|
||||
info.registerDialectRegistryCallbacks(&dialectRegistry);
|
||||
}
|
||||
|
||||
private:
|
||||
DialectPlugin(const std::string &filename,
|
||||
const llvm::sys::DynamicLibrary &library)
|
||||
: filename(filename), library(library), info() {}
|
||||
|
||||
std::string filename;
|
||||
llvm::sys::DynamicLibrary library;
|
||||
DialectPluginLibraryInfo info;
|
||||
};
|
||||
} // namespace mlir
|
||||
|
||||
/// The public entry point for a dialect plugin.
|
||||
///
|
||||
/// When a plugin is loaded by the driver, it will call this entry point to
|
||||
/// obtain information about this plugin and about how to register its dialects.
|
||||
/// This function needs to be implemented by the plugin, see the example below:
|
||||
///
|
||||
/// ```
|
||||
/// extern "C" ::mlir::DialectPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
/// mlirGetDialectPluginInfo() {
|
||||
/// return {
|
||||
/// MLIR_PLUGIN_API_VERSION, "MyPlugin", "v0.1", [](DialectRegistry) { ... }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
extern "C" ::mlir::DialectPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
mlirGetDialectPluginInfo();
|
||||
|
||||
#endif /* MLIR_IR_DIALECTPLUGIN_H */
|
||||
112
mlir/include/mlir/Pass/PassPlugin.h
Normal file
112
mlir/include/mlir/Pass/PassPlugin.h
Normal file
@@ -0,0 +1,112 @@
|
||||
//===- mlir/Pass/PassPlugin.h - Public Plugin API -----------------------===//
|
||||
//
|
||||
// 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 defines the public entry point for pass plugins.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_PASSES_PASSPLUGIN_H
|
||||
#define MLIR_PASSES_PASSPLUGIN_H
|
||||
|
||||
#include "mlir/Support/LLVM.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace mlir {
|
||||
/// \macro MLIR_PLUGIN_API_VERSION
|
||||
/// Identifies the API version understood by this plugin.
|
||||
///
|
||||
/// When a plugin is loaded, the driver will check it's supported plugin version
|
||||
/// against that of the plugin. A mismatch is an error. The supported version
|
||||
/// will be incremented for ABI-breaking changes to the \c PassPluginLibraryInfo
|
||||
/// struct, i.e. when callbacks are added, removed, or reordered.
|
||||
#define MLIR_PLUGIN_API_VERSION 1
|
||||
|
||||
extern "C" {
|
||||
/// Information about the plugin required to load its passes
|
||||
///
|
||||
/// This struct defines the core interface for pass plugins and is supposed to
|
||||
/// be filled out by plugin implementors. LLVM-side users of a plugin are
|
||||
/// expected to use the \c PassPlugin class below to interface with it.
|
||||
struct PassPluginLibraryInfo {
|
||||
/// The API version understood by this plugin, usually \c
|
||||
/// MLIR_PLUGIN_API_VERSION
|
||||
uint32_t apiVersion;
|
||||
/// A meaningful name of the plugin.
|
||||
const char *pluginName;
|
||||
/// The version of the plugin.
|
||||
const char *pluginVersion;
|
||||
|
||||
/// The callback for registering plugin passes.
|
||||
void (*registerPassRegistryCallbacks)();
|
||||
};
|
||||
}
|
||||
|
||||
/// A loaded pass plugin.
|
||||
///
|
||||
/// An instance of this class wraps a loaded pass plugin and gives access to
|
||||
/// its interface defined by the \c PassPluginLibraryInfo it exposes.
|
||||
class PassPlugin {
|
||||
public:
|
||||
/// Attempts to load a pass plugin from a given file.
|
||||
///
|
||||
/// \returns Returns an error if either the library cannot be found or loaded,
|
||||
/// there is no public entry point, or the plugin implements the wrong API
|
||||
/// version.
|
||||
static llvm::Expected<PassPlugin> load(const std::string &filename);
|
||||
|
||||
/// Get the filename of the loaded plugin.
|
||||
StringRef getFilename() const { return filename; }
|
||||
|
||||
/// Get the plugin name
|
||||
StringRef getPluginName() const { return info.pluginName; }
|
||||
|
||||
/// Get the plugin version
|
||||
StringRef getPluginVersion() const { return info.pluginVersion; }
|
||||
|
||||
/// Get the plugin API version
|
||||
uint32_t getAPIVersion() const { return info.apiVersion; }
|
||||
|
||||
/// Invoke the PassRegistry callback registration
|
||||
void registerPassRegistryCallbacks() const {
|
||||
info.registerPassRegistryCallbacks();
|
||||
}
|
||||
|
||||
private:
|
||||
PassPlugin(const std::string &filename,
|
||||
const llvm::sys::DynamicLibrary &library)
|
||||
: filename(filename), library(library), info() {}
|
||||
|
||||
std::string filename;
|
||||
llvm::sys::DynamicLibrary library;
|
||||
PassPluginLibraryInfo info;
|
||||
};
|
||||
} // namespace mlir
|
||||
|
||||
/// The public entry point for a pass plugin.
|
||||
///
|
||||
/// When a plugin is loaded by the driver, it will call this entry point to
|
||||
/// obtain information about this plugin and about how to register its passes.
|
||||
/// This function needs to be implemented by the plugin, see the example below:
|
||||
///
|
||||
/// ```
|
||||
/// extern "C" ::mlir::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
/// mlirGetPassPluginInfo() {
|
||||
/// return {
|
||||
/// MLIR_PLUGIN_API_VERSION, "MyPlugin", "v0.1", []() { ... }
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
extern "C" ::mlir::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
|
||||
mlirGetPassPluginInfo();
|
||||
|
||||
#endif /* MLIR_PASS_PASSPLUGIN_H */
|
||||
@@ -35,12 +35,12 @@ class PassManager;
|
||||
/// 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();` and creating a config using
|
||||
/// `auto config = MlirOptMainConfig::createFromCLOptions();`.
|
||||
/// 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();
|
||||
static void registerCLOptions(DialectRegistry &dialectRegistry);
|
||||
|
||||
/// Create a new config with the default set from the CL options.
|
||||
static MlirOptMainConfig createFromCLOptions();
|
||||
|
||||
@@ -14,6 +14,7 @@ add_mlir_library(MLIRIR
|
||||
BuiltinTypeInterfaces.cpp
|
||||
Diagnostics.cpp
|
||||
Dialect.cpp
|
||||
DialectPlugin.cpp
|
||||
DialectResourceBlobManager.cpp
|
||||
Dominance.cpp
|
||||
ExtensibleDialect.cpp
|
||||
|
||||
53
mlir/lib/IR/DialectPlugin.cpp
Normal file
53
mlir/lib/IR/DialectPlugin.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//===- lib/IR/DialectPlugin.cpp - Load Dialect Plugins --------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/IR/DialectPlugin.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
llvm::Expected<DialectPlugin> DialectPlugin::load(const std::string &filename) {
|
||||
std::string error;
|
||||
auto library =
|
||||
llvm::sys::DynamicLibrary::getPermanentLibrary(filename.c_str(), &error);
|
||||
if (!library.isValid())
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Could not load library '") + filename + "': " + error,
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
DialectPlugin plugin{filename, library};
|
||||
|
||||
// mlirGetDialectPluginInfo should be resolved to the definition from the
|
||||
// plugin we are currently loading.
|
||||
intptr_t getDetailsFn =
|
||||
(intptr_t)library.getAddressOfSymbol("mlirGetDialectPluginInfo");
|
||||
|
||||
if (!getDetailsFn)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Plugin entry point not found in '") + filename,
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
plugin.info =
|
||||
reinterpret_cast<decltype(mlirGetDialectPluginInfo) *>(getDetailsFn)();
|
||||
|
||||
if (plugin.info.apiVersion != MLIR_PLUGIN_API_VERSION)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Wrong API version on plugin '") + filename + "'. Got version " +
|
||||
Twine(plugin.info.apiVersion) + ", supported version is " +
|
||||
Twine(MLIR_PLUGIN_API_VERSION) + ".",
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
if (!plugin.info.registerDialectRegistryCallbacks)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Empty entry callback in plugin '") + filename + "'.'",
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
return plugin;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ add_mlir_library(MLIRPass
|
||||
Pass.cpp
|
||||
PassCrashRecovery.cpp
|
||||
PassManagerOptions.cpp
|
||||
PassPlugin.cpp
|
||||
PassRegistry.cpp
|
||||
PassStatistics.cpp
|
||||
PassTiming.cpp
|
||||
|
||||
53
mlir/lib/Pass/PassPlugin.cpp
Normal file
53
mlir/lib/Pass/PassPlugin.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//===- lib/Passes/PassPlugin.cpp - Load Plugins for PR Passes ---===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Pass/PassPlugin.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
llvm::Expected<PassPlugin> PassPlugin::load(const std::string &filename) {
|
||||
std::string Error;
|
||||
auto library =
|
||||
llvm::sys::DynamicLibrary::getPermanentLibrary(filename.c_str(), &Error);
|
||||
if (!library.isValid())
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Could not load library '") + filename + "': " + Error,
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
PassPlugin plugin{filename, library};
|
||||
|
||||
// mlirGetPassPluginInfo should be resolved to the definition from the plugin
|
||||
// we are currently loading.
|
||||
intptr_t getDetailsFn =
|
||||
(intptr_t)library.getAddressOfSymbol("mlirGetPassPluginInfo");
|
||||
|
||||
if (!getDetailsFn)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Plugin entry point not found in '") + filename,
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
plugin.info =
|
||||
reinterpret_cast<decltype(mlirGetPassPluginInfo) *>(getDetailsFn)();
|
||||
|
||||
if (plugin.info.apiVersion != MLIR_PLUGIN_API_VERSION)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Wrong API version on plugin '") + filename + "'. Got version " +
|
||||
Twine(plugin.info.apiVersion) + ", supported version is " +
|
||||
Twine(MLIR_PLUGIN_API_VERSION) + ".",
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
if (!plugin.info.registerPassRegistryCallbacks)
|
||||
return llvm::make_error<llvm::StringError>(
|
||||
Twine("Empty entry callback in plugin '") + filename + "'.'",
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
return plugin;
|
||||
}
|
||||
@@ -21,11 +21,13 @@
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Diagnostics.h"
|
||||
#include "mlir/IR/Dialect.h"
|
||||
#include "mlir/IR/DialectPlugin.h"
|
||||
#include "mlir/IR/Location.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "mlir/Parser/Parser.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Pass/PassPlugin.h"
|
||||
#include "mlir/Support/FileUtilities.h"
|
||||
#include "mlir/Support/Timing.h"
|
||||
#include "mlir/Support/ToolUtilities.h"
|
||||
@@ -101,15 +103,41 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
|
||||
cl::desc("Run the verifier after each transformation pass"),
|
||||
cl::location(verifyPassesFlag), cl::init(true));
|
||||
|
||||
static cl::list<std::string> passPlugins(
|
||||
"load-pass-plugin", cl::desc("Load passes from plugin library"));
|
||||
/// Set the callback to load a pass plugin.
|
||||
passPlugins.setCallback([&](const std::string &pluginPath) {
|
||||
auto plugin = PassPlugin::load(pluginPath);
|
||||
if (!plugin) {
|
||||
errs() << "Failed to load passes from '" << pluginPath
|
||||
<< "'. Request ignored.\n";
|
||||
return;
|
||||
}
|
||||
plugin.get().registerPassRegistryCallbacks();
|
||||
});
|
||||
|
||||
static cl::list<std::string> dialectPlugins(
|
||||
"load-dialect-plugin", cl::desc("Load dialects from plugin library"));
|
||||
this->dialectPlugins = std::addressof(dialectPlugins);
|
||||
|
||||
static PassPipelineCLParser passPipeline("", "Compiler passes to run", "p");
|
||||
setPassPipelineParser(passPipeline);
|
||||
}
|
||||
|
||||
/// Set the callback to load a dialect plugin.
|
||||
void setDialectPluginsCallback(DialectRegistry ®istry);
|
||||
|
||||
/// Pointer to static dialectPlugins variable in constructor, needed by
|
||||
/// setDialectPluginsCallback(DialectRegistry&).
|
||||
cl::list<std::string> *dialectPlugins = nullptr;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ManagedStatic<MlirOptMainConfigCLOptions> clOptionsConfig;
|
||||
|
||||
void MlirOptMainConfig::registerCLOptions() { *clOptionsConfig; }
|
||||
void MlirOptMainConfig::registerCLOptions(DialectRegistry ®istry) {
|
||||
clOptionsConfig->setDialectPluginsCallback(registry);
|
||||
}
|
||||
|
||||
MlirOptMainConfig MlirOptMainConfig::createFromCLOptions() {
|
||||
return *clOptionsConfig;
|
||||
@@ -134,6 +162,19 @@ MlirOptMainConfig &MlirOptMainConfig::setPassPipelineParser(
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MlirOptMainConfigCLOptions::setDialectPluginsCallback(
|
||||
DialectRegistry ®istry) {
|
||||
dialectPlugins->setCallback([&](const std::string &pluginPath) {
|
||||
auto plugin = DialectPlugin::load(pluginPath);
|
||||
if (!plugin) {
|
||||
errs() << "Failed to load dialect plugin from '" << pluginPath
|
||||
<< "'. Request ignored.\n";
|
||||
return;
|
||||
};
|
||||
plugin.get().registerDialectRegistryCallbacks(registry);
|
||||
});
|
||||
}
|
||||
|
||||
/// Set the ExecutionContext on the context and handle the observers.
|
||||
class InstallDebugHandler {
|
||||
public:
|
||||
@@ -365,7 +406,7 @@ LogicalResult mlir::MlirOptMain(int argc, char **argv, llvm::StringRef toolName,
|
||||
InitLLVM y(argc, argv);
|
||||
|
||||
// Register any command line options.
|
||||
MlirOptMainConfig::registerCLOptions();
|
||||
MlirOptMainConfig::registerCLOptions(registry);
|
||||
registerAsmPrinterCLOptions();
|
||||
registerMLIRContextCLOptions();
|
||||
registerPassManagerCLOptions();
|
||||
|
||||
@@ -79,8 +79,10 @@ add_mlir_tool(mlir-opt
|
||||
|
||||
DEPENDS
|
||||
${LIBS}
|
||||
SUPPORT_PLUGINS
|
||||
)
|
||||
target_link_libraries(mlir-opt PRIVATE ${LIBS})
|
||||
llvm_update_compile_flags(mlir-opt)
|
||||
|
||||
mlir_check_all_link_libraries(mlir-opt)
|
||||
export_executable_symbols_for_plugins(mlir-opt)
|
||||
|
||||
Reference in New Issue
Block a user