Revision tags: llvmorg-21-init |
|
#
acde3f72 |
| 24-Jan-2025 |
Peter Hawkins <phawkins@google.com> |
[mlir:python] Compute get_op_result_or_value in PyOpView's constructor. (#123953)
This logic is in the critical path for constructing an operation from
Python. It is faster to compute this in C++ t
[mlir:python] Compute get_op_result_or_value in PyOpView's constructor. (#123953)
This logic is in the critical path for constructing an operation from
Python. It is faster to compute this in C++ than it is in Python, and it
is a minor change to do this.
This change also alters the API contract of
_ods_common.get_op_results_or_values to avoid calling
get_op_result_or_value on each element of a sequence, since the C++ code
will now do this.
Most of the diff here is simply reordering the code in IRCore.cpp.
show more ...
|
#
a77250fd |
| 22-Jan-2025 |
Jacques Pienaar <jpienaar@google.com> |
[mlir] Add C and Python interface for file range (#123276)
Plumbs through creating file ranges to C and Python.
|
#
e30b7030 |
| 22-Jan-2025 |
Peter Hawkins <phawkins@google.com> |
[mlir:python] Construct PyOperation objects in-place on the Python heap. (#123813)
Currently we make two memory allocations for each PyOperation: a Python
object, and the PyOperation class itself.
[mlir:python] Construct PyOperation objects in-place on the Python heap. (#123813)
Currently we make two memory allocations for each PyOperation: a Python
object, and the PyOperation class itself. With some care we can allocate
the PyOperation inline inside the Python object, saving us a malloc()
call per object and perhaps improving cache locality.
show more ...
|
#
f4125e02 |
| 22-Jan-2025 |
Peter Hawkins <phawkins@google.com> |
[mlir python] Change PyOpView constructor to construct operations. (#123777)
Previously ODS-generated Python operations had code like this:
```
super().__init__(self.build_generic(attributes=att
[mlir python] Change PyOpView constructor to construct operations. (#123777)
Previously ODS-generated Python operations had code like this:
```
super().__init__(self.build_generic(attributes=attributes, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip))
```
we change it to:
```
super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)
```
This:
a) avoids an extra call dispatch (to `build_generic`), and
b) passes the class attributes directly to the constructor. Benchmarks
show that it is faster to pass these as arguments rather than having the
C++ code look up attributes on the class.
This PR improves the timing of the following benchmark on my workstation
from 5.3s to 4.5s:
```
def main(_):
with ir.Context(), ir.Location.unknown():
typ = ir.IntegerType.get_signless(32)
m = ir.Module.create()
with ir.InsertionPoint(m.body):
start = time.time()
for i in range(1000000):
arith.ConstantOp(typ, i)
end = time.time()
print(f"time: {end - start}")
```
Since this change adds an additional overload to the constructor and
does not alter any existing behaviors, it should be backwards
compatible.
show more ...
|
Revision tags: llvmorg-19.1.7 |
|
#
e2c49a45 |
| 13-Jan-2025 |
Peter Hawkins <phawkins@google.com> |
[mlir python] Add locking around PyMlirContext::liveOperations. (#122720)
In JAX, I observed a race between two PyOperation destructors from
different threads updating the same `liveOperations` map
[mlir python] Add locking around PyMlirContext::liveOperations. (#122720)
In JAX, I observed a race between two PyOperation destructors from
different threads updating the same `liveOperations` map, despite not
intentionally sharing the context between different threads. Since I
don't think we can be completely sure when GC happens and on which
thread, it seems safest simply to add locking here.
We may also want to explicitly support sharing a context between threads
in the future, which would require this change or something similar.
show more ...
|
#
f136c800 |
| 13-Jan-2025 |
vfdev <vfdev.5@gmail.com> |
Enabled freethreading support in MLIR python bindings (#122684)
Reland reverted https://github.com/llvm/llvm-project/pull/107103 with
the fixes for Python 3.8
cc @jpienaar
Co-authored-by: Pet
Enabled freethreading support in MLIR python bindings (#122684)
Reland reverted https://github.com/llvm/llvm-project/pull/107103 with
the fixes for Python 3.8
cc @jpienaar
Co-authored-by: Peter Hawkins <phawkins@google.com>
show more ...
|
#
3f1486f0 |
| 12-Jan-2025 |
Jacques Pienaar <jpienaar@google.com> |
Revert "Added free-threading CPython mode support in MLIR Python bindings (#107103)"
Breaks on 3.8, rolling back to avoid breakage while fixing.
This reverts commit 9dee7c44491635ec9037b90050bcdbd3
Revert "Added free-threading CPython mode support in MLIR Python bindings (#107103)"
Breaks on 3.8, rolling back to avoid breakage while fixing.
This reverts commit 9dee7c44491635ec9037b90050bcdbd3d5291e38.
show more ...
|
#
9dee7c44 |
| 12-Jan-2025 |
vfdev <vfdev.5@gmail.com> |
Added free-threading CPython mode support in MLIR Python bindings (#107103)
Related to https://github.com/llvm/llvm-project/issues/105522
Description:
This PR is a joint work with Peter Hawkin
Added free-threading CPython mode support in MLIR Python bindings (#107103)
Related to https://github.com/llvm/llvm-project/issues/105522
Description:
This PR is a joint work with Peter Hawkins (@hawkinsp) originally done
by myself for pybind11 and then reworked to nanobind based on Peter's
branch: https://github.com/hawkinsp/llvm-project/tree/nbdev .
- Added free-threading CPython mode support for MLIR Python bindings
- Added a test which can reveal data races when cpython and LLVM/MLIR
compiled with TSAN
Context:
- Related to https://github.com/google/jax/issues/23073
Co-authored-by: Peter Hawkins <phawkins@google.com>
show more ...
|
#
a0f5bbcf |
| 07-Jan-2025 |
vfdev <vfdev.5@gmail.com> |
Fixed typo in dunder get/set methods in PyAttrBuilderMap (#121794)
Description: - fixed a typo in the method name: dunde -> dunder
|
#
08e2c15a |
| 29-Dec-2024 |
Maksim Levental <maksim.levental@gmail.com> |
[mlir][python] disable nanobind leak warnings (#121099)
|
#
5cd42747 |
| 21-Dec-2024 |
Peter Hawkins <phawkins@google.com> |
[mlir python] Port in-tree dialects to nanobind. (#119924)
This is a companion to #118583, although it can be landed independently
because since #117922 dialects do not have to use the same Python
[mlir python] Port in-tree dialects to nanobind. (#119924)
This is a companion to #118583, although it can be landed independently
because since #117922 dialects do not have to use the same Python
binding framework as the Python core code.
This PR ports all of the in-tree dialect and pass extensions to
nanobind, with the exception of those that remain for testing pybind11
support.
This PR also:
* removes CollectDiagnosticsToStringScope from NanobindAdaptors.h. This
was overlooked in a previous PR and it is duplicated in Diagnostics.h.
---------
Co-authored-by: Jacques Pienaar <jpienaar@google.com>
show more ...
|
#
b56d1ec6 |
| 19-Dec-2024 |
Peter Hawkins <phawkins@google.com> |
[mlir python] Port Python core code to nanobind. (#120473)
Relands #118583, with a fix for Python 3.8 compatibility. It was not
possible to set the buffer protocol accessers via slots in Python 3.8
[mlir python] Port Python core code to nanobind. (#120473)
Relands #118583, with a fix for Python 3.8 compatibility. It was not
possible to set the buffer protocol accessers via slots in Python 3.8.
Why? https://nanobind.readthedocs.io/en/latest/why.html says it better
than I can, but my primary motivation for this change is to improve MLIR
IR construction time from JAX.
For a complicated Google-internal LLM model in JAX, this change improves
the MLIR
lowering time by around 5s (out of around 30s), which is a significant
speedup for simply switching binding frameworks.
To a large extent, this is a mechanical change, for instance changing
`pybind11::` to `nanobind::`.
Notes:
* this PR needs Nanobind 2.4.0, because it needs a bug fix
(https://github.com/wjakob/nanobind/pull/806) that landed in that
release.
* this PR does not port the in-tree dialect extension modules. They can
be ported in a future PR.
* I removed the py::sibling() annotations from def_static and def_class
in `PybindAdapters.h`. These ask pybind11 to try to form an overload
with an existing method, but it's not possible to form mixed
pybind11/nanobind overloads this ways and the parent class is now
defined in nanobind. Better solutions may be possible here.
* nanobind does not contain an exact equivalent of pybind11's buffer
protocol support. It was not hard to add a nanobind implementation of a
similar API.
* nanobind is pickier about casting to std::vector<bool>, expecting that
the input is a sequence of bool types, not truthy values. In a couple of
places I added code to support truthy values during casting.
* nanobind distinguishes bytes (`nb::bytes`) from strings (e.g.,
`std::string`). This required nb::bytes overloads in a few places.
show more ...
|
#
6e8b3a3e |
| 18-Dec-2024 |
Jacques Pienaar <jpienaar@google.com> |
Revert "[mlir python] Port Python core code to nanobind. (#118583)"
This reverts commit 41bd35b58bb482fd466aa4b13aa44a810ad6470f.
Breakage detected, rolling back.
|
#
41bd35b5 |
| 18-Dec-2024 |
Peter Hawkins <phawkins@google.com> |
[mlir python] Port Python core code to nanobind. (#118583)
Why? https://nanobind.readthedocs.io/en/latest/why.html says it better
than I can, but my primary motivation for this change is to improve
[mlir python] Port Python core code to nanobind. (#118583)
Why? https://nanobind.readthedocs.io/en/latest/why.html says it better
than I can, but my primary motivation for this change is to improve MLIR
IR construction time from JAX.
For a complicated Google-internal LLM model in JAX, this change improves
the MLIR
lowering time by around 5s (out of around 30s), which is a significant
speedup for simply switching binding frameworks.
To a large extent, this is a mechanical change, for instance changing
`pybind11::`
to `nanobind::`.
Notes:
* this PR needs Nanobind 2.4.0, because it needs a bug fix
(https://github.com/wjakob/nanobind/pull/806) that landed in that
release.
* this PR does not port the in-tree dialect extension modules. They can
be ported in a future PR.
* I removed the py::sibling() annotations from def_static and def_class
in `PybindAdapters.h`. These ask pybind11 to try to form an overload
with an existing method, but it's not possible to form mixed
pybind11/nanobind overloads this ways and the parent class is now
defined in nanobind. Better solutions may be possible here.
* nanobind does not contain an exact equivalent of pybind11's buffer
protocol support. It was not hard to add a nanobind implementation of a
similar API.
* nanobind is pickier about casting to std::vector<bool>, expecting that
the input is a sequence of bool types, not truthy values. In a couple of
places I added code to support truthy values during casting.
* nanobind distinguishes bytes (`nb::bytes`) from strings (e.g.,
`std::string`). This required nb::bytes overloads in a few places.
show more ...
|
Revision tags: llvmorg-19.1.6, llvmorg-19.1.5 |
|
#
21df3251 |
| 20-Nov-2024 |
Perry Gibson <Wheest@users.noreply.github.com> |
[mlir,python] Expose replaceAllUsesExcept to Python bindings (#115850)
Problem originally described in [the forums
here](https://discourse.llvm.org/t/mlir-python-expose-replaceallusesexcept/83068/1
[mlir,python] Expose replaceAllUsesExcept to Python bindings (#115850)
Problem originally described in [the forums
here](https://discourse.llvm.org/t/mlir-python-expose-replaceallusesexcept/83068/1).
Using the MLIR Python bindings, the method
[`replaceAllUsesWith`](https://mlir.llvm.org/doxygen/classmlir_1_1Value.html#ac56b0fdb6246bcf7fa1805ba0eb71aa2)
for `Value` is exposed, e.g.,
```python
orig_value.replace_all_uses_with(
new_value
)
```
However, in my use-case I am separating a block into multiple blocks, so
thus want to exclude certain Operations from having their Values
replaced (since I want them to diverge).
Within Value, we have
[`replaceAllUsesExcept`](https://mlir.llvm.org/doxygen/classmlir_1_1Value.html#a9ec8d5c61f8a6aada4062f609372cce4),
where we can pass the Operations which should be skipped.
This is not currently exposed in the Python bindings: this PR fixes
this. Adds `replace_all_uses_except`, which works with individual
Operations, and lists of Operations.
show more ...
|
Revision tags: llvmorg-19.1.4 |
|
#
00a93e62 |
| 05-Nov-2024 |
Peter Hawkins <phawkins@google.com> |
[mlir:python] Change PyOperation::create to actually return a PyOperation. (#114542)
In the tablegen-generated Python bindings, we typically see a pattern
like:
```
class ConstantOp(_ods_ir.OpVie
[mlir:python] Change PyOperation::create to actually return a PyOperation. (#114542)
In the tablegen-generated Python bindings, we typically see a pattern
like:
```
class ConstantOp(_ods_ir.OpView):
...
def __init__(self, value, *, loc=None, ip=None):
...
super().__init__(self.build_generic(attributes=attributes, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip))
```
i.e., the generated code calls `OpView.__init__()` with the output of
`build_generic`. The purpose of `OpView` is to wrap another operation
object, and `OpView.__init__` can accept any `PyOperationBase` subclass,
and presumably the intention is that `build_generic` returns a
`PyOperation`, so the user ends up with a `PyOpView` wrapping a
`PyOperation`.
However, `PyOpView::buildGeneric` calls `PyOperation::create`, which
does not just build a PyOperation, but it also calls `createOpView` to
wrap that operation in a subclass of `PyOpView` and returns that view.
But that's rather pointless: we called this code from the constructor of
an `OpView` subclass, so we already have a view object ready to go; we
don't need to build another one!
If we change `PyOperation::create` to return the underlying
`PyOperation`, rather than a view wrapper, we can save allocating a
useless `PyOpView` object for each ODS-generated Python object.
This saves approximately 1.5s of Python time in a JAX LLM benchmark that
generates a mixture of upstream dialects and StableHLO.
show more ...
|
Revision tags: llvmorg-19.1.3, llvmorg-19.1.2, llvmorg-19.1.1, llvmorg-19.1.0, llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3, llvmorg-19.1.0-rc2, llvmorg-19.1.0-rc1, llvmorg-20-init |
|
#
abad8455 |
| 20-Jun-2024 |
Jonas Rickert <semi1@posteo.de> |
[mlir] Expose skipRegions option for Op printing in the C and Python bindings (#96150)
The MLIR C and Python Bindings expose various methods from
`mlir::OpPrintingFlags` . This PR adds a binding fo
[mlir] Expose skipRegions option for Op printing in the C and Python bindings (#96150)
The MLIR C and Python Bindings expose various methods from
`mlir::OpPrintingFlags` . This PR adds a binding for the `skipRegions`
method, which allows to skip the printing of Regions when printing Ops.
It also exposes this option as parameter in the python `get_asm` and
`print` methods
show more ...
|
Revision tags: llvmorg-18.1.8 |
|
#
55d2fffd |
| 05-Jun-2024 |
Sandeep Dasgupta <sdasgup@google.com> |
[mlir][python]Python Bindings for select edit operations on Block arguments (#94305)
The PR implements MLIR Python Bindings for a few simple edit operations
on Block arguments, namely, `add_argumen
[mlir][python]Python Bindings for select edit operations on Block arguments (#94305)
The PR implements MLIR Python Bindings for a few simple edit operations
on Block arguments, namely, `add_argument`, `erase_argument`, and
`erase_arguments`.
show more ...
|
Revision tags: llvmorg-18.1.7 |
|
#
67897d77 |
| 30-May-2024 |
Oleksandr "Alex" Zinenko <git@ozinenko.com> |
[mlir][py] invalidate nested operations when parent is deleted (#93339)
When an operation is erased in Python, its children may still be in the
"live" list inside Python bindings. After this, if so
[mlir][py] invalidate nested operations when parent is deleted (#93339)
When an operation is erased in Python, its children may still be in the
"live" list inside Python bindings. After this, if some of the newly
allocated operations happen to reuse the same pointer address, this will
trigger an assertion in the bindings. This assertion would be incorrect
because the operations aren't actually live. Make sure we remove the
children operations from the "live" list when erasing the parent.
This also concentrates responsibility over the removal from the "live"
list and invalidation in a single place.
Note that this requires the IR to be sufficiently structurally valid so
a walk through it can succeed. If this invariant was broken by, e.g, C++
pass called from Python, there isn't much we can do.
show more ...
|
#
8f21909c |
| 24-May-2024 |
Oleksandr "Alex" Zinenko <git@ozinenko.com> |
[mlir] expose -debug-only equivalent to C and Python (#93175)
These are useful for finer-grain debugging and complement the already
exposed global debug flag.
|
Revision tags: llvmorg-18.1.6, llvmorg-18.1.5 |
|
#
bc553646 |
| 18-Apr-2024 |
tomnatan30 <130450079+tomnatan30@users.noreply.github.com> |
[mlir][python] Fix PyOperationBase::walk not catching exception in python callback (#89225)
If the python callback throws an error, the c++ code will throw a
py::error_already_set that needs to be
[mlir][python] Fix PyOperationBase::walk not catching exception in python callback (#89225)
If the python callback throws an error, the c++ code will throw a
py::error_already_set that needs to be caught and handled in the c++
code .
This change is inspired by the similar solution in
PySymbolTable::walkSymbolTables.
show more ...
|
#
47148832 |
| 17-Apr-2024 |
Hideto Ueno <uenoku.tokotoko@gmail.com> |
[mlir][python] Add `walk` method to PyOperationBase (#87962)
This commit adds `walk` method to PyOperationBase that uses a python
object as a callback, e.g. `op.walk(callback)`. Currently callback
[mlir][python] Add `walk` method to PyOperationBase (#87962)
This commit adds `walk` method to PyOperationBase that uses a python
object as a callback, e.g. `op.walk(callback)`. Currently callback must
return a walk result explicitly.
We(SiFive) have implemented walk method with python in our internal
python tool for a while. However the overhead of python is expensive and
it didn't scale well for large MLIR files. Just replacing walk with this
version reduced the entire execution time of the tool by 30~40% and
there are a few configs that the tool takes several hours to finish so
this commit significantly improves tool performance.
show more ...
|
Revision tags: llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2, llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4 |
|
#
91f11611 |
| 21-Feb-2024 |
Oleksandr "Alex" Zinenko <zinenko@google.com> |
[mlir] expose transform interpreter to Python (#82365)
Transform interpreter functionality can be used standalone without going
through the interpreter pass, make it available in Python.
|
Revision tags: llvmorg-18.1.0-rc3 |
|
#
d1fdb416 |
| 08-Feb-2024 |
John Demme <john.demme@microsoft.com> |
[MLIR][Python] Add method for getting the live operation objects (#78663)
Currently, a method exists to get the count of the operation objects
which are still alive. This helps for sanity checking,
[MLIR][Python] Add method for getting the live operation objects (#78663)
Currently, a method exists to get the count of the operation objects
which are still alive. This helps for sanity checking, but isn't
terribly useful for debugging. This new method returns the actual
operation objects which are still alive.
This allows Python code like the following:
```
gc.collect()
live_ops = ir.Context.current._get_live_operation_objects()
for op in live_ops:
print(f"Warning: {op} is still live. Referrers:")
for referrer in gc.get_referrers(op)[0]:
print(f" {referrer}")
```
show more ...
|
Revision tags: llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1, llvmorg-19-init |
|
#
78bd1246 |
| 21-Dec-2023 |
Alex Zinenko <zinenko@google.com> |
Revert "[mlir][python] Make the Context/Operation capsule creation methods work as documented. (#76010)"
This reverts commit bbc29768683b394b34600347f46be2b8245ddb30.
This change seems to be at odd
Revert "[mlir][python] Make the Context/Operation capsule creation methods work as documented. (#76010)"
This reverts commit bbc29768683b394b34600347f46be2b8245ddb30.
This change seems to be at odds with the non-owning part semantics of MlirOperation in C API. Since downstream clients can only take and return MlirOperation, it does not sound correct to force all returns of MlirOperation transfer ownership. Specifically, this makes it impossible for downstreams to implement IR-traversing functions that, e.g., look at neighbors of an operation.
The following patch triggers the exception, and there does not seem to be an alternative way for a downstream binding writer to express this:
``` diff --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp index 39757dfad5be..2ce640674245 100644 --- a/mlir/lib/Bindings/Python/IRCore.cpp +++ b/mlir/lib/Bindings/Python/IRCore.cpp @@ -3071,6 +3071,11 @@ void mlir::python::populateIRCore(py::module &m) { py::arg("successors") = py::none(), py::arg("regions") = 0, py::arg("loc") = py::none(), py::arg("ip") = py::none(), py::arg("infer_type") = false, kOperationCreateDocstring) + .def("_get_first_in_block", [](PyOperation &self) -> MlirOperation { + MlirBlock block = mlirOperationGetBlock(self.get()); + MlirOperation first = mlirBlockGetFirstOperation(block); + return first; + }) .def_static( "parse", [](const std::string &sourceStr, const std::string &sourceName, diff --git a/mlir/test/python/ir/operation.py b/mlir/test/python/ir/operation.py index f59b1a26ba48..6b12b8da5c24 100644 --- a/mlir/test/python/ir/operation.py +++ b/mlir/test/python/ir/operation.py @@ -24,6 +24,25 @@ def expect_index_error(callback): except IndexError: pass
+@run +def testCustomBind(): + ctx = Context() + ctx.allow_unregistered_dialects = True + module = Module.parse( + r""" + func.func @f1(%arg0: i32) -> i32 { + %1 = "custom.addi"(%arg0, %arg0) : (i32, i32) -> i32 + return %1 : i32 + } + """, + ctx, + ) + add = module.body.operations[0].regions[0].blocks[0].operations[0] + op = add.operation + # This will get a reference to itself. + f1 = op._get_first_in_block() + +
# Verify iterator based traversal of the op/region/block hierarchy. # CHECK-LABEL: TEST: testTraverseOpRegionBlockIterators ```
show more ...
|