708 Commits

Author SHA1 Message Date
Krzysztof Drewniak
7fce7631a0
[mlir] Refactor opaque properties to make them type-safe (#185157)
At its core, this commit changes `OpaqueProperties` (aka a void*) to
`PropertyRef`, which is a {TypeID, void*}, where the TypeID is the ID of
the storage type of the given property (which can, as is often the case
for operations, be a struct of other properties).

Long-term, this change will allow for
1) Some sort of getFooPropertyRef() on property structs, allowing
individual members to be extracted generically
2) By having a property kind that is an OwningProprtyRef, generic
parsing (in combination with a bunch of other changes) 3) Probably a
safer C/Python API because we'll be able to indicate what's supposed to
be under a given void*

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 19:49:40 -07:00
Twice
e568136e94
[MLIR][Python] Add more field specifiers to Python-defined operations (#188064)
This PR adds two new field specifiers (`operand` and `attribute`) and
extends the existing one (`result`):
- `default_factory` parameter is added for `result` and `attribute` to
specify default value via a lambda/function
- `kw_only` parameter is added for all these three specifiers, to make a
field a keyword-only parameter (without giving a default value).

```python
def result(
    *,
    infer_type: bool = False,
    default_factory: Optional[Callable[[], Any]] = None,
    kw_only: bool = False,
) -> Any: ...


def operand(
    *,
    kw_only: bool = False,
) -> Any: ...


def attribute(
    *,
    default_factory: Optional[Callable[[], Any]] = None,
    kw_only: bool = False,
) -> Any: ...
```

Examples about how to use them:
```python
class OperandSpecifierOp(TestFieldSpecifiers.Operation, name="operand_specifier"):
    a: Operand[IntegerType[32]] = operand()
    b: Optional[Operand[IntegerType[32]]] = None
    c: Operand[IntegerType[32]] = operand(kw_only=True)

class ResultSpecifierOp(TestFieldSpecifiers.Operation, name="result_specifier"):
    a: Result[IntegerType[32]] = result()
    b: Result[IntegerType[16]] = result(infer_type=True)
    c: Result[IntegerType] = result(
        default_factory=lambda: IntegerType.get_signless(8)
    )
    d: Sequence[Result[IntegerType]] = result(default_factory=list)
    e: Result[IntegerType[32]] = result(kw_only=True)

class AttributeSpecifierOp(
    TestFieldSpecifiers.Operation, name="attribute_specifier"
):
    a: IntegerAttr = attribute()
    b: IntegerAttr = attribute(
        default_factory=lambda: IntegerAttr.get(IntegerType.get_signless(32), 42)
    )
    c: StringAttr["a"] | StringAttr["b"] = attribute(
        default_factory=lambda: StringAttr.get("a")
    )
    d: IntegerAttr = attribute(kw_only=True)
```

---------

Co-authored-by: Rolf Morel <rolfmorel@gmail.com>
2026-03-28 21:46:21 +08:00
Twice
1503293cbc
[MLIR][Python] Support has_trait for operations (#188492)
This PR adds a `has_trait(trait_cls)` API to `_OperationBase`, that can
be used for:
- C++-defined operations and C++-defined traits (e.g.
`func_return_op.has_trait(IsTerminatorTrait)`)
- Python-defined operations and C++-defined traits (e.g.
`my_python_op.has_trait(IsTerminatorTrait)`)
- Python-defined operations and Python-defined traits (e.g.
`my_python_op.has_trait(MyPythonTrait)`)

---------

Co-authored-by: Maksim Levental <maksim.levental@gmail.com>
2026-03-27 00:02:31 +08:00
Sergei Lebedev
8afb4620d6
[MLIR] [Python] Fixed a long standing bug in the PyRegionListIterator (#188475)
`PyRegionIterator` did not account for start index/step, so this commit
removes it in favor of the sequence iterator provided by CPython.

The previous attempt in #137232 bitrotted, so I decided to open a new
PR.
2026-03-25 16:01:35 +00:00
Tuomas Kärnä
7cb57c6808
[MLIR][XeGPU][TransformOps] Remove obsolete transform ops (#187561)
Cleaning up XeGPU transform ops. Now that XeGPU layout propagation
works, it is sufficient to set the layouts for anchor ops (e.g.
load/store/dpas ops) only.

Changes:
* Remove `xegpu.get_desc_op` and `xegpu.set_desc_layout`. Users should
not change the layout of descriptor op's return value anymore.
* Add `xegpu.get_load_op(value)` that finds either `xegpu.load_nd` or
`xegpu.load` op in the value's producer chain. This is a useful utility
as load ops often need to be annotated with a layout.
* The generic `xegpu.set_op_layout_attr(op, ...)` is now replaced by
`xegpu.set_anchor_layout(op, ...)` that only sets layout attribute of
anchor ops. Raises an error if the given op does not support anchor
layouts.
* `xegpu.insert_prefetch` takes a load op handle instead of a value.
2026-03-25 10:24:11 +02:00
Twice
6dabcef0b3
[MLIR][IRDL][Python] Fix error while composing irdl.any_of and irdl.base (#187914)
Previously, while users compose `irdl.any_of` and `irdl.base`, e.g.
```mlir
module {
  irdl.dialect @ext_attr_in_op {
    irdl.operation @op_with_attr {
      %0 = irdl.base "#builtin.integer" 
      %1 = irdl.base "#builtin.string" 
      %2 = irdl.any_of(%0, %1) 
      irdl.attributes {"a" = %2}
    }
  }
}
```

The program will crash due to `llvm_unreachable("unknown IRDL
constraint")`.

This PR implements `getBases(..)` for `irdl::BaseOp` to make this work.
This make fields like `attr: IntegerAttr | StringAttr` work in
Python-defined dialects, which led to a crash previously.
2026-03-23 08:47:53 +08:00
Twice
d818fa4c55
[MLIR][Python] Make init parameters follow the field definition order (#186574)
Currently, Python-defined operations automatically generate an
`__init__` function to serve as the operation builder. Previously, the
parameters of this `__init__` function followed a fairly complex set of
rules. For example:

* All result fields were moved to the front to align with other op
builders.
* Fields of `Optional` type were automatically moved to the end and
treated as keyword parameters.
* If the types of all result fields could be inferred automatically,
then all result fields were removed from the parameter list.
* Other than that, the parameter order followed the field definition
order.

These rules may seem reasonable, and they have worked well in practice,
but they have one major drawback: users cannot easily tell what the
actual `__init__` parameter list will look like when writing code,
because the rules are simply too complicated. Users can inspect the
signature at runtime via `MyOp.__init__.__signature__`, but this is
clearly poor for the development experience.

After some offline discussion with Rolf, we decided to replace this with
the following rules, which is what this PR implements:

* The parameters of `__init__` now strictly follow the field definition
order.
* By default, all parameters are required. A field becomes a keyword
parameter only if it is declared with `= None`.
* By default, no type inference is performed. A field becomes a keyword
parameter and participates in type inference only if it is declared with
`= infer_type()`.

These new rules give users full control over the `__init__` parameter
list, making it easy to understand the parameter order and explicitly
control optional parameters and type inference. In addition, this makes
it much easier in the future to use `dataclass_transform` so that type
checkers can understand these automatically generated `__init__`
methods, although there are still some issues to resolve at the moment.

NOTE that this is a **breaking change**. Even so, I still believe it is
worth making, mainly for two reasons:
- the current number of users of Python-defined dialects is still quite
limited;
- this change will bring long-term benefits.

Assisted by Copilot.
2026-03-22 00:48:14 +08:00
Maksim Levental
c3f381ccfe
[mlir-python] Fix duplicate EnumAttr builder registration across dialects. (#187191)
When multiple dialects share td `#includes` (e.g. `affine` includes
`arith`), each dialect's `*_enum_gen.py` file registers attribute
builders under the same keys, causing "already registered" errors on the
second import; the first commit checks in such a case which currently
fails on main:

```
# | RuntimeError: Attribute builder for 'Arith_CmpFPredicateAttr' is already registered with func: <function _arith_cmpfpredicateattr at 0x78d13cbe9a80>
```

This PR implements a two-pronged fix:

1. Add `allow_existing=True` to `register_attribute_builder` (and the
underlying C++ `registerAttributeBuilder`). When set, silently skips
registration if the key already exists (first-wins semantics). This
handles `EnumInfo`-based builders which have no dialect prefix (e.g.
`AtomicRMWKindAttr`, `Arith_CmpFPredicateAttr`), which may be emitted by
every dialect whose td file includes the defining file;
2. Filter `EnumAttr` builders by `-bind-dialect` in
`EnumPythonBindingGen.cpp` and register them under dialect qualified
keys (`"dialect.AttrName"`). Update `OpPythonBindingGen.cpp` to look up
the same qualified keys for EnumAttr typed op attributes (detected via
`isSubClassOf("EnumAttr")`). Pass `-bind-dialect` from
`AddMLIRPython.cmake`.

This approach incurs no changes to `ir.py` registrations (no "builtin."
prefix), and no manual builder additions to individual dialect Python
files (unlike the previous attempt
https://github.com/llvm/llvm-project/pull/117918).

Note, this PR was "clauded" not "coded".
2026-03-19 21:02:23 -07:00
srcarroll
333f6abe30
Reland Support float8_e3m4 and float8_e4m3 in np_to_memref (#186453) (#186833)
This patch adds support for `float8_e3m4` and `float8_e4m3` in
`np_to_memref.py` by adding the appropriate ctypes structures.
Additionally changes minimum numpy version to 2.1.0 and uses a single
ml_dtypes version of 0.5.0.
2026-03-17 12:11:09 -05:00
Maksim Levental
e3d7bf290d
[MLIR][LLVM] add metadata attrs and llvm.named_metadata op (#186703)
This PR adds some LLVM metadata attributes and an `llvm.named_metadata`
container op (similar to `llvm.module_flags`) for those attributes.

Summary:

- Add MLIR attributes modeling LLVM IR metadata: `#llvm.md_string`,
`#llvm.md_const`, `#llvm.md_func`, and `#llvm.md_node`;
- Add `llvm.named_metadata` container op for module-level named metadata
nodes;
  - Add MLIR-to-LLVM-IR translation for the new attributes and op;
- Add C API functions (`mlirLLVMMDStringAttrGet`,
`mlirLLVMMDNodeAttrGet`, etc.);
- Add Python bindings (`llvm.MDStringAttr`, `llvm.MDConstantAttr`,
`llvm.MDFuncAttr`, `llvm.MDNodeAttr`, `llvm.FunctionType`).
2026-03-16 16:33:53 -07:00
srcarroll
9e22690671
Revert "Support float8_e3m4 and float8_e4m3 in np_to_memref (#186453)" (#186677)
This reverts commit 57427f84fe5fdda71aef4be257ed28d7b4f55d05.

For some reason mlir-nvidia CI is failing to import `float8_e3m4` from
`ml_dtypes`. See
https://lab.llvm.org/buildbot/#/builders/138/builds/27095.
2026-03-15 11:52:59 -05:00
srcarroll
57427f84fe
Support float8_e3m4 and float8_e4m3 in np_to_memref (#186453)
This patch adds support for `float8_e3m4` and `float8_e4m3` in
`np_to_memref.py` by adding the appropriate ctypes structures
2026-03-15 09:35:32 -05:00
Twice
044776691a
[MLIR][Python] Refine the behavior of Python-defined dialect reloading (#186128)
This includes several changes:
- `Dialect.load(reload=False)` will fail if the dialect was already
loaded in a different context. To prevent the further program abortion.
- `Dialect.load(reload=True)` implies `replace=True` in
dialect/operation registering.
- `PyGlobals::registerDialectImpl` now has a parameter `replace`.
- `register_dialect` and `register_operation` is no longer exposed in
`mlir.dialects.ext`.

This should solve the registering problem found in writing transform
test cases by @rolfmorel.
2026-03-15 10:25:24 +08:00
RattataKing
39b3b2e0e8
[MLIR][Python] Add type filter to walk() binding and add get_ops_of_type() utility (#186131)
MLIR's C++ `Operation::walk` supports type-filtered traversal (e.g.
`op->walk([](arith::AddIOp op) { ... })`), but the Python binding
`op.walk()` requires users to manually implement type filtering inside
the callback function.

This PR adds type filtering into the python binding `op.walk()`, if
users pass `op_class`, walk() will only apply callback to matching ops.

This PR also adds a common use helper in mlir/ir that collects all ops
of a given type into a list. Users can just call: `ops =
ir.get_ops_of_type(root, op_class)`.
2026-03-13 13:36:30 -04:00
Asher Mancinelli
9cee895333
[mlir][llvm] Expose llvm array type to CAPI and Python bindings (#185475)
This PR mostly copies everything to do with llvm.struct in the CAPI and
search-and-replaces `struct` with `array`.

Assisted-by: claude opus 4.6
2026-03-13 09:43:37 -07:00
Twice
eb687fb106
[MLIR][Python] Make location optional in Python-defined dialect loading (#186172)
Now we need to provide a location when call `load()`, e.g.
```python
with Context(), Location.unknown():
  MyDialect.load()
```

But it's actually weird: IRDL is just an implementation details, so for
users they don't know why they need to provide a location for loading a
dialect, which is unrelated to constructing an IR module.

This PR made location optional for dialect loading.
2026-03-13 10:17:26 +08:00
RattataKing
29cd7921bc
[MLIR][Python] Add get_parent_of_type helper (#185512)
The `op.parent` only returns the immediate parent, in which case
downstream users have to traverse the operation by themselves to find a
specific type op.
This PR adds a python function `get_parent_of_type()` to mlir.ir to
provide an API to do so.

The function mirrors the implementation here:

https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/IR/Operation.h#L257-L273.
Instead of creating a new binding, reimplement it in python using
`isinstance()` is simpler.
2026-03-10 12:11:51 -04:00
Charitha Saumya
ce227964cc
[mlir][xegpu] Add support for setting order in SetDescLayoutOp and SetOpLayoutAttrOp transform ops. (#184705)
Currently XeGPU transform dialect does not allow the user to set the
`order` attribute of a layout in `SetDescLayoutOp` and
`SetOpLayoutAttrOp`. This PR adds `order` as an optional argument to
these transform ops.
2026-03-09 08:37:28 -07:00
Jakub Kuderski
15e7177f08
[mlir][GPU] Fix double spaces in tests after ODS printer fix. NFC. (#185325)
Follow-up to #184253. The ODS attr/type printer fix removed the leading
space from generated print() methods. Update tests that checked for the
old double-space output of GPU ops using GPU_DimensionAttr and
GPU_MmaElementwiseOpAttr.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:46:54 -04:00
Jakub Kuderski
4df95b1a56
[mlir][NVVM] Fix double spaces in tests after ODS printer fix. NFC. (#185326)
Follow-up to #184253. Update tests that checked for the old double-space
output of NVVM ops using ReductionKindAttr, ShflKindAttr, and
LoadCacheModifierAttr.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:46:46 -04:00
Erick Ochoa Lopez
613a5c555e
[mlir][vector] Replace OneDimMultiReductionToTwoDim with OneDimMultiReductionToReduction (#184241)
The `OneDimMultiReductionToTwoDim` pattern had some issues. For the
input program:

```mlir
func.func @rank1_multi_reduction(%arg0: vector<8xf32>, %acc: f32) -> f32 {
    %0 = vector.multi_reduction <add>, %arg0, %acc [0] : vector<8xf32> to f32
    return %0 : f32
}
```

* when lowering using the inner-parallel strategy, the compiler would
essentially produce scalar code:
```mlir
func.func @rank1_multi_reduction(%arg0: vector<8xf32>, %arg1: f32) -> f32 {
    %0 = vector.shape_cast %arg0 : vector<8xf32> to vector<1x8xf32>
    %1 = vector.broadcast %arg1 : f32 to vector<1xf32>
    %2 = vector.transpose %0, [1, 0] : vector<1x8xf32> to vector<8x1xf32>
    %3 = vector.extract %2[0] : vector<1xf32> from vector<8x1xf32>
    %4 = arith.addf %3, %1 : vector<1xf32>
    %5 = vector.extract %2[1] : vector<1xf32> from vector<8x1xf32>
    %6 = arith.addf %5, %4 : vector<1xf32>
    ... (repeats for all 8 elements) ...
    %17 = vector.extract %2[7] : vector<1xf32> from vector<8x1xf32>
    %18 = arith.addf %17, %16 : vector<1xf32>
    %19 = vector.extract %18[0] : f32 from vector<1xf32>
    return %19 : f32
}
```
* when lowering using the inner-reduction strategy, the compiler would
first unnecessarily transform it into a 2-D multi_reduction operation
<1x8xf32> and then extract an <8xf32> vector and apply reduction. The
canonicalization and folding would lead to the following final result:
```mlir
func.func @rank1_multi_reduction(%arg0: vector<8xf32>, %arg1: f32) -> f32 {
    %0 = vector.reduction <add>, %arg0, %arg1 : vector<8xf32> into f32
    return %0 : f32
}
```

Now, after this change:
* when lowering the compiler now produces for both strategies in one
step.
```
func.func @rank1_multi_reduction(%arg0: vector<8xf32>, %arg1: f32) -> f32 {
    %0 = vector.reduction <add>, %arg0, %arg1 : vector<8xf32> into f32
    return %0 : f32
}
```

This pattern is also useful for an ongoing refactoring that is happening
in the multi_reduction patterns. It is the only pattern that increases
multi_reduction in rank and would lead to an infinite loop when
attempting to reach a fixed point once we generalize other unrolling
patterns.

Assisted-by: Claude
2026-03-04 16:13:11 +00:00
Rolf Morel
756d068ead
[MLIR][Python][Transform] Expose PatternDescriptorOpInterface to Python (#184331)
Makes it possible to include Python-defined rewrite patterns in
transform-dialect schedules, inside of `transform.apply_patterns`, which
upon execution of the schedule runs the pattern in a greedy rewriter.

With assistance of Claude.
2026-03-04 10:19:59 +00:00
Twice
e95dabef96
[MLIR][Python] Support attribute definitions in Python-defined dialects (#183907)
This PR is quite similiar to
https://github.com/llvm/llvm-project/pull/182805.

We added basic support of attribute definitions in Python-defined
dialects, including:

- IRDL codegen for attribute definitions
- Attr builders like `MyAttr.get(..)` and attr parameter accessors (e.g.
`my_attr.param1`)
- Use Python-defined attrs in Python-defined operations

Assisted by GitHub Copilot.
2026-03-02 09:57:25 +08:00
Jakub Kuderski
2c9720972e
[mlir][python] Add stable ABI (abi3) support (#183856)
Add `MLIR_ENABLE_PYTHON_STABLE_ABI` cmake flag to build bindings against
the Python limited/stable API (abi3 / PEP 384). This allow for
compatibility across different >=3.12 versions with a single .so /
wheel. We also require CMake >=3.26.

The stable ABI restricts usage to a subset of the CPython C API: frame
and code object structs are opaque, so introspection APIs like
`PyCode_Addr2Location`, `PyFrame_GetLasti`, and `PyFrame_GetCode` are
unavailable. The traceback-based auto-location logic is dropped because
we don’t have stable ABI to produce complete locations.

Assisted-by: claude
2026-03-01 13:45:52 +00:00
Mehdi Amini
785490e9db
[MLIR] Remove let constructor = from mlir/include/mlir/Transforms/Passes.td (#183950)
This makes the constructor auto-generated.
2026-03-01 13:51:23 +01:00
Twice
4673cecc89
[MLIR][Python] Add support of convert_region_types and the bf integration test (#183664)
This PR adds the `convert_region_types` API to
`ConversionPatternRewriter` and introduces a new integration test,
`bf.py`, which demonstrates how to combine a Python-defined dialect, the
dialect conversion API, the pass manager, and the execution engine to
build a pure-Python JIT compilation pipeline.
2026-03-01 09:55:33 +08:00
Twice
361e235986
[MLIR][Python] Support op adaptor for Python-defined operations (#183528)
Previously, in #177782, we added support for dialect conversion and
generated an `OpAdaptor` subtype for every ODS-defined operation. In
this PR, we will also generate `OpAdaptor` subtypes for Python-defined
operations, so that they can be applied in dialect conversion as well.
2026-02-27 09:13:24 +08:00
Twice
e2d2b23a5a
[MLIR][Python] Add convert_type API for TypeConverter (#183561)
This PR adds the  `convert_type` API for `TypeConverter`.
2026-02-27 00:30:00 +08:00
Adam Siemieniuk
67ac275fee
[mlir][x86] Rename x86vector to x86 (#183311)
Renames 'x86vector' dialect to 'x86'.

This is the first PR in series of cleanups around dialects targeting x86
platforms.
The new naming scheme is shorter, cleaner, and opens possibility of
integrating other x86-specific operations not strictly fitting pure
vector representation. For example, the generalization will allow for
future merger of AMX dialect into the x86 dialect to create one-stop x86
operations collection and boost discoverability.
2026-02-26 11:21:58 +01:00
Twice
d7bd36d7e9
[MLIR][Python] Handle errors in dialect conversion properly (#183320)
Before this, MLIR error capture in `apply_partial_conversion` and
`apply_full_conversion` wasn’t handled, which meant any `emitError`
would crash the entire program. This PR adds the handling.
2026-02-26 10:22:24 +08:00
Twice
3f6648422c
[MLIR][Python] Fix typeid support for DynamicType and DynamicAttr (#183076)
Previously, we were using the static `typeid` of `DynamicType` for
checks, which is incorrect. We should instead check against the `typeid`
of `DynamicTypeDefinition` (which is a subclass of `SelfOwningTypeID`),
and register it via `register_type_caster` so that Python-defined types
can use `maybe_downcast`. (The attribute part is same.)
2026-02-25 21:58:13 +08:00
Srinivasa Ravi
43dfde4a07
[MLIR][NVVM] Enable result type inference (#181781)
Includes `InferOpTypeInterface.td` in `NVVMOps.td` enabling result type
inference for NVVM operations.

Fixes a test for `nvvm.redux.sync` in `nvvm.py` due to a resulting
change in the python binding for the operation.
2026-02-25 10:27:25 +05:30
Rahul Kayaith
7160a4409a
[mlir][python] Fix segfault in DenseResourceElementsAttr.get_from_buffer for 0-d tensors (#183070)
When `ndim == 0`, `view->strides[view->ndim - 1]` is an out-of-bounds
access (unsigned underflow to `SIZE_MAX`). Use `view->itemsize` for
alignment instead, since a scalar buffer is trivially aligned to its
element size.

Fixes iree-org/iree-turbine#1312.
2026-02-24 11:01:58 -05:00
Twice
3b2c1db870
[MLIR][Python] Support type definitions in Python-defined dialects (#182805)
In this PR, we added basic support of type definitions in Python-defined
dialects, including:
- IRDL codegen for type definitions
- Type builders like `MyType.get(..)` and type parameter accessors (e.g.
`my_type.param1`)
- Use Python-defined types in Python-defined oeprations

```python
class TestType(Dialect, name="ext_type"):
    pass

class Array(TestType.Type, name="array"):
    elem_type: IntegerType[32] | IntegerType[64]
    length: IntegerAttr

class MakeArrayOp(TestType.Operation, name="make_array"):
    arr: Result[Array]

class MakeArray3Op(TestType.Operation, name="make_array3"):
    arr: Result[Array[IntegerType[32], IntegerAttr[IntegerType[32], 3]]]
```
2026-02-24 10:34:58 +08:00
Twice
de3cefe560
[MLIR][Python] Add C and Python API for mlir::DynamicAttr (#182820)
This PR adds C and Python API support for `mlir::DynamicAttr`. It
primarily enables attributes in dialects that are dynamically generated
via IRDL to be constructed in Python, and allows retrieving the
parameters contained in a dynamic attribute from Python.

This PR is quite similiar to #182751, so I use tab to autocomplete some
code via github copilot, but manually verified.
2026-02-23 17:26:08 +08:00
Twice
059accca53
[MLIR][Python] Add Python and C API of mlir::DynamicType (#182751)
This PR adds C and Python API support for `mlir::DynamicType`. It
primarily enables types in dialects that are dynamically generated via
IRDL to be constructed in Python, and allows retrieving the parameters
contained in a dynamic type from Python.

---------

Co-authored-by: Rolf Morel <rolfmorel@gmail.com>
2026-02-23 12:14:56 +08:00
Twice
8542514e5c
[MLIR][Python] Allow passing dialect as a class keyword argument (#182465)
Previously, we constructed new ops using the pattern `class
MyOp(MyInt.Operation)`.

Now we’ve added a new pattern: `class MyOp(Operation, dialect=MyInt)`,
which allows more flexible composition. For example:
```python
class BinOpBase(Operation): # it can be used in any dialect!
  res: Result[Any]
  lhs: Operand[Any]
  rhs: Operand[Any]
  
class MyInt(Dialect, name="myint"):
  pass

class AddOp(BinOpBase, dialect=MyInt, name="add"):
  ...
```
2026-02-22 18:52:57 +08:00
Erick Ochoa Lopez
eeb6b394c5
[mlir][vector] remove lower_multi_reduction (#182332)
* Removes `ApplyLowerMultiReductionPatternsOp`
(`apply_patterns.vector.lower_multi_reduction`)
* Updates uses of `apply_patterns.vector.lower_multi_reduction` in tests
to use:
  *  reorder_and_expand_multi_reduction_dims
  * multi_reduction_flattening
   * multi_reduction_unrolling
* Removes `populateVectorMultiReductionLoweringPatterns` (unused)
2026-02-20 08:33:24 -05:00
Erick Ochoa Lopez
f33f9a0cf5
[mlir][vector] Add apply_patterns.vector.multi_reduction_unrolling. (#182113)
* Adds vector transform op
`apply_patterns.vector.multi_reduction_unrolling`
* Adds test for `populateVectorMultiReductionUnrollingPatterns`
* Deletes old test files `vector-multi-reduction-lowering.mlir` and
`vector-multi-reduction-lowering-outer.mlir`. Tests that exercise these
patterns exist in `vector-multi-reduction-flattening.mlir`,
`vector-multi-reduction-reorder-and-expand.mlir` and
`vector-multi-reduction-unrolling.mlir`

Assisted-by: claude
2026-02-19 16:19:58 -05:00
Erick Ochoa Lopez
6ec5c1e368
[mlir][vector] Add multi_reduction_flattening (#181244)
* Adds tests for `populateVectorMultiReductionFlatteningPatterns`
* Add apply_patterns.vector.multi_reduction_flattening transform op.

This follows PR #180977. 

Assisted-by: claude
2026-02-18 14:40:24 -05:00
Erick Ochoa Lopez
3cf4156198
[mlir][vector] add ApplyReorderMultiReductionDimsPatternsOp tests (#180977)
With the new finer grained populate methods introduced in
8dde3051504cb9ae42e654bbce39001f3946beea (#180750), there was a
discussion about refactoring tests such that only one of the patterns
applies at a time. This commit starts this process by adding the
structure for one of these populate methods. The goal is for the
populate methods to have their own file (each showing inner and outer
reduction); deprecating populateVectorMultiReductionLoweringPatterns and
ApplyLowerMultiReduction; and removing the test file for
mlir/test/Dialect/Vector/vector-multi-reduction-lowering.mlir

Essentially an NFC. It also adds a new transform op for testing the
dialect and which downstream projects may choose to use.

Assisted-By: claude-4.5-sonnet
2026-02-17 16:14:59 -05:00
Tuomas Kärnä
48566b21a4
[MLIR][XeGPU][TransformOps] set_op_layout_attr supports setting anchor layout (#172542)
Changes `transform.xegpu.set_op_layout_attr` to support xegpu anchor
layouts. By default, if `result` and `operand` bool arguments are unset,
this transform op sets the op's anchor layout, if the op supports it
(otherwise emits a silenceable failure).

In contrast to the earlier implementation, setting the operand layout
now requires setting the new `operand` argument.
2026-02-13 07:49:59 +02:00
Rolf Morel
a1d7cda1d7
[MLIR][Python] Impl XOpInterface(s) from Python, with X=Transform and X=MemoryEffects (#176920)
Provides the infrastructure for implementing and late-binding
OpInterfaces from Python.

* On the mlir-c API declaration side, each `XOpInterface` has a callback
struct, with a callback for each method and a userdata member (provided
as an arg to each method), and a
`mlirXOpInterfaceAttachFallbackModel(ctx, op_name, callbacks)` func.
* This CAPI is implemented by defining a subclass of
`XOpInterface::FallbackModel` that holds the callback struct and has
each method call the corresponding callback (with userdata as an arg).
Given a callback struct, a new `FallbackModel` is created and attached,
i.e. late bound, to the named op. (MLIR's interface infrastructure is
such that the thus registered `FallbackModel` will be returned in case
the op gets cast to the `XOpInterface`.)
* On the Python side, we expose a stand-in `XOpInterface` base class
which has one (class)method: `XOpInterface.attach(cls, op_name, ctx)`.
Python users subclass this class (`class MyInterfaceImpl(XOpInterface):
...`) and implement the interface's methods (with the right names and
signatures). The user calls `attach` on the subclass
(`MyInterfaceImpl.attach("my_dialect.my_op", ctx)`) which prepares the
callbacks struct _with userdata set to the subclass_ (as we use it to
lookup methods). These callbacks (and userdata) are then registered as
an `XOpInterface::FallbackModel` by
`mlirXOpInterfaceAttachFallbackModel(...)`. From then on the Python
methods will be used to respond to calls to the interface methods
(originating in C++).

This PR enables implementing the TransformOpInterface and the
MemoryEffectsOpInterface, both of which are required for making an op
into a transform op.

Everything besides the above linked code is there to facilitate exposing
the interfaces: the right types for the arguments of the methods are
exposed as are functions/methods for manipulating these arguments (e.g.
specifying side effects on `OpOperand`s and `OpResult`s and being able
to access and set the transform handles associated with args and
results).
2026-02-12 14:07:10 +00:00
Matthias Springer
c6964b1b4d
[mlir][IR] DenseElementsAttr: Remove i1 dense packing special case (#180397)
`DenseElementsAttr` stores elements in a `ArrayRef<char>` buffer, where
each element is padded to a full byte. Before this commit, there used to
be a special storage format for `i1` elements: they used to be densely
packed, i.e., 1 bit per element. This commit removes the dense packing
special case for `i1`.

This commit removes complexity from `DenseElementsAttr`. If dense
packing is needed in the future it could be implemented in a general way
that works for all element types (based on #179122).

Discussion:
https://discourse.llvm.org/t/denseelementsattr-i1-element-type/62525
2026-02-11 15:56:08 +00:00
Twice
972aa597de
[MLIR][Python] Make traits declarative in python-defined operations (#180748)
This will support two syntax in python-defined dialects.

First is that traits can now be declared in class parameters, e.g.
```python
class ParentIsIfTrait(DynamicOpTrait): #define a python-side trait
    @staticmethod
    def verify_invariants(op) -> bool:
        if not isinstance(op.parent.opview, IfOp):
            op.location.emit_error(
                f"{op.name} should be put inside {IfOp.OPERATION_NAME}"
            )
            return False
        return True

class YieldOp( # attach two traits: IsTerminatorTrait, ParentIsIfTrait
    TestRegion.Operation, name="yield", traits=[IsTerminatorTrait, ParentIsIfTrait]
):
    ...
```

Second is that users can directly define
`verify_invariants`/`verify_region_invariants` methods in the operation
to add additional custom verification logic. And this is implemented via
traits.
```python
class YieldOp(TestRegion.Operation, name="yield", ...):
    value: Operand[Any]

    def verify_invariants(self) -> bool: # define a method directly
        if self.parent.results[0].type != self.value.type:
            self.location.emit_error(
                "result type mismatch between YieldOp and its parent IfOp"
            )
            return False
        return True
```

Previously we use `verify`/`verify_region` as method names (in
yesterday's PR #179705), but in this PR they are renamed to
`verify_invariants`/`verify_region_invariants` because there are
conflicts between the newly-added `verify` method and `ir.OpView.verify`
method:
- `verify_invariants` is just to attach **additional** verification
logic. but `OpView.verify` is to construct an OperationVerifer and do
full verification for an operation, so the semantics is not same between
these two. We should not shadow the `OpView.verify` method by defining a
new semantically-different `verify` method.
- it will make users confuse between these two `verify` methods, since
they have different meaning.
- if users didn't define the `verify` method in their python-defined
operation, `DynamicOpTraits.attach(opname, MyOpCls)` still do the
attaching (because `hasattr("verify")` returns `True`) and seg fault
(because we cannot attach `OpView.verify`).

---------

Co-authored-by: Rolf Morel <rolfmorel@gmail.com>
2026-02-11 20:39:58 +08:00
Twice
fccbdcb15a
[MLIR][Python] Support dynamic traits in python-defined dialects (#179705)
This is a follow-up PR of #169045 and the second part of #179086.

In #179086, we added support for defining regions in Python-defined ops,
but its usefulness was quite limited because we still couldn’t mark an
op as a `Terminator` or `NoTerminator`. In this PR, we port the
`DynamicOpTrait` (introduced on the C++ side for `DynamicDialect` in
#177735) to Python, so we can dynamically attach traits to
Python-defined ops.
2026-02-09 22:26:56 +08:00
Arun Thangamani
fe91384a5b
[mlir][vector] Wrapping populateFlattenVectorTransferPatterns as a transform pass. (#178134)
This PR covers the `mlir::vector::populateFlattenVectorTransferPatterns`
as a transform pass.
2026-02-09 15:10:51 +05:30
Adam Siemieniuk
ba58225a0a
[mlir][x86vector] Python bindings for x86vector dialect (#179958)
Registers python bindings for x86vector dialect and transform ops.
2026-02-05 20:05:17 +01:00
Twice
cb274ea176
[MLIR][Python] Support region in python-defined dialects (#179086)
This PR adds basic support for defining regions in Python-defined
dialects. Example usage:

```python
class TestRegion(Dialect, name="ext_region"):
    pass

class IfOp(TestRegion.Operation, name="if"):
    cond: Operand[IntegerType[1]]
    then: Region
    else_: Region
```

Current limitations:

* We can’t specify region constraints yet (e.g., number of blocks or
block argument types). This will be addressed as a follow-up task.
* We can’t mark an op as a `Terminator` or `NoTerminator` yet. This
depends on `DynamicOpTraits` (#177735) and Python-side trait API
support, and will be implemented in a follow-up PR.

This is the first PR after splitting off #179032.

This is a follow-up PR of #169045.

---------

Co-authored-by: Rolf Morel <rolfmorel@gmail.com>
2026-02-02 22:11:22 +08:00
Twice
f992f9719f
[MLIR][Python] Support dialect conversion in python bindings (#177782)
This PR adds dialect conversion support to the MLIR Python bindings.
Because it introduces a number of new APIs, it’s a fairly large PR. It
mainly includes the following parts:

* Add a set of types and APIs to the C API, including
`MlirConversionTarget`, `MlirConversionPattern`, `MlirTypeConverter`,
`MlirConversionPatternRewriter`, and others.
* Add the corresponding types and APIs to the Python bindings.
* Extend `mlir-tblgen` with codegen for Python adaptor classes, which
generates an adaptor class for each op.

Note that this PR only adds support for 1-to-1 conversions, 1-to-N
type/value conversions are not supported yet.

---------

Co-authored-by: Maksim Levental <maksim.levental@gmail.com>
2026-01-31 12:37:49 +08:00