1086 Commits
Author SHA1 Message Date
Jeremy Kun 3349d8e7d3 [NFC][mlir][nvvm] move OptimizeForNVVM to its own directory (#206520)
This change moves the NVVM optimizations in the LLVM Dialect directory
to a dedicated `mlir/lib/Dialect/NVVM/Transforms/` directory.

Cf.
https://discourse.llvm.org/t/rfc-separate-gpu-specific-transforms-from-llvmirtransforms/91151
2026-06-29 22:17:29 +00:00
dGinten b87fe380d7 [mlir][docs] Add page for third-party tutorials (#188080)
Add a new page to the MLIR documentation that links to the
upstream Lighthouse project as well as additional third-party tutorials.
The goal is to make it easier for newcomers to discover MLIR learning
resources beyond the Toy tutorial.

The underlying discussion/RFC can be found
[here](https://discourse.llvm.org/t/rfc-tutorial-a-beginner-friendly-end-to-end-mlir-compiler-pipeline/89788).
2026-06-16 21:12:05 +02:00
Jameson Nash 7daddf2b6f [docs] try again to handle doxygen everywhere (#203081)
The previous attempt at this (b7da956501)
still broke standalone builds. Now I have locally tested standalone
flang, runtimes (with openmp), lldb, combined builds, and the utils
script. Hopefully that covers everything this time, and gets everything
into a more consistent state (always using the HandleDoxygen script in
the same way, included exactly once as required by the cmake design).
2026-06-11 08:58:36 -04:00
Mehdi Amini 831ed97b12 [mlir][LangRef] Clarify terminator continuations (#201111)
Document that terminators may have no normal control-flow continuation,
such as ub.unreachable. Also clarify that no-return calls do not remove
the structural terminator requirement.

Assisted-by: Codex
2026-06-11 14:12:06 +02:00
Jameson NashandAiden Grossman b7da956501 [docs] update CI to use latest release of doxygen (#202420)
Resubmitting https://github.com/llvm/llvm-project/pull/191501 for
review, with added https://github.com/llvm/llvm-project/pull/202404 for
SHA checksum verification and fix for cmake target name conflicts.
Tested with `./llvm/utils/release/build-docs.sh -no-sphinx` locally.

Co-authored-by: Aiden Grossman <aidengrossman@google.com>
2026-06-10 10:25:33 -04:00
Jameson Nash 50088e2275 Revert "[docs] update CI to use latest release of doxygen" (#202412)
Reverts llvm/llvm-project#191501 as cmake CI is having an issue with it:

```
-- Doxygen enabled (1.14.0).
CMake Error at /work/as-worker-4/publish-doxygen-docs/llvm-project/cmake/Modules/HandleDoxygen.cmake:29 (add_custom_target):
  add_custom_target cannot create target "doxygen" because another target
  with the same name already exists.  The existing target is a custom target
  created in source directory
  "/work/as-worker-4/publish-doxygen-docs/llvm-project/llvm".  See
  documentation for policy CMP0002 for more details.
Call Stack (most recent call first):
  docs/CMakeLists.txt:59 (include)
```
2026-06-08 15:28:03 -04:00
Jameson Nash 2eed192c21 [docs] update CI to use latest release of doxygen (#191501)
Previously this was likely 1.9.8, with the Ubuntu 24.04 worker. Now this
is 1.17.0. This is a fix for
https://discourse.llvm.org/t/many-doxygen-links-are-broken/83809/2.

Fixes 3 significant issues for LLVM:

- `dot` execution performance is very slow (cuts this half hour step
down to mere seconds). https://github.com/doxygen/doxygen/pull/12037
- multi-thread performance is very slow (worse than single threading),
and now uses all cores for ncpu times speedup (when using version with
fix, autodetected by cmake).
https://github.com/doxygen/doxygen/pull/12027
- file links for IR.cpp and similar files were wrong
https://github.com/doxygen/doxygen/pull/11944

Assisted-by: Claude Code
2026-06-08 13:17:05 -04:00
Fangrui Song f7f6e6f401 [mlir] Remove unused DenseMapInfo::getEmptyKey (#201991)
After #201281 DenseMapInfo<T>::getEmptyKey() is no longer used by
DenseMap. Remove the unused getEmptyKey definitions and dead sentinel
uses.
2026-06-06 12:33:34 -07:00
Matthias SpringerandMehdi Amini 67aaa03dac [mlir][IR] Add builtin TokenType (#195640)
Introduces a new parameterless, opaque, builtin SSA value type,
`!token`. A token cannot appear in a value-forwarding position such as
`cf.br`, `arith.select`, `scf.for` iter-args or function call/return.
Walking back from any token use reaches the producing operation without
crossing such a boundary. Tokens carry no runtime data and cannot
constant-fold.

This contract is enforced by changing the default ODS `AnyType`
predicate to exclude tokens. In addition, token-producing and
token-consuming ops must opt in by implementing the `ProducesToken` and
`ConsumesToken` traits. The IR verifier checks for the presence of these
traits.

Note: CSE, DCE, hoisting, and `OperationEquivalence` remain unchanged. A
stronger contract (e.g., uniqueness, arity, paired lifetime), if
desirable based on the semantics of token-producing and token-consuming
ops, can be expressed at the op level via existing mechanisms (side
effects, block arguments, traits, attributes), keeping the type
orthogonal to operation-level transformations. This mirrors LLVM's
`token` type.

Other changes:
* Builtin bytecode: new entry for `TokenType`.
* AsmParser / AsmPrinter: `token` keyword for the textual format.
* Remove `LLVMTokenType` from the LLVM dialect and use the builtin
`TokenType` instead.
* Async dialect: references to `async::TokenType` are qualified to
disambiguate from the new builtin `TokenType`.
* Documentation: new `mlir/docs/Tokens.md` covering the structural
contract, design rationale, and ODS integration.

No changes to `Operation`, the generic op syntax, the bytecode op
encoding, or core C++ APIs around `Operation`.

This commit is in preparation of adding support for breaking exit from
regions. (E.g., early exit from loops.)

RFC:
https://discourse.llvm.org/t/rfc-add-a-builtin-token-type-to-mlir/90706

Assisted-by: claude-opus-4.7-thinking-high

---------

Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2026-06-02 12:33:46 +02:00
Fangrui Song 4b91251dd8 [mlir] Remove unused DenseMapInfo::getTombstoneKey (#200633)
#200595 changed DenseMap to no longer create tombstone buckets, so
DenseMapInfo<T>::getTombstoneKey() is never called. Remove dead
definitions and dead tombstone branches.
2026-06-01 14:27:21 -07:00
Maximilian Ehlers 5d20fd3280 [mlir] Fix typo in toy tutorial (#200640)
Signed-off-by: Maximilian Ehlers <maximilian@sodawa.com>
2026-05-31 12:12:24 +00:00
AidinT 92a37ea073 [mlir][docs] Fix bugs in data flow analysis code example (#198200)
Some minor changes to avoid compilation errors.
1. `MetadataLatticeValue` doesn't define an `insert` method.
2. `it` (the one that changed) and `rhsIt` are both iterators.
2026-05-21 18:44:43 +02:00
Jeremy Kun 6a9c3b64a8 Add a more complete example to mlir-reduce docs (#116085)
This PR was started because I noticed bugs in the docs:

- The interestingness test checked for an error, but did not redirect
stderr to stdout to include it in the pipe.
- The interestingness test pipe ended with grep, but then checked for an
exit code of 1 to mark the input as interesting. However, a pipe's
overall exit code is the exit code of the rightmost command, and grep's
exit code is zero when it detects the query string, and 1 when it does
not detect the query string. So the test was backwards.

Then I wanted to test my fixes to be sure I got it right, and I realized
that the doc has no properly runnable example. This PR adds a working
example. h/t @aidint for fixing up the input.
2026-05-07 18:34:41 +00:00
Henrich Lauko 81bdba1fee [MLIR] Add HasAncestor op trait (#195447)
Add HasAncestor/AncestorOneOf traits that verify an operation has a
specific ancestor anywhere in the parent chain, unlike HasParent which
only checks the immediate parent.
2026-05-05 07:00:30 +02:00
Jeremy Kun 11e7f6c844 [milr] [docs] add view-op-graph and dump-pass-pipeline as useful CLI options (#194419)
Also fixes a typo and a rendering issue with the TOC
2026-04-27 11:40:14 -07:00
Sergio Afonso d6061d297d [Flang][OpenMP] Add pass to replace allocas with device shared memory (#161863)
This patch introduces a new Flang OpenMP MLIR pass, only ran for target
device modules, that identifies `fir.alloca` operations that should use
device shared memory and replaces them with pairs of
`omp.alloc_shared_mem` and `omp.free_shared_mem` operations.

This works in conjunction to the MLIR to LLVM IR translation pass'
handling of privatization, mapping and reductions in the OpenMP dialect
to properly select the right memory space for allocations based on where
they are made and where they are used.

This pass, in particular, handles explicit stack allocations in MLIR,
whereas the aforementioned translation pass takes care of implicit ones
represented by entry block arguments.
2026-04-27 13:14:19 +01:00
Matthias Springer d4974dfe67 [mlir][docs] Add poison example to canonicalization section (#192782)
Mention that folding to `ub.poison` is a common canonicalization.
2026-04-19 10:51:52 +01:00
Romain Paquet b87f23a38e [mlir][docs] Rename fusion option name in MlirOpt tutorial (#184635)
Options have been renamed in #128405
2026-04-18 00:27:08 +00:00
Twice 2874480930 [MLIR][Python] Migrate result(infer_type=True) to a new field specifier (#191849)
Currrently the signature of `result(..)` is:
```python
result(*, infer_type: bool = False, default_factory: Callable[[], Any] | None = None, kw_only: bool = False) -> Result
```

so when users use `result(infer_type=True)`, the type checkers will
still get `kw_only=False` (from the signature), but actually the
`kw_only` should be `True` (it should follow the value of `infer_type`).
users can use `result(infer_type=True, kw_only=True)` but it's
unnecessarily verbose.

So it may introduce an incompatibility when we start to use
`dataclass_transform`. currently it's fine because we just don't use
`dataclass_transform`. But when we use, we may require a breaking
change.

This PR migrates such use to a new field specifier named
`infer_result()`.
2026-04-14 10:45:28 +08:00
Tom Eccles d243d55ce4 [mlir][OpenMP] Rename omp.taskloop to omp.taskloop.wrapper (#188071)
Rename the loop wrapper operation to better distinguish it from the
context op (omp.taskloop.context), which handles outlining and runtime
calls. The new name makes the role of each operation clearer at a
glance.

RFC:
https://discourse.llvm.org/t/rfc-openmp-alloca-placement-for-openmp-loop-wrappers/89512/7

Patch 3/3

Assisted-by: Copilot, Claude Sonnet 4.6
2026-04-07 17:59:59 +00:00
Bangtian Liu 86b5f11ecc [mlir][GPU] Add constant address space to GPU dialect (#190211)
This PR adds a `constant` address space to the` GPU dialect and
lowerings to all GPU backends.

Signed-off-by: Bangtian Liu <liubangtian@gmail.com>
2026-04-02 15:02:12 -04:00
AidinT 67c34294a6 [mlir][docs] dialect interfaces and mlir reduce documentation fix (#189258)
Two modifications:

1. Reflect newly added dialect interface methods in the documentation
2. Remove the bug in the `MLIR Reduce` documentation
2026-03-31 15:23:13 +00:00
Sergei Lebedev b544ad5703 [MLIR] [Python] Added a way to extend MLIR->Python type mappings (#189368)
The idea is to use TableGen records for both custom type constraints and
attributes:

* `PythonTypeName` is for type constraints, while
* `PythonAttrType` is for attributes.

The key types differ between these two records. `PythonTypeName` is
keyed by C++ type because multiple type constraints map to the same C++
type (e.g. `I32` and `I64` both map to `::mlir::IntegerType`), so a
single entry covers all of them. `PythonAttrType` is keyed by TableGen
def name because different attributes can share the same C++ storage
type but need distinct Python types (e.g. `I32ArrayAttr` and
`StrArrayAttr` are both `::mlir::ArrayAttr`).

We could in theory reimplement `getPythonAttrName` using the same
approach, but I decided to leave it for future PRs.
2026-03-31 11:00:40 +01:00
Mehdi Amini 79fdef22d6 [mlir][ods] Document and test DefaultValuedProp elision in prop-dict format (#189045)
Issue #152743 reports that DefaultValuedProp is printed even when the
property value equals the default, unlike DefaultValuedAttr which is not
printed in that case.

The fix for this was already present in the codebase since commit
8955e285e1 ("[mlir] Add property combinators, initial ODS support"),
which added elision of default-valued properties in the
genPropDictPrinter
function in OpFormatGen.cpp.

This commit adds:
- Documentation in Operations.md clarifying that DefaultValuedProp is
  also elided from prop-dict output when the value equals the default,
  consistent with the existing documentation for DefaultValuedAttr.
- An explicit test in properties.mlir verifying that DefaultValuedProp
  with value equal to default is elided from prop-dict output, and that
  DefaultValuedProp with a non-default value is still printed.

Fixes #152743

Assisted-by: Claude Code
2026-03-27 16:31:09 +00:00
Twice ad39e5a6b8 [MLIR][Python][Docs] Fix example of Python-defined dialects (#188174)
Some breaking changes are introduced in #186574 for Python-defined
dialects. So we need to fix the example in the docs.
2026-03-24 19:50:49 +08:00
Chao Shi d7dbf1bd64 [mlir][gpu] Fix typo in documentation (#156619) 2026-03-18 13:05:58 +00:00
Luke Hutton 9a42e5ba6f [mlir][tosa] Remove 'Pure' trait from operations that are not speculatable (#185700)
This commit removes the 'Pure' trait from a number of TOSA operations.
Instead of marking most ops as pure by default, the trait is now opt-in
for operations that are provably side-effect free and speculatable.

Several operations were previously marked as pure unintentionally.

The following operations have had 'Pure' removed (reason in brackets):
- ARGMAX (out-of-range index)
- AVG_POOL2D (accumulator overflow/underflow)
- AVG_POOL2D_ADAPTIVE (same as above)
- CONV2D (accumulator overflow/underflow)
- CONV2D_BLOCK_SCALED (accumulator overflow/underflow)
- CONV3D (accumulator overflow/underflow)
- DEPTHWISE_CONV2D (accumulator overflow/underflow)
- MATMUL (accumulator overflow/underflow)
- MATMUL_T_BLOCK_SCALED (accumulator overflow/underflow)
- TRANSPOSE_CONV2D (accumulator overflow/underflow)
- ADD (overflow)
- SUB (underflow)
- MUL (invalid shift, overflow)
- ARITHMETIC_RIGHT_SHIFT (invalid shift value)
- LOGICAL_LEFT_SHIFT (invalid shift value)
- LOGICAL_RIGHT_SHIFT (invalid shift value)
- INTDIV (division by zero)
- POW (negative exponent restrictions)
- TABLE (invalid slope computation)
- ABS (underflow)
- NEGATE (overflow/underflow)
- REDUCE_PRODUCT (overflow)
- REDUCE_SUM (overflow)
- GATHER (out-of-range indices)
- SCATTER (out-of-range or duplicate indices)
- RESCALE (overflow/underflow)

Many of these operations can exhibit undefined behaviour when a
`REQUIRE` condition in the TOSA specification pseudocode fails. Whether
such failures result in a runtime error is implementation-defined. As a
result, speculating or reordering these operations can change program
behaviour.

For this reason, the `AlwaysSpeculatable` property implied by `Pure` is
not valid for these ops. The `NoMemoryEffect` trait is retained, as
these operations do not have direct memory side effects.
2026-03-17 12:48:06 +00:00
Matthias Springer 13c00cbc2a [mlir][IR] Rename DenseIntOrFPElementsAttr to DenseTypedElementsAttr (#185687)
`DenseIntOrFPElementsAttr` was recently generalized to accept any type
that implement the `DenseElementType` interface. The name
`DenseIntOrFPElementsAttr` does not make sense anymore. This commit
renames the attribute to `DenseTypedElementsAttr`. An alias is kept for
migration purposes. The alias will be removed after some time.
2026-03-13 17:27:23 +01:00
Slava Zakharin 48e6adc97e [RFC][mlir] Resource hierarchy for MLIR Side Effects. (#181229)
This patch allows creating a hierarchy of `SideEffects::Resource`s by adding
a virtual `getParent()` method, so that effects on *disjoint* resources
can be proven non-conflicting. It also adds virtual `isAddressable()` method
that represents a property of a resource to be addressable via a pointer
value. The non-addressable resources may not be affected via any pointer.
This is unblocking CSE, LICM and alias analysis without per-pass
special-casing.

RFC:
https://discourse.llvm.org/t/rfc-mlir-memory-region-hierarchy-for-mlir-side-effects/89811
2026-03-09 13:12:49 -07:00
Markus Böck bd15e6b736 [mlir][docs] Add LLVM target passes to the docs (#185283)
These passes are useful for translating between LLVM proper and the LLVM
dialect and have so far been missing in the documentation.
2026-03-08 16:20:55 +01:00
Adam Siemieniuk e44fd05035 [mlir][x86] Move AMX dialect into X86 dialect (#183717)
Unifies the two dialects that define x86 operations into a single one.
The AMX dialect is moved into X86 in line with other x86 extensions.

Following the dialect renaming, X86 dialect is now a suitable home for
wider range of operations targeting specific hardware features. Moving
AMX definitions to X86 dialect creates a single, centralized hub for
defining all x86 intrinsic-like operations. The new grouping aims to
eliminate the need for new dialects as new hardware extensions become
available.

The two dialects are simply merged together. X86 dialect refactoring
will be addressed separately.

List of changes:
  - operations: 'amx.tile_*' => 'x86.amx.tile_*'
  - types: '!amx.tile' => '!x86.amx.tile'
  - namespace: 'mlir::amx' => 'mlir::x86::amx'
  - test define: 'MLIR_RUN_AMX_TESTS' => 'MLIR_RUN_X86_AMX_TESTS'
  - vector lowering: AMX is enabled by default together with X86

The MLIR AMX tests are now nested under X86 directory. To enable AMX
integration tests, 'MLIR_RUN_X86_TESTS' must also be defined.
2026-03-02 11:47:30 +01: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
Paul Walker 59661a2955 [LLVM][LangRef] Restrict vscale to be a signed power-of-two integer. (#183080)
There is no known requirement to support non-power-of-two
values of vscale and yet said support is leading to unnecessary
complexity within LLVM.
2026-02-24 17:41:18 +00:00
Mehdi Amini e22cbf6a45 [MLIR] format LangRef.md (NFC) (#182259)
Using `mdformat --wraps 80` in preparation of further LangRef changes.
2026-02-20 13:13:21 +01:00
Twice 424686a62d [MLIR][Docs] Add docs about Python-defined dialects (#181372)
This PR adds documentation to the MLIR Python bindings introducing
support for Python-defined dialects (initially introduced in #169045).
2026-02-13 23:49:00 +08:00
Justin Fargnoli 243f011577 [mlir][GPU|NVVM] Update the default SM to 7.5 (#177469)
Update MLIR's default SM to `sm_75`. This matches the behavior of
offline compilation tools in the CUDA Toolkit (`nvcc`, `ptxas`, ...) and
follows suit with 9fc5fd0ad6.

Additionally, `sm_75` is the oldest GPU variant compatible with the
widest range of recent major CUDA Toolkit versions (11/12/13).
2026-01-29 17:44:04 +00:00
Maksim Levental 29c15eeff7 [mlir][Python] add docs about downstream type/attr implementation (#175259)
This PR adds docs on the changes introduced in
https://github.com/llvm/llvm-project/pull/171775.
2026-01-10 05:25:03 +00:00
Twice 87453a77cf [MLIR][docs] Clarify Python version support status (#174949)
According to this RFC
(https://discourse.llvm.org/t/rfc-adopt-regularly-scheduled-python-minimum-version-bumps/88841),
we no longer support Python versions that have reached EOL. This PR
mainly clarifies the somewhat vague wording of “a relatively recent
Python 3 installation.”
2026-01-08 20:14:21 +08:00
Maksim Levental ad5be31c30 [mlir][Python] fix NV examples after #172892 (#174481) 2026-01-05 21:47:35 +00:00
Maksim Levental f0ef5dba6d [mlir][Python] create MLIRPythonSupport (#171775)
# What

This PR adds a shared library `MLIRPythonSupport` which contains all of
the CRTP classes ike `PyConcreteValue`, `PyConcreteType`,
`PyConcreteAttribute`, as well as other useful code like `Defaulting*`
and etc enabling their reuse in downstream projects. Downstream projects
can now do

```c++
struct PyTestType : mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyTestType> {
  ...
};

class PyTestAttr : public mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteAttribute<PyTestAttr> {
  ...
}

NB_MODULE(_mlirPythonTestNanobind, m) {
  PyTestType::bind(m);
  PyTestAttr::bind(m);
}
```

instead of using the discordant alternative
`mlir_type_subclass`/`mlir_attr_subclass` (same goes for
`PyConcreteValue`/`mlir_value_subclass`).

# Why

This PR is mostly code motion (along with CMake) but before I describe
the changes I want to state the goals/benefits:

1. Currently upstream "core" extensions and "dialect" extensions ([all
of the `Dialect*` extensions
here](https://github.com/llvm/llvm-project/tree/d7c734b5a14bd91e1c76e2ce0014c19f9deef487/mlir/lib/Bindings/Python))
are a two-tier system;
**a**. [core
extensions](https://github.com/llvm/llvm-project/blob/main/mlir/lib/Bindings/Python/IRTypes.cpp#L361)
enjoy first class support as far as type inference[^3], type stub
generation, and ease of implementation, while dialect extensions [have
poorer support](https://reviews.llvm.org/D150927), incorrect type stub
generation much more tedious (boilerplate) implementation;
**b**. Crucially, this two-tiered system is reflected in the fact that
**the two sets of types/attributes are not in the same Python object
hierarchy**. To wit: `isinstance(..., Type)` and `isinstance(...,
Attribute)` are not supported for the dialect extensions[^2];
**c**. Since these types are not exposed in public headers, downstream
users (dialect extensions or not) cannot write functions that overload
on e.g. `PyFloat8*Type` - that's quite a [useful
feature](https://github.com/nod-ai/PI/blob/fdbee98df8376f47818e6b47e1cf089528c9d48d/cpp_ext/TorchOps.cpp#L29-L69)!
2. The dialect extensions incur a sizeable performance penalty relative
to the core extensions in that every single trip across the wire (either
`python->cpp` or `cpp->python`) requires work in addition to nanobind's
own casting/construction pipeline;
**a**. When going from `python->cpp`, [we extract the capsule object
from the Python
object](https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Bindings/Python/NanobindAdaptors.h#L219C24-L219C46)
and then extract from the capsule the `Mlir*` opaque struct/ptr. This
side isn't so onerous;
**b**. When going from `cpp->python` we call long-hand call Python
`import` APIs and construct the Python object using `_CAPICreate`. Note,
there at least 2 `attr` calls incurred in addition to `_CAPICreate`;
this is already much more [efficiently handled by nanobind
itself](https://github.com/wjakob/nanobind/blob/4ba51fcf795971c5d603d875ae4184bc0c9bd8e6/src/nb_internals.h#L381-L382)!
3. This division blocks various features: in some configurations[^1] we
trigger a circular import bug because "dialect" types and attributes
perform an [import of the root `_mlir`
module](https://github.com/llvm/llvm-project/blob/bd9651bf78f2b1713a8203e0bd5b97f7ff199924/mlir/include/mlir/Bindings/Python/NanobindAdaptors.h#L585)
when they are created (the types themselves, not even instances of those
types). This blocks type stub generation for dialect extensions (i.e.,
the reason we currently only generate type stubs for `_mlir`).

# How

Prior this was not done/possible because of "ODR" issues but I have
resolved those issues; the basic idea for how we solve this is "move
things we want to share into shared libraries":

1. Move IRCore (stuff like `PyConcreteValue`, `PyConcreteType`,
`PyConcreteAttribute`) into `MLIRPythonSupport`;
- Note, we move the rest of the things in `IRModule.h` (renamed to
`IRCore.h`) because `PyConcreteValue`, `PyConcreteType`,
`PyConcreteAttribute` depend on them. This makes for a bigger PR than
one would hope for but ultimately I think we should give people access
to these classes to use as they see fit (specifically inherit from, but
also liberally use in bindings signatures instead of the opaque `Mlir*`
struct wrappers).
2. Put all of this code into a nested namespace
`MLIR_BINDINGS_PYTHON_DOMAIN` which is determined by a compile time
define (and tied to `MLIR_BINDINGS_PYTHON_NB_DOMAIN`). This is necessary
in order to prevent conflicts on both symbol name **and** typeid
(necessary for nanobind to not double register binded types) between
multiple bindings libraries (e.g., `torch-mlir`, and `jax`). Note
[nanobind doesn't support `module_local` like
pybind11](https://nanobind.readthedocs.io/en/latest/porting.html#removed-features).
It does support `NB_DOMAIN` but that is not sufficient for
disambiguating typeids across projects (to wit: we currently define
`NB_DOMAIN` and it was still necessary to move everything to a nested
namespace);
3. Build the [nanobind library itself as a shared
object](https://github.com/wjakob/nanobind/blob/master/cmake/nanobind-config.cmake#L127)
(and link it to both the extensions and `MLIRPythonSupport`).
4. CMake to make this work, in-tree, out-of-tree, downstream, upstream,
etc.

# Testing

Three tests are added here 

1. `PythonTestModuleNanobind` is ported to use
`PyConcreteType<PyTestType>` instead of `mlir_type_subclass` and
`PyConcreteAttribute<PyTestAttr>` instead of `mlir_atrr_subclass`,
verifying this works for non-core extensions in-tree;
2. `StandaloneExtensionNanobind` is ported to use `struct PyCustomType :
mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyCustomType>`
instead of `mlir_type_subclass` verifying this works for non-core
extensions out-of-tree;
3. `StandaloneExtensionNanobind`'s `smoketest` is extended to also load
another bindings package (namely `mlir`) verifying
`MLIR_BINDINGS_PYTHON_DOMAIN` successfully disambiguates symbols and
typeids.

I have also tested this downstream:
https://github.com/llvm/eudsl/pull/287 as well run the following builder
bots:

mlir-nvidia-gcc7:
https://lab.llvm.org/buildbot/#/buildrequests/6654424?redirect_to_build=true

I have also tested against IREE:
https://github.com/iree-org/iree/pull/21916

# Integration

It is highly recommended to set the CMake var
`MLIR_BINDINGS_PYTHON_NB_DOMAIN` (which will also determine
`MLIR_BINDINGS_PYTHON_DOMAIN`) to something unique for each downstream.
This can also be passed explicitly to `add_mlir_python_modules` if your
project builds multiple bindings packages. I added a `WARNING` to this
effect in `AddMLIRPython.cmake`.

[^3]: Python values being typed correctly when exiting from cpp;
[^1]: Specifically when the modules are imported using `importlib`,
which occurs with nanobind's
[stubgen](https://github.com/wjakob/nanobind/blob/master/src/stubgen.py#L965);
[^2]: The workaround we implemented was a class method for the dialect
bindings called `Class.isinstance(...)`;
2026-01-05 09:08:13 -08:00
Jacenty AndruszkiewiczandAndruszkiewicz, Jacenty b5614ce13f Enable printing newlines and indents in attribute and type printers (#87948)
This commit moves the code responsible for adding newlines and tracking
indent, so that it can be used not only for operation printers, but also
for attribute and type printers.

It could be useful for nested attributes, where proper formatting with
newlines and indents would benefit the readability of the IR. Currently,
everything is printed on one line, which makes it difficult to read if
the attribute is more verbose and there are multiple levels of nesting.

Co-authored-by: Andruszkiewicz, Jacenty <andruszkiewicz.jacenty@intel.com>
2026-01-05 15:05:12 +02:00
Maksim Levental e4af5b102b [mlir][python] fix symbol resolution on MacOS with multiple packages (#174057)
# Problem:

There are two build system bugs on MacOS in the case where one intends
to use multiple bindings packages simultaneously (same Python
interpreter session):

1. The nanobind modules are built with
[`-Wl,-flat_namespace`](https://github.com/llvm/llvm-project/blob/8518d2c4057d9aa4249b8466a4d77771e4f1bf4f/llvm/cmake/modules/HandleLLVMOptions.cmake#L268)
thereby leading to ambiguous symbols across multiple whatever dylibs;
2. Intra-library symbol resolution (within the C API aggregate dylib)
fails to resolve symbols correctly unless things are built with
`-DCMAKE_C_VISIBILITY_PRESET=hidden -DCMAKE_CXX_VISIBILITY_PRESET=hidden
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON`.

# Repro:

On a Mac (with this patch applied):

1. Build without `twolevel_namespace` and without hidden vis properties
and run `LIT_FILTER=test.toy ninja check-mlir` (assuming you have
`-DLLVM_BUILD_EXAMPLES=ON -DLLVM_INCLUDE_EXAMPLES=ON`) and you will see:
    ```
LLVM ERROR: can't create Attribute 'mlir::StringAttr' because storage
uniquer isn't initialized: the dialect was likely not loaded, or the
attribute wasn't added with addAttributes<...>() in the
Dialect::initialize() method.
    ```
2. Build with `twolevel_namespace` but not hidden vis and run the same
lit test and you will see:
    ```
LLVM ERROR: Attempting to attach an interface to an unregistered
operation builtin.unrealized_conversion_cast.
    ```

# Fix

We only do a partial fix here (adding `twolevel_namespace` to Python
bindings modules) because a full fix requires adding visibility
attributes to all object files. I added docs discussing this.


# Why is this not happening on Linux

Using `DYLD_PRINT_BINDINGS=1` I observe that for the checked-in/updated
test (without the fix) `libMLIRPythonCAPI` resolves many of its symbols
to `libStandalonePythonCAPI`:

```
dyld[98449]: looking for weak-def symbol '__ZN4mlir6TypeID3getINS_13AffineMapAttrEEES0_v':
dyld[98449]:   found __ZN4mlir6TypeID3getINS_13AffineMapAttrEEES0_v in map, using impl from /Users/maksimlevental/dev_projects/llvm-project/cmake-build-debug/tools/mlir/test/Examples/standalone/python_packages/standalone/mlir_standalone/_mlir_libs/libStandalonePythonCAPI.dylib
dyld[98449]: <libMLIRPythonCAPI.dylib/bind#22> -> 0x11348fa9c <libStandalonePythonCAPI.dylib/__ZN4mlir6TypeID3getINS_13AffineMapAttrEEES0_v>)
dyld[98449]: looking for weak-def symbol '__ZN4mlir6TypeID3getINS_9ArrayAttrEEES0_v':
dyld[98449]:   found __ZN4mlir6TypeID3getINS_9ArrayAttrEEES0_v in map, using impl from /Users/maksimlevental/dev_projects/llvm-project/cmake-build-debug/tools/mlir/test/Examples/standalone/python_packages/standalone/mlir_standalone/_mlir_libs/libStandalonePythonCAPI.dylib
dyld[98449]: <libMLIRPythonCAPI.dylib/bind#23> -> 0x11348f990 <libStandalonePythonCAPI.dylib/__ZN4mlir6TypeID3getINS_9ArrayAttrEEES0_v>)
dyld[98449]: looking for weak-def symbol '__ZN4mlir6TypeID3getINS_14DictionaryAttrEEES0_v':
dyld[98449]:   found __ZN4mlir6TypeID3getINS_14DictionaryAttrEEES0_v in map, using impl from /Users/maksimlevental/dev_projects/llvm-project/cmake-build-debug/tools/mlir/test/Examples/standalone/python_packages/standalone/mlir_standalone/_mlir_libs/libStandalonePythonCAPI.dylib
dyld[98449]: <libMLIRPythonCAPI.dylib/bind#24> -> 0x11348eec0 <libStandalonePythonCAPI.dylib/__ZN4mlir6TypeID3getINS_14DictionaryAttrEEES0_v>)
```

Turns out this is "expected" behavior:

> It appears on macOS, when a static library is compiled without
-fvisibility=hidden, its C++ template instantiations could lead to
leftover weak symbols that are resolved and bound at runtime


https://joyeecheung.github.io/blog/2025/01/11/executable-loading-and-startup-performance-on-macos/

🤷
2026-01-02 18:53:57 +00:00
Matthias SpringerandMehdi Amini abfac95143 [mlir][docs] Add more examples for the "canonical form" (#173667)
Mention that there is no formal definition of the canonical form. Also
add more examples for users to understand what kind of transformations
the community has agreed upon in the past.

---------

Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2025-12-30 09:24:07 +01:00
Maksim Levental 3d7018c70b [MLIR][Python] remove pybind11 support (#172581)
This PR removes pybind which has been deprecated for over a year
(https://github.com/llvm/llvm-project/pull/117922).
2025-12-19 09:51:22 -08:00
hellozmz ecf979cdb6 [mlir] [docs] fix toy readme (#172262)
mlir toy docs use the deprecated api, so I fix it.
2025-12-19 09:41:44 +01:00
Henrich Lauko 32243a54f8 [MLIR] Add DefaultValuedEnumAttr decorator (#172916)
Introduce DefaultValuedEnumAttr, which similarly to DefaultValuedAttr
decorates an enum attribute to have a default value from a specific enum
case when not present. The default is constructed as the fully-qualified
enum case symbol.

In comparison to DefaultValuedAttr, this allows using a TableGen
EnumCase
variable instead of a raw string.
2025-12-19 08:29:53 +01:00
Guray Ozen eeaf435859 [MLIR][Remarks] Improve the doc (#171128) 2025-12-13 10:53:38 +01:00
Alexander Root dda0486653 [MLIR] Update broken link in LangRef.md (#170938)
Noticed the link was dead when reading the docs. According to the
wayback machine, it was a link to "Revisiting Out-of-SSA Translation for
Correctness, Code Quality, and Efficiency" by Boissinot et al., so
providing a more permanent link.
2025-12-06 10:57:33 +01:00
AidinT 41f00cb3de [MLIR] feat(mlir-tblgen): Add support for dialect interfaces (#170046)
Currently, Dialect Interfaces can't be defined in ODS. This PR adds the
support for dialect interfaces. It follows the same approach with other
interfaces and extends on top of `Interface` class defined in
`mlir/TableGen/Interfaces.h`.

Given the following input:

```tablegen
#ifndef MY_INTERFACES
#define MY_INTERFACES

include "mlir/IR/Interfaces.td"

def DialectInlinerInterface : DialectInterface<"DialectInlinerInterface"> {
  let description = [{
     Define a base inlining interface class to allow for dialects to opt-in to the inliner.
  }];

  let cppNamespace = "::mlir";

  let methods = [
    InterfaceMethod<
      /*desc=*/        [{
        Returns true if the given region 'src' can be inlined into the region
        'dest' that is attached to an operation registered to the current dialect.
        'valueMapping' contains any remapped values from within the 'src' region.
        This can be used to examine what values will replace entry arguments into
        the 'src' region, for example.
      }],
      /*returnType=*/  "bool",
      /*methodName=*/  "isLegalToInline",
      /*args=*/        (ins "::mlir::Region *":$dest, "::mlir::Region *":$src, "::mlir::IRMapping &":$valueMapping),
      /*methodBody=*/  [{
        return true;
      }]
      >
  ];
}


#endif
```

It will generate the following code:

```cpp
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|*                                                                            *|
|* Dialect Interface Declarations                                             *|
|*                                                                            *|
|* Automatically generated file, do not edit!                                 *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

namespace mlir {

/// Define a base inlining interface class to allow for dialects to opt-in to the inliner.
class DialectInlinerInterface : public ::mlir::DialectInterface::Base<DialectInlinerInterface> {
public:

  /// Returns true if the given region 'src' can be inlined into the region
  /// 'dest' that is attached to an operation registered to the current dialect.
  /// 'valueMapping' contains any remapped values from within the 'src' region.
  /// This can be used to examine what values will replace entry arguments into
  /// the 'src' region, for example.
  virtual bool isLegalToInline(::mlir::Region * dest, ::mlir::Region * src, ::mlir::IRMapping & valueMapping) const;

protected:
  DialectInlinerInterface(::mlir::Dialect *dialect) : Base(dialect) {}
};

} // namespace mlir

bool ::mlir::DialectInlinerInterface::isLegalToInline(::mlir::Region * dest, ::mlir::Region * src, ::mlir::IRMapping & valueMapping) const {
  return true;
}
```
2025-12-05 08:10:51 -08:00
Jakub Kuderski 0bd2f12753 [mlir][linalg] Restrict fill initial value type to output element type (#169567)
Disallow implicit casting, which is surprising, and, IME, usually
indicative of copy-paste errors.

Because the initial value must be a scalar, I don't expect this to
affect any data movement.
2025-11-30 09:51:37 -05:00