-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[mlir][python] C++ API demo #71133
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
base: main
Are you sure you want to change the base?
[mlir][python] C++ API demo #71133
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -607,11 +607,13 @@ if(MLIR_INCLUDE_TESTS) | |
ROOT_DIR "${MLIR_SOURCE_DIR}/test/python/lib" | ||
SOURCES | ||
PythonTestModule.cpp | ||
PythonTestPass.cpp | ||
PRIVATE_LINK_LIBS | ||
LLVMSupport | ||
EMBED_CAPI_LINK_LIBS | ||
MLIRCAPIPythonTestDialect | ||
) | ||
set_source_files_properties(${MLIR_SOURCE_DIR}/test/python/lib/PythonTestPass.cpp PROPERTIES COMPILE_FLAGS -fno-rtti) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default, anything linked into a C extension module that's being built using pybind cmake helpers. The problem is Footnotes
|
||
endif() | ||
|
||
################################################################################ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
import mlir.dialects.python_test as test | ||
import mlir.dialects.tensor as tensor | ||
import mlir.dialects.arith as arith | ||
from mlir.passmanager import PassManager | ||
|
||
|
||
def run(f): | ||
|
@@ -551,3 +552,37 @@ def testInferTypeOpInterface(): | |
two_operands = test.InferResultsVariadicInputsOp(single=zero, doubled=zero) | ||
# CHECK: f32 | ||
print(two_operands.result.type) | ||
|
||
|
||
# CHECK-LABEL: testPythonPassDemo | ||
@run | ||
def testPythonPassDemo(): | ||
def print_ops(op): | ||
print(op.name) | ||
|
||
module = """ | ||
module { | ||
func.func @main() { | ||
%memref = memref.alloca() : memref<1xi64> | ||
%c0 = arith.constant 0 : index | ||
%c1 = arith.constant 1 : i64 | ||
memref.store %c1, %memref[%c0] : memref<1xi64> | ||
%u_memref = memref.cast %memref : memref<1xi64> to memref<*xi64> | ||
return | ||
} | ||
} | ||
""" | ||
|
||
# CHECK: memref.alloca | ||
# CHECK: arith.constant | ||
# CHECK: arith.constant | ||
# CHECK: memref.store | ||
# CHECK: memref.cast | ||
# CHECK: func.return | ||
# CHECK: func.func | ||
# CHECK: builtin.module | ||
with Context() as ctx, Location.unknown(): | ||
test.register_python_test_dialect(ctx) | ||
test.register_python_test_pass_demo_pass(print_ops) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That seems like a dangerous pattern to me: what happens when print_ops goes out of scope? (I mean it can't here, but you're registering a Also can you write in the same file a second run of the pipeline with a different There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The bandaid is to put
Yea sure but you can't register a single pass (in asserts mode...) multiple times anyway so we shouldn't expect that to work "afortiori". |
||
mlir_module = Module.parse(module) | ||
PassManager.parse("builtin.module(python-pass-demo)").run(mlir_module.operation) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is intended as a demo, can you make it into its own file, with extensive documentation: "example style" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
//===- PythonTestPassDemo.cpp -----------------------------------*- 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "PythonTestPass.h" | ||
|
||
#include "mlir-c/Bindings/Python/Interop.h" | ||
#include "mlir/CAPI/IR.h" | ||
#include "mlir/IR/BuiltinDialect.h" | ||
#include "mlir/Pass/Pass.h" | ||
|
||
using namespace mlir; | ||
|
||
namespace { | ||
|
||
struct PythonTestPassDemo | ||
: public PassWrapper<PythonTestPassDemo, OperationPass<ModuleOp>> { | ||
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(PythonTestPassDemo) | ||
|
||
PythonTestPassDemo(PyObject *func) : func(func) {} | ||
StringRef getArgument() const final { return "python-pass-demo"; } | ||
|
||
void runOnOperation() override { | ||
this->getOperation()->walk([this](Operation *op) { | ||
PyObject *mlirModule = | ||
PyImport_ImportModule(MAKE_MLIR_PYTHON_QUALNAME("ir")); | ||
PyObject *cAPIFactory = PyObject_GetAttrString( | ||
PyObject_GetAttrString(mlirModule, "Operation"), | ||
MLIR_PYTHON_CAPI_FACTORY_ATTR); | ||
PyObject *opApiObject = PyObject_CallFunction( | ||
cAPIFactory, "(O)", mlirPythonOperationToCapsule(wrap(op))); | ||
(void)PyObject_CallFunction(func, "(O)", opApiObject); | ||
Py_DECREF(opApiObject); | ||
}); | ||
} | ||
|
||
PyObject *func; | ||
}; | ||
|
||
std::unique_ptr<OperationPass<ModuleOp>> | ||
createPythonTestPassDemoPassWithFunc(PyObject *func) { | ||
return std::make_unique<PythonTestPassDemo>(func); | ||
} | ||
|
||
} // namespace | ||
|
||
void registerPythonTestPassDemoPassWithFunc(PyObject *func) { | ||
registerPass([func]() { return createPythonTestPassDemoPassWithFunc(func); }); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
//===- PythonTestPassDemo.h ---------------------------------------*- 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef MLIR_TEST_PYTHON_PASS_PYTHONTESTCAPI_H | ||
#define MLIR_TEST_PYTHON_PASS_PYTHONTESTCAPI_H | ||
|
||
#include <Python.h> | ||
|
||
void registerPythonTestPassDemoPassWithFunc(PyObject *func); | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pulls in mlir c++ libs (built-in and pass) but it's not depending on them here. It appears they just happen to be resolved via MLIRCAPIPythonTestDialect.
I don't think this is going to work, and there is not an easy fix. This is relying in the capi lib incidentally exporting symbols for its backing c++ API. That is dependent on how the project is built: it happens to be true in this dev tree but will not work with hidden visibility, like real packages use. The other option you may be tempted to do is add the things you need to PRIVATE_LINK_LIBS, but that is also fraught. Not only will it duplicate the backing library code in the extension, TypeID linkage will no longer be single, strongly rooted. This will create the dreaded vague linkage issues on Linux and has no path to work on Windows.
I don't have a good suggestion: this is why we did not get adventurous on some of this stuff.