summaryrefslogtreecommitdiff
path: root/mlir/lib/Bindings/Python/IRCore.cpp
AgeCommit message (Collapse)Author
2025-11-21[mlir][py][c] Enable setting block arg locations. (#169033)Jacques Pienaar
This enables changing the location of a block argument. Follows the approach for updating type of block arg.
2025-11-13[MLIR] [Python] `ir.Value` is now generic in the type of the value it holds ↵Sergei Lebedev
(#166148) This makes it similar to `mlir::TypedValue` in the MLIR C++ API and allows users to be more specific about the values they produce or accept. Co-authored-by: Maksim Levental <maksim.levental@gmail.com>
2025-11-11[MLIR][Python] fix PyRegionList `__iter__` (#167466)Maksim Levental
Fixes https://github.com/llvm/llvm-project/issues/167455
2025-11-10[MLIR][Python] add/fix docstrings in IRCore (#167063)Maksim Levental
This PR adds all the missing doc strings in IRCore.cpp. It also 1. Normalizes all doc strings to have proper punctuation; 2. Inlines non-duplicated docstrings which are currently at the top of the source file (and thereby possibly out of sync). Follow-up PRs will do the same for the rest of the modules/source files. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-26[MLIR][Python] fix getOwner to return (typed) nb::object instead of abstract ↵Maksim Levental
PyOpView (#165053) https://github.com/llvm/llvm-project/pull/157930 changed `nb::object getOwner()` to `PyOpView getOwner()` which implicitly constructs the generic OpView against from a (possibly) concrete OpView. This PR fixes that.
2025-10-16[mlir][python] add dict-style to IR attributes (#163200)Perry Gibson
It makes sense that Attribute dicts/maps should behave like dicts in the Python bindings. Previously this was not the case.
2025-10-05[MLIR][Python] Expose the insertion point of pattern rewriter (#161001)Twice
In [#160520](https://github.com/llvm/llvm-project/pull/160520), we discussed the current limitations of PDL rewriting in Python (see [this comment](https://github.com/llvm/llvm-project/pull/160520#issuecomment-3332326184)). At the moment, we cannot create new operations in PDL native (python) rewrite functions because the `PatternRewriter` APIs are not exposed. This PR introduces bindings to retrieve the insertion point of the `PatternRewriter`, enabling users to create new operations within Python rewrite functions. With this capability, more complex rewrites e.g. with branching and loops that involve op creations become possible. --------- Co-authored-by: Maksim Levental <maksim.levental@gmail.com>
2025-10-02[MLIR][Python] fixup Context and Location stubs and NanobindAdaptors (#161433)Maksim Levental
add correct names for `NB_TYPE_CASTER(..., name)` so users of `NanobindAdaptors.h` can generate the correct hints. Also fix a few straggler stubs.
2025-10-01[MLIR][Python] expose Operation::setLoc (#161594)Maksim Levental
2025-09-23[MLIR][Python] use nb::typed for return signatures (#160221)Maksim Levental
https://github.com/llvm/llvm-project/pull/160183 removed `nb::typed` annotation to fix bazel but it turned out to be simply a matter of not using the correct version of nanobind (see https://github.com/llvm/llvm-project/pull/160183#issuecomment-3321429155). This PR restores those annotations but (mostly) moves to the return positions of the actual methods.
2025-09-22[MLIR][Python] restore APIs in terms of Mlir* types (#160203)Maksim Levental
https://github.com/llvm/llvm-project/pull/157930 changed a few APIs from `Mlir*` to `Py*` and broke users that were using them (see https://github.com/llvm/llvm-project/pull/160183#issuecomment-3321383969). This PR restores those APIs.
2025-09-22[MLIR][Python] remove nb::typed to fix bazel build (#160183)Maksim Levental
https://github.com/llvm/llvm-project/pull/157930 broke bazel build (see https://github.com/llvm/llvm-project/pull/157930#issuecomment-3318681217) because bazel is stricter on implicit conversions (some difference in flags passed to clang). This PR fixes by moving/removing `nb::typed`. EDIT: and also the overlay...
2025-09-20[MLIR][Python] reland (narrower) type stub generation (#157930)Maksim Levental
This a reland of https://github.com/llvm/llvm-project/pull/155741 which was reverted at https://github.com/llvm/llvm-project/pull/157831. This version is narrower in scope - it only turns on automatic stub generation for `MLIRPythonExtension.Core._mlir` and **does not do anything automatically**. Specifically, the only CMake code added to `AddMLIRPython.cmake` is the `mlir_generate_type_stubs` function which is then used only in a manual way. The API for `mlir_generate_type_stubs` is: ``` Arguments: MODULE_NAME: The fully-qualified name of the extension module (used for importing in python). DEPENDS_TARGETS: List of targets these type stubs depend on being built; usually corresponding to the specific extension module (e.g., something like StandalonePythonModules.extension._standaloneDialectsNanobind.dso) and the core bindings extension module (e.g., something like StandalonePythonModules.extension._mlir.dso). OUTPUT_DIR: The root output directory to emit the type stubs into. OUTPUTS: List of expected outputs. DEPENDS_TARGET_SRC_DEPS: List of cpp sources for extension library (for generating a DEPFILE). IMPORT_PATHS: List of paths to add to PYTHONPATH for stubgen. PATTERN_FILE: (Optional) Pattern file (see https://nanobind.readthedocs.io/en/latest/typing.html#pattern-files). Outputs: NB_STUBGEN_CUSTOM_TARGET: The target corresponding to generation which other targets can depend on. ``` Downstream users should use `mlir_generate_type_stubs` in coordination with `declare_mlir_python_sources` to turn on stub generation for their own downstream dialect extensions and upstream dialect extensions if they so choose. Standalone example shows an example. Note, downstream will also need to set `-DMLIR_PYTHON_PACKAGE_PREFIX=...` correctly for their bindings.
2025-09-15[MLIR][Python] restore `liveModuleMap` (#158506)Maksim Levental
There are cases where the same module can have multiple references (via `PyModule::forModule` via `PyModule::createFromCapsule`) and thus when `PyModule`s get gc'd `mlirModuleDestroy` can get called multiple times for the same actual underlying `mlir::Module` (i.e., double free). So we do actually need a "liveness map" for modules. Note, if `type_caster<MlirModule>::from_cpp` weren't a thing we could guarantree this never happened except explicitly when users called `PyModule::createFromCapsule`.
2025-09-08[MLIR][Python] remove unnecessary `arg.none() = nb::none()` pattern (#157519)Maksim Levental
We have `arg.none() = nb::none()` in a lot of places but this is no longer necessary (as of ~[2022](https://github.com/wjakob/nanobind/commit/62a23bb87b57d939e045f9c9da78a1d7235d2271)).
2025-09-05[MLIR][Python] bind InsertionPointAfter (#157156)Maksim Levental
2025-09-02[MLIR][Python] fix operation hashing (#156514)Maksim Levental
https://github.com/llvm/llvm-project/pull/155114 broke op hashing (because the python objects ceased to be reference equivalent). This PR fixes by binding `OperationEquivalence::computeHash`.
2025-09-01[MLIR][Python] remove `liveOperations` (#155114)Maksim Levental
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](https://github.com/llvm/llvm-project/pull/139721#issuecomment-3217131918) interest in https://github.com/llvm/llvm-project/pull/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 (https://github.com/llvm/llvm-project/pull/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](https://github.com/llvm/llvm-project/pull/92631#issuecomment-2119397018)" 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](https://github.com/llvm/llvm-project/pull/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 `==`.
2025-08-26[MLIR] Apply clang-tidy fixes for readability-identifier-naming in ↵Mehdi Amini
IRCore.cpp (NFC)
2025-08-26[MLIR] Apply clang-tidy fixes for performance-move-const-arg in IRCore.cpp (NFC)Mehdi Amini
2025-08-26[MLIR] Apply clang-tidy fixes for modernize-use-using in IRCore.cpp (NFC)Mehdi Amini
2025-08-26[MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in IRCore.cpp (NFC)Mehdi Amini
2025-08-16[mlir][python] handle more undefined symbols not covered by nanobind (#153861)Maksim Levental
Introduced (but omitted from this CMake) in https://github.com/llvm/llvm-project/pull/151246.
2025-08-12[mlir][python] fix PyThreadState_GetFrame again (#153333)Maksim Levental
add more APIs missing from 3.8 (fix rocm builder)
2025-08-13[mlir][python] fix PyThreadState_GetFrame (#153325)Maksim Levental
`PyThreadState_GetFrame` wasn't added until 3.9 (fixes currently failing rocm builder)
2025-08-12[mlir][python] automatic location inference (#151246)Maksim Levental
This PR implements "automatic" location inference in the bindings. The way it works is it walks the frame stack collecting source locations (Python captures these in the frame itself). It is inspired by JAX's [implementation](https://github.com/jax-ml/jax/blob/523ddcfbcad005deab5a7d542df4c706f5ee5e9c/jax/_src/interpreters/mlir.py#L462) but moves the frame stack traversal into the bindings for better performance. The system supports registering "included" and "excluded" filenames; frames originating from functions in included filenames **will not** be filtered and frames originating from functions in excluded filenames **will** be filtered (in that order). This allows excluding all the generated `*_ops_gen.py` files. The system is also "toggleable" and off by default to save people who have their own systems (such as JAX) from the added cost. Note, the system stores the entire stacktrace (subject to `locTracebackFramesLimit`) in the `Location` using specifically a `CallSiteLoc`. This can be useful for profiling tools (flamegraphs etc.). Shoutout to the folks at JAX for coming up with a good system. --------- Co-authored-by: Jacques Pienaar <jpienaar@google.com>
2025-08-11[mlir][python] expose isAttached (#153045)Maksim Levental
2025-07-23[mlir][python,CAPI] expose Op::isBeforeInBlock (#150271)Maksim Levental
2025-07-17[MLIR][Python] Support eliding large resource strings in PassManager (#149187)Akshay Khadse
- Introduces a `large_resource_limit` parameter across Python bindings, enabling the eliding of resource strings exceeding a specified character limit during IR printing. - To maintain backward compatibilty, when using `operation.print()` API, if `large_resource_limit` is None and the `large_elements_limit` is set, the later will be used to elide the resource string as well. This change was introduced by https://github.com/llvm/llvm-project/pull/125738. - For printing using pass manager, the `large_resource_limit` and `large_elements_limit` are completely independent of each other.
2025-06-23[mlir][python] bind block predecessors and successors (#145116)Maksim Levental
bind `block.getSuccessor` and `block.getPredecessors`.
2025-06-20[mlir][python] expose operation.block (#145088)Maksim Levental
Expose `operation-getBlock()` in python.
2025-04-09[mlir][python] add use_name_loc_as_prefix to value.get_name() (#135052)Maksim Levental
Add `use_name_loc_as_prefix` to `value.get_name()`.
2025-03-21[MLIR] [python] A few improvements to the Python bindings (#131686)Sergei Lebedev
* `PyRegionList` is now sliceable. The dialect bindings generator seems to assume it is sliceable already (!), yet accessing e.g. `cases` on `scf.IndexedSwitchOp` raises a `TypeError` at runtime. * `PyBlockList` and `PyOperationList` support negative indexing. It is common for containers to do that in Python, and most container in the MLIR Python bindings already allow the index to be negative.
2025-03-10[MLIR][py] Add PyThreadPool as wrapper around MlirLlvmThreadPool in MLIR ↵vfdev
python bindings (#130109) In some projects like JAX ir.Context are used with disabled multi-threading to avoid caching multiple threading pools: https://github.com/jax-ml/jax/blob/623865fe9538100d877ba9d36f788d0f95a11ed2/jax/_src/interpreters/mlir.py#L606-L611 However, when context has enabled multithreading it also uses locks on the StorageUniquers and this can be helpful to avoid data races in the multi-threaded execution (for example with free-threaded cpython, https://github.com/jax-ml/jax/issues/26272). With this PR user can enable the multi-threading: 1) enables additional locking and 2) set a shared threading pool such that cached contexts can have one global pool.
2025-03-10[mlir][CAPI][python] bind CallSiteLoc, FileLineColRange, FusedLoc, NameLoc ↵Maksim Levental
(#129351) This PR extends the python bindings for CallSiteLoc, FileLineColRange, FusedLoc, NameLoc with field accessors. It also adds the missing `value.location` accessor. I also did some "spring cleaning" here (`cast` -> `dyn_cast`) after running into some of my own illegal casts.
2025-03-04[mlir][py] Plumb OpPrintingFlags::printNameLocAsPrefix() through the ↵Jacques Pienaar
C/Python APIs (#129607)
2025-02-24[mlir] Python: write bytecode to a file path (#127118)Nikhil Kalra
The current `write_bytecode` implementation necessarily requires the serialized module to be duplicated in memory when the python `bytes` object is created and sent over the binding. For modules with large resources, we may want to avoid this in-memory copy by serializing directly to a file instead of sending bytes across the boundary.
2025-02-12[mlir] Python: Parse ModuleOp from file path (#126572)Nikhil Kalra
For extremely large models, it may be inefficient to load the model into memory in Python prior to passing it to the MLIR C APIs for deserialization. This change adds an API to parse a ModuleOp directly from a file path. Re-lands [4e14b8a](https://github.com/llvm/llvm-project/commit/4e14b8afb44af58ab7073bb8c0b52875599b0ae1).
2025-02-10Revert "[mlir] Python: Parse ModuleOp from file path" (#126482)Mehdi Amini
Reverts llvm/llvm-project#125736 The gcc7 Bot is broken at the moment.
2025-02-05[mlir] Python: Parse ModuleOp from file path (#125736)Nikhil Kalra
For extremely large models, it may be inefficient to load the model into memory in Python prior to passing it to the MLIR C APIs for deserialization. This change adds an API to parse a ModuleOp directly from a file path.
2025-02-05[mlir] Python: Extend print large elements limit to resources (#125738)Nikhil Kalra
If the large element limit is specified, large elements are hidden from the asm but large resources are not. This change extends the large elements limit to apply to printed resources as well.
2025-01-24[mlir:python] Compute get_op_result_or_value in PyOpView's constructor. ↵Peter Hawkins
(#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.
2025-01-22[mlir] Add C and Python interface for file range (#123276)Jacques Pienaar
Plumbs through creating file ranges to C and Python.
2025-01-22[mlir:python] Construct PyOperation objects in-place on the Python heap. ↵Peter Hawkins
(#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.
2025-01-22[mlir python] Change PyOpView constructor to construct operations. (#123777)Peter Hawkins
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.
2025-01-13[mlir python] Add locking around PyMlirContext::liveOperations. (#122720)Peter Hawkins
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.
2025-01-13Enabled freethreading support in MLIR python bindings (#122684)vfdev
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>
2025-01-12Revert "Added free-threading CPython mode support in MLIR Python bindings ↵Jacques Pienaar
(#107103)" Breaks on 3.8, rolling back to avoid breakage while fixing. This reverts commit 9dee7c44491635ec9037b90050bcdbd3d5291e38.
2025-01-12Added free-threading CPython mode support in MLIR Python bindings (#107103)vfdev
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>
2025-01-07Fixed typo in dunder get/set methods in PyAttrBuilderMap (#121794)vfdev
Description: - fixed a typo in the method name: dunde -> dunder