You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Historical context: `PyMlirContext::liveOperations` was an optimization
meant to cut down on the number of Python object allocations and
(partially) a mechanism for updating validity of ops after
transformation. E.g. during walking/transforming the AST. See original
patch [here](https://reviews.llvm.org/D87958).
Inspired by a
[renewed](#139721 (comment))
interest in #139721 (which has
become a little stale...)
<p align="center">
<img width="504" height="375" alt="image"
src="https://github.com/user-attachments/assets/0daad562-d3d1-4876-8d01-5dba382ab186"
/>
</p>
In the previous go-around
(#92631) there were two issues
which have been resolved
1. ops that were "fetched" under a root op which has been transformed
are no longer reported as invalid. We simply "[formally
forbid](#92631 (comment))"
this;
2. `Module._CAPICreate(module_capsule)` must now be followed by a
`module._clear_mlir_module()` to prevent double-freeing of the actual
`ModuleOp` object (i.e. calling the dtor on the
`OwningOpRef<ModuleOp>`):
```python
module = ...
module_dup = Module._CAPICreate(module._CAPIPtr)
module._clear_mlir_module()
```
- **the alternative choice** here is to remove the `Module._CAPICreate`
API altogether and replace it with something like `Module._move(module)`
which will do both `Module._CAPICreate` and `module._clear_mlir_module`.
Note, the other approach I explored last year was a [weakref
system](#97340) for
`mlir::Operation` which would effectively hoist this `liveOperations`
thing into MLIR core. Possibly doable but I now believe it's a bad idea.
The other potentially breaking change is `is`, which checks object
equality rather than value equality, will now report `False` because we
are always allocating `new` Python objects (ie that's the whole point of
this change). Users wanting to check equality for `Operation` and
`Module` should use `==`.
Copy file name to clipboardExpand all lines: mlir/docs/Bindings/Python.md
+23-13Lines changed: 23 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -216,13 +216,28 @@ added to an attached operation, they need to be re-parented to the containing
216
216
module).
217
217
218
218
Due to the validity and parenting accounting needs, `PyOperation` is the owner
219
-
for regions and blocks and needs to be a top-level type that we can count on not
220
-
aliasing. This let's us do things like selectively invalidating instances when
221
-
mutations occur without worrying that there is some alias to the same operation
222
-
in the hierarchy. Operations are also the only entity that are allowed to be in
223
-
a detached state, and they are interned at the context level so that there is
224
-
never more than one Python `mlir.ir.Operation` object for a unique
225
-
`MlirOperation`, regardless of how it is obtained.
219
+
for regions and blocks. Operations are also the only entities which are allowed to be in
220
+
a detached state.
221
+
222
+
**Note**: Multiple `PyOperation` objects (i.e., the Python objects themselves) can alias a single `mlir::Operation`.
223
+
This means, for example, if you have `py_op1` and `py_op2` which wrap the same `mlir::Operation op`
224
+
and you somehow transform `op` (e.g., you run a pass on `op`) then walking the MLIR AST via either/or `py_op1`, `py_op2`
225
+
will reflect the same MLIR AST. This is perfectly safe and supported. What is not supported is invalidating any
226
+
operation while there exist multiple Python objects wrapping that operation **and then manipulating those wrappers**.
227
+
For example if `py_op1` and `py_op2` wrap the same operation under a root `py_op3` and then `py_op3` is
228
+
transformed such that the operation referenced (by `py_op1`, `py_op2`) is erased. Then `py_op1`, `py_op2`
229
+
become "undefined" in a sense; manipulating them in any way is "formally forbidden". Note, this also applies to
230
+
`SymbolTable` mutation, which is considered a transformation of the root `SymbolTable`-supporting operation for the
231
+
purposes of the discussion here. Metaphorically, one can think of this similarly to how STL container iterators are invalidated once the container itself is changed. The "best practices" recommendation is to structure your code such that
0 commit comments