Skip to content

[mlir] Make C/Python ExecutionEngine constructible with an Operation. #86329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion mlir/include/mlir-c/ExecutionEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,15 @@ DEFINE_C_API_STRUCT(MlirExecutionEngine, void);
/// that will be loaded are specified via `numPaths` and `sharedLibPaths`
/// respectively.
/// TODO: figure out other options.
MLIR_CAPI_EXPORTED MlirExecutionEngine mlirExecutionEngineCreateFromOp(
MlirOperation op, int optLevel, int numPaths,
const MlirStringRef *sharedLibPaths, bool enableObjectDump);

// Deprecated variant which takes an MlirModule instead of an operation.
// This is being preserved as of 2024-Mar for short term consistency and should
// be dropped soon.
MLIR_CAPI_EXPORTED MlirExecutionEngine mlirExecutionEngineCreate(
MlirModule op, int optLevel, int numPaths,
MlirModule module, int optLevel, int numPaths,
const MlirStringRef *sharedLibPaths, bool enableObjectDump);

/// Destroy an ExecutionEngine instance.
Expand Down
25 changes: 22 additions & 3 deletions mlir/lib/Bindings/Python/ExecutionEngineModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,34 @@ PYBIND11_MODULE(_mlirExecutionEngine, m) {
// Mapping of the top-level PassManager
//----------------------------------------------------------------------------
py::class_<PyExecutionEngine>(m, "ExecutionEngine", py::module_local())
.def(py::init<>([](MlirModule module, int optLevel,
.def(py::init<>([](py::object operation_or_module, int optLevel,
const std::vector<std::string> &sharedLibPaths,
bool enableObjectDump) {
// Manually type cast from either a Module or Operation. The
// automatic type casters do not handle such cascades well,
// so be explicit.
py::object capsule = mlirApiObjectToCapsule(operation_or_module);
MlirOperation module_op =
mlirPythonCapsuleToOperation(capsule.ptr());
if (mlirOperationIsNull(module_op)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing ... I'd have expected this to be a check if not-null.

// If null, then a PyErr_Set has set an exception, which we must
// clear.
PyErr_Clear();
MlirModule mod = mlirPythonCapsuleToModule(capsule.ptr());
if (mlirModuleIsNull(mod)) {
throw py::type_error(
"ExecutionEngine expects a Module or Operation");
}
module_op = mlirModuleGetOperation(mod);
}

llvm::SmallVector<MlirStringRef, 4> libPaths;
for (const std::string &path : sharedLibPaths)
libPaths.push_back({path.c_str(), path.length()});
MlirExecutionEngine executionEngine =
mlirExecutionEngineCreate(module, optLevel, libPaths.size(),
libPaths.data(), enableObjectDump);
mlirExecutionEngineCreateFromOp(
module_op, optLevel, libPaths.size(), libPaths.data(),
enableObjectDump);
if (mlirExecutionEngineIsNull(executionEngine))
throw std::runtime_error(
"Failure while creating the ExecutionEngine.");
Expand Down
16 changes: 12 additions & 4 deletions mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,18 @@
using namespace mlir;

extern "C" MlirExecutionEngine
mlirExecutionEngineCreate(MlirModule op, int optLevel, int numPaths,
mlirExecutionEngineCreate(MlirModule module, int optLevel, int numPaths,
const MlirStringRef *sharedLibPaths,
bool enableObjectDump) {
return mlirExecutionEngineCreateFromOp(mlirModuleGetOperation(module),
optLevel, numPaths, sharedLibPaths,
enableObjectDump);
}

extern "C" MlirExecutionEngine
mlirExecutionEngineCreateFromOp(MlirOperation op, int optLevel, int numPaths,
const MlirStringRef *sharedLibPaths,
bool enableObjectDump) {
static bool initOnce = [] {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmParser(); // needed for inline_asm
Expand Down Expand Up @@ -104,9 +113,8 @@ extern "C" void mlirExecutionEngineRegisterSymbol(MlirExecutionEngine jit,
void *sym) {
unwrap(jit)->registerSymbols([&](llvm::orc::MangleAndInterner interner) {
llvm::orc::SymbolMap symbolMap;
symbolMap[interner(unwrap(name))] =
{ llvm::orc::ExecutorAddr::fromPtr(sym),
llvm::JITSymbolFlags::Exported };
symbolMap[interner(unwrap(name))] = {llvm::orc::ExecutorAddr::fromPtr(sym),
llvm::JITSymbolFlags::Exported};
return symbolMap;
});
}
Expand Down
4 changes: 2 additions & 2 deletions mlir/python/mlir/_mlir_libs/_mlirExecutionEngine.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# * Relative imports for cross-module references.
# * Add __all__

from typing import List, Sequence
from typing import List, Sequence,Union

from ._mlir import ir as _ir

Expand All @@ -13,7 +13,7 @@ __all__ = [
]

class ExecutionEngine:
def __init__(self, module: _ir.Module, opt_level: int = 2, shared_libs: Sequence[str] = ...) -> None: ...
def __init__(self, module: Union[_ir.Operation, _ir.Module], opt_level: int = 2, shared_libs: Sequence[str] = ...) -> None: ...
def _CAPICreate(self) -> object: ...
def _testing_release(self) -> None: ...
def dump_to_object_file(self, file_name: str) -> None: ...
Expand Down
Loading