865 Commits

Author SHA1 Message Date
puneeth_aditya_5656
fe9107fc73
[mlir][sparse] Implement missing BufferizableOpInterface methods for NewOp (#178423)
## Summary
Fixes crash when running `--eliminate-empty-tensors` on MLIR modules
containing `sparse_tensor.new` with a tensor input.

## Problem
The `sparse_tensor.new` operation was missing the
`bufferizesToMemoryRead`, `bufferizesToMemoryWrite`, and
`getAliasingValues` methods in its `BufferizableOpInterface`
implementation. This caused an `UNREACHABLE` crash with message
"bufferizesToMemoryRead not implemented".

## Solution
Implemented the missing methods in `NewOpInterface`:
- `bufferizesToMemoryRead`: returns `true` (reads from source tensor)
- `bufferizesToMemoryWrite`: returns `false` (doesn't write to source)  
- `getAliasingValues`: returns empty (result is new allocation, not an
alias)

Also added a test case for `sparse_tensor.new` with tensor input.

Fixes #178419

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 07:59:58 +00:00
Jakub Kuderski
9aaf0b89f5
[mlir] Apply clang-tidy check llvm-use-vector-utils. NFC. (#178526) 2026-01-29 02:19:00 +00:00
Matthias Springer
ae51ee2b55
[mlir][DialectUtils][NFC] Add helper for matching zero int/float values (#171293)
Add a convenience helper similar to `isZeroInteger` that works for
integers and floats.
2025-12-31 10:23:36 +01:00
Mehdi Amini
9cae8ec551 [MLIR] Apply clang-tidy fixes for bugprone-argument-comment in SparseTensorDescriptor.cpp (NFC) 2025-12-17 05:30:01 -08:00
Mehdi Amini
3da82af83f [MLIR] Apply clang-tidy fixes for bugprone-argument-comment in SparseBufferRewriting.cpp (NFC) 2025-11-20 03:35:18 -08:00
Govind Malasani
6f5c8fe1c1
[MLIR][SparseTensor] Dense Outer Loop Ordering Strategy (#160168)
This PR builds upon the infrastructure set up for Sparse Tensor Loop
Ordering Heuristics (#154656) by adding a preference to have dense loops
outer and sparse loops inner.

As always I'd love to get feedback and know if there's any other
direction to go with this work that might be better.
2025-11-17 09:01:44 -08:00
Kazu Hirata
ff8ed4d80a
[mlir] Use llvm::copy (NFC) (#168213)
Identified with llvm-use-ranges.
2025-11-15 10:54:01 -08:00
Ryutaro Okada
7e7ea9c535
[MLIR] Extend vector.scatter to accept tensor as base (#165548)
This PR makes the following improvements to `vector.scatter` and its
lowering pipeline:
- In addition to `memref`, accept a ranked `tensor` as the base operand
of `vector.scatter`, similar to `vector.transfer_write`.
- Implement bufferization support for `vector.scatter`, so that
tensor-based scatter ops can be fully lowered to memref-based forms.

It's worth to complete the functionality of map_scatter decomposition.
Full discussion can be found here:
https://github.com/iree-org/iree/issues/21135

---------

Signed-off-by: Ryutaro Okada <1015ryu88@gmail.com>
2025-11-14 19:56:24 +00:00
Kazu Hirata
188f109490
[mlir] Remove duplicate includes (NFC) (#167187)
Identified with readability-duplicate-include.
2025-11-08 17:01:32 -08:00
Kazu Hirata
05b6e1ffb3
[mlir] Remove redundant typename (NFC) (#166108)
Identified with readability-redundant-typename.
2025-11-02 15:52:36 -08:00
Jordan Rupprecht
34c58c8b7c
[mlir][sparse] Include sparse emit strategy in wrapping iterator (#165611)
When we create a `SparseIterator`, we sometimes wrap it in a
`FilterIterator`, which delegates _some_ calls to the underlying
`SparseIterator`.

After construction, e.g. in `makeNonEmptySubSectIterator()`, we call
`setSparseEmitStrategy()`. This sets the strategy only in one of the
filters -- if we call `setSparseEmitStrategy()` immediately after
creating the `SparseIterator`, then the wrapped `SparseIterator` will
have the right strategy, and the `FilterIterator` strategy will be
unintialized; if we call `setSparseEmitStrategy()` after wrapping the
iterator in `FilterIterator`, then the opposite happens.

If we make `setSparseEmitStrategy()` a virtual method so that it's
included in the `FilterIterator` pattern, and then do all reads of
`emitStrategy` via a virtual method as well, it's pretty simple to
ensure that the value of `strategy` is being set consistently and
correctly.

Without this, the UB of strategy being uninitialized manifests as a
sporadic test failure in
mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_strided_conv_2d_nhwc_hwcf.mlir,
when run downstream with the right flags (e.g. asan + assertions off).
The test sometimes fails with `ne_sub<trivial<dense[0,1]>>.begin' op
created with unregistered dialect`. It can also be directly observed w/
msan that this uninitialized read is the cause of that issue, but msan
causes other problems w/ this test.
2025-10-29 15:40:05 -05:00
Slava Gurevich
2fc4d0ecd1
[MLIR] Fix use-after-move in debug logging (#165208)
1. In `Transforms.cpp` the debug macro is accessing a SmallVector
variable that has been moved-from and reset. Fixed by reordering code
for the move-from to happen last.

2. `IterationGraphSorter` Refine the previous use-after-move fix for
style/readability by renaming the private constructor args to resolve
naming ambiguity with the class members.

Testing: `ninja check-mlir`
2025-10-28 17:01:01 -07:00
Slava Gurevich
5dcf82d3da
[MLIR] Fix use-after-move for DEBUG builds, and broken assert logic. (#164763)
These issues affect only Debug builds, and Release builds with asserts
enabled.

1. In `SparseTensor.h` a variable is moved-from within an assert,
introducing a side effect that alters its subsequent use, and causes
divergence between Debug and Release builds (with asserts disabled).

2. In `IterationGraphSorter.cpp`, the class constructor arguments are
moved-from to initialize class member variables via the initializer
list. Because both the arguments and class members are identically
named, there's a naming collision where the arguments shadow their
identically-named member variables counterparts inside the constructor
body. In the original code, unqualified names inside the asserts,
referred to the constructor arguments. This is wrong, because these have
already been moved-from. It's not just a UB, but is broken. These
SmallVector types when moved-from are reset i.e. the size resets to 0.
This actually renders the affected asserts ineffective, since the
comparisons operate on two hollowed-out objects and always succeed. This
name ambiguity is fixed by using 'this->' to correctly refer to the
initialized member variables carrying the relevant state.

3. While the fix 2 above made the asserts act as intended, it also
unexpectedly broke one mlir test: `llvm-lit -v
mlir/test/Dialect/SparseTensor/sparse_scalars.mlir` This required fixing
the assert logic itself, which likely has never worked and went
unnoticed all this time due to the bug 2. Specifically, in the failing
test that uses `mlir/test/Dialect/SparseTensor/sparse_scalars.mlir` the
'%argq' of 'ins' is defined as 'f32' scalar type, but the original code
inside the assert had no support for scalar types as written, and was
breaking the test.

Testing:
```
ninja check-mlir
llvm-lit -v mlir/test/Dialect/SparseTensor/sparse_scalars.mlir
```
2025-10-25 20:35:34 -07:00
Kazu Hirata
6870f68978
[mlir] Replace LLVM_ATTRIBUTE_UNUSED with [[maybe_unused]] (NFC) (#163703)
This patch replaces LLVM_ATTRIBUTE_UNUSED with [[maybe_unused]],
introduced as part of C++17.
2025-10-16 06:52:36 -07:00
Govind Malasani
95e0ae9fa7
[MLIR][SparseTensor] Loop ordering strategy infrastructure (flag) (#154656)
As discussed before, this PR adds the basic infrastructure/boiler plate
for loop ordering strategies to be implemented.

If this looks ok, I wanted to also mention some of the heuristics that I
would implement next, if they sound reasonable to you guys:
- Parallel first : prioritize parallel loops over reduction loops
- Dense outer : prioritize the most dense loops first
- Sparse outer : the opposite, potentially useful in some cases?

There is another that I am considering, stride/memory aware, which would
prioritize loops with better stride patterns (like sequential or
linear). Not sure how well this carries over to Sparse Tensor though.
Are there any ideas/heuristics that I should definitely try to
implement?

As we discussed, I will try to incrementally add heuristics. Sorry for
the delay on my end, and thank you so much for the feedback!

---------

Co-authored-by: Aart Bik <ajcbik@google.com>
2025-10-06 17:29:48 +00:00
Mehdi Amini
600e97dfea [MLIR] Apply clang-tidy fixes for modernize-use-emplace in LoopEmitter.cpp (NFC) 2025-09-29 01:10:16 -07:00
Mehdi Amini
5cf9fd012e [MLIR] Apply clang-tidy fixes for modernize-use-default-member-init in SparseReinterpretMap.cpp (NFC) 2025-09-03 14:20:31 -07:00
Mehdi Amini
5ea4ccad93 [MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in SparseBufferRewriting.cpp (NFC) 2025-08-27 09:45:44 -07:00
Matthias Springer
21b607adbe
[mlir][SCF] scf.for: Add support for unsigned integer comparison (#153379)
Add a new unit attribute to allow for unsigned integer comparison.

Example:
```mlir
scf.for unsigned %iv_32 = %lb_32 to %ub_32 step %step_32 : i32 {
  // body
}
```

Discussion:
https://discourse.llvm.org/t/scf-should-scf-for-support-unsigned-comparison/84655
2025-08-15 10:59:14 +02:00
Matthias Springer
7e7c9d975e
[mlir][Transforms] Dialect Conversion Driver without Rollback (#151865)
This commit improves the `allowPatternRollback` flag handling in the
dialect conversion driver. Previously, this flag was used to merely
detect cases that are incompatible with the new One-Shot Dialect
Conversion driver. This commit implements the driver itself: when the
flag is set to "false", all IR changes are materialized immediately,
bypassing the `IRRewrite` and `ConversionValueMapping` infrastructure.

A few selected test cases now run with both the old and the new driver.

RFC:
https://discourse.llvm.org/t/rfc-a-new-one-shot-dialect-conversion-driver/79083
2025-08-13 17:40:55 +02:00
Evan Liu
e654d4e8fd
[mlir] Generalize OneShotModuleBufferize to operate on any Operation (#148327)
As part of 2646c36a864aa6a62bc1280e9a8cd2bcd2695349,
`OneShotModuleBufferize` no longer descends into nested symbol tables,
recommending users who wish to do this should do so in a pass
pipeline/custom pass. This did not support the use case of ops that
weren't ModuleOps. The patch updates `OneShotModuleBufferize` to work on
any general op.
2025-07-28 19:29:18 -07:00
Maksim Levental
c090ed53fb
[mlir][NFC] update mlir/Dialect create APIs (33/n) (#150659)
See https://github.com/llvm/llvm-project/pull/147168 for more info.
2025-07-25 16:13:55 -04:00
Longsheng Mou
f047b735e9
[mlir][NFC] Use getDefiningOp<OpTy>() instead of dyn_cast<OpTy>(getDefiningOp()) (#150428)
This PR uses `val.getDefiningOp<OpTy>()` to replace `dyn_cast<OpTy>(val.getDefiningOp())` , `dyn_cast_or_null<OpTy>(val.getDefiningOp())` and `dyn_cast_if_present<OpTy>(val.getDefiningOp())`.
2025-07-25 10:35:51 +08:00
Maksim Levental
972ac59c9a
[mlir][NFC] update mlir/Dialect create APIs (21/n) (#149928)
See https://github.com/llvm/llvm-project/pull/147168 for more info.
2025-07-22 08:15:27 -04:00
Kazu Hirata
433a5a7c20
[mlir] Remove unused includes (NFC) (#148396) 2025-07-12 15:46:34 -07:00
Jakub Kuderski
6512ca7ddb
[mlir] Add isStatic* size check for ShapedTypes. NFCI. (#147085)
The motivation is to avoid having to negate `isDynamic*` checks, avoid
double negations, and allow for `ShapedType::isStaticDim` to be used in
ADT functions without having to wrap it in a lambda performing the
negation.

Also add the new functions to C and Python bindings.
2025-07-07 14:57:27 -04:00
Longsheng Mou
5a8e60e724
[mlir] Use llvm::fill instead of std::fill(NFC) (#146889) 2025-07-07 09:12:38 +08:00
Matthias Springer
d480359420
[mlir][sparse] Do not access operation after it was replaced (#146546)
Accessing an erased operation will no longer work during a One-Shot
Dialect Conversion.
2025-07-01 21:39:54 +02:00
Kazu Hirata
abc2c3a538
[mlir] Use llvm::is_contained instead of llvm::all_of (NFC) (#145845)
llvm::is_contained is shorter than llvm::all_of plus a lambda.
2025-06-26 08:41:26 -07:00
Kazu Hirata
dec93ae454
[mlir] Migrate away from ValueRange(std::nullopt) (NFC) (#145210)
ArrayRef has a constructor that accepts std::nullopt.  This
constructor dates back to the days when we still had llvm::Optional.

Since the use of std::nullopt outside the context of std::optional is
kind of abuse and not intuitive to new comers, I would like to move
away from the constructor and eventually remove it.

One of the common uses of std::nullopt is in one of the constructors
for ValueRange.  This patch takes care of the migration where we need
ValueRange() to facilitate perfect forwarding.  Note that {} would be
ambiguous for perfecting forwarding to work.
2025-06-22 06:30:17 -07:00
Andrei Golubev
ee070d0816
[mlir][bufferization] Support custom types (1/N) (#142986)
Following the addition of TensorLike and BufferLike type interfaces (see
00eaff3e9c897c263a879416d0f151d7ca7eeaff), introduce minimal changes
required to bufferize a custom tensor operation into a custom buffer
operation.

To achieve this, new interface methods are added to TensorLike type
interface that abstract away the differences between existing (tensor ->
memref) and custom conversions.

The scope of the changes is intentionally limited (for example,
BufferizableOpInterface is untouched) in order to first understand the
basics and reach consensus design-wise.

---
Notable changes:
* mlir::bufferization::getBufferType() returns BufferLikeType (instead
of BaseMemRefType)
* ToTensorOp / ToBufferOp operate on TensorLikeType / BufferLikeType.
Operation argument "memref" renamed to "buffer"
* ToTensorOp's tensor type inferring builder is dropped (users now need
to provide the tensor type explicitly)
2025-06-18 16:18:12 +02:00
Andrei Golubev
a1c2a71293
[mlir][bufferization] Use Type instead of Value in unknown conversion (#144658)
Generally, bufferization should be able to create a memref from a tensor
without needing to know more than just a mlir::Type. Thus, change
BufferizationOptions::UnknownTypeConverterFn to accept just a type
(mlir::TensorType for now) instead of mlir::Value. Additionally, apply
the same rationale to getMemRefType() helper function.

Both changes are prerequisites to enable custom types support in
one-shot bufferization.
2025-06-18 14:38:58 +02:00
Diego Caballero
1ac61c8334
[mlir][Vector] Remove vector.extractelement/insertelement from sparse vectorizer (#143270)
This PR is part of the last step to remove `vector.extractelement` and `vector.insertelement` ops.
RFC: https://discourse.llvm.org/t/rfc-psa-remove-vector-extractelement-and-vector-insertelement-ops-in-favor-of-vector-extract-and-vector-insert-ops

It updates the Sparse Vectorizer to use `vector.extract` and `vector.insert` instead of `vector.extractelement` and `vector.insertelement`.
2025-06-12 14:49:00 -07:00
Michele Scuttari
63cb6af782
[MLIR] Add bufferization state to getBufferType and resolveConflicts interface methods (#141466)
The PR continues the work started in #141019 by adding the `BufferizationState` class also to the `getBufferType` and `resolveConflicts` interface methods, together with the additional support functions that are used throughout the bufferization infrastructure.
2025-05-28 10:35:23 +02:00
Michele Scuttari
61d5fdf50c
[MLIR] Add bufferization state class to OneShotBufferization pass (#141019)
Follow-up on #138143, which was reverted due to a missing update a method signature (more specifically, the bufferization interface for `tensor::ConcatOp`) that was not catched before merging. The old PR description is reported in the next lines.

This PR is a follow-up on https://github.com/llvm/llvm-project/pull/138125, and adds a bufferization state class providing information about the IR. The information currently consists of a cached list of symbol tables, which aims to solve the quadratic scaling of the bufferization task with respect to the number of symbols. The PR breaks API compatibility: the bufferize method of the BufferizableOpInterface has been enriched with a reference to a BufferizationState object.

The bufferization state must be kept in a valid state by the interface implementations. For example, if an operation with the Symbol trait is inserted or replaced, its parent SymbolTable must be updated accordingly (see, for example, the bufferization of arith::ConstantOp, where the symbol table of the module gets the new global symbol inserted). Similarly, the invalidation of a symbol table must be performed if an operation with the SymbolTable trait is removed (this can be performed using the invalidateSymbolTable method, introduced in https://github.com/llvm/llvm-project/pull/138014).
2025-05-23 09:21:35 +02:00
Kazu Hirata
6464238dc0
[mlir] Use llvm::stable_sort (NFC) (#141186) 2025-05-22 22:36:32 -07:00
Michele Scuttari
72a8893689
Revert "[MLIR] Add bufferization state class to OneShotBufferization pass" (#141012)
Reverts llvm/llvm-project#138143

The PR for the BufferizationState is temporarily reverted due to API incompatibilities that have been initially missed during the update and were not catched by PR checks.
2025-05-22 09:25:07 +02:00
Michele Scuttari
67fc1660d9
[MLIR] Add bufferization state class to OneShotBufferization pass (#138143)
This PR is a follow-up on #138125, and adds a bufferization state class providing information about the IR. The information currently consists of a cached list of symbol tables, which aims to solve the quadratic scaling of the bufferization task with respect to the number of symbols. The PR breaks API compatibility: the `bufferize` method of the `BufferizableOpInterface` has been enriched with a reference to a `BufferizationState` object.

The bufferization state must be kept in a valid state by the interface implementations. For example, if an operation with the `Symbol` trait is inserted or replaced, its parent `SymbolTable` must be updated accordingly (see, for example, the bufferization of `arith::ConstantOp`, where the symbol table of the module gets the new global symbol inserted). Similarly, the invalidation of a symbol table must be performed if an operation with the `SymbolTable` trait is removed (this can be performed using the `invalidateSymbolTable` method, introduced in #138014).
2025-05-22 08:53:38 +02:00
Han-Chung Wang
c39915fa2e
[mlir][NFC] Simplify constant checks with isOneInteger and renamed isZeroInteger. (#139340)
The revision adds isOneInteger helper, and simplifies the existing code
with the two methods. It removes some lambda, which makes code cleaner.

For downstream users, you can update the code with the below script.

```bash
sed -i "s/isZeroIndex/isZeroInteger/g" **/*.h
sed -i "s/isZeroIndex/isZeroInteger/g" **/*.cpp
```

---------

Signed-off-by: hanhanW <hanhan0912@gmail.com>
2025-05-20 14:53:02 -07:00
Matthias Springer
ef1bb2a243
[mlir][SparseTensor] Fix unused variable error (#140428) 2025-05-18 10:55:09 +09:00
Matthias Springer
3360a23e60
[mlir][SparseTensor] Fix type conversion rule (#140350)
A type conversion rule cannot make any assumptions about the number of
pre-existing types in the `results` vector.

This commit fixes a failed assertion in a SparseTensor type conversion
rule. This is only reproducible when type conversion caching is
deactivated. There's no way to do this at the moment. This commit is in
preparation of adding context-aware type conversions, which will
deactivate type caching in such cases.
2025-05-18 09:21:33 +09:00
Iris Shi
78af0f3ab8
[mlir][NFC] Use llvm::sort (#140261) 2025-05-16 23:35:13 +08:00
Andrei Golubev
8f91b108df
[mlir][bufferization][NFC] Rename to_memref to to_buffer (#137180)
As part of the work on transitioning bufferization dialect, ops, and
associated logic to operate on newly added type interfaces (see
00eaff3e9c897c263a879416d0f151d7ca7eeaff), rename the
bufferization.to_memref to highlight the generic nature of the op.

Bufferization process produces buffers while memref is a builtin type
rather than a generic term.

Preserve the current API (to_buffer still produces a memref), however,
as the new type interfaces are not used yet.
2025-05-14 11:17:09 +02:00
Kazu Hirata
b4b5013aa3
[mlir] Use llvm::is_contained (NFC) (#139834) 2025-05-13 23:33:41 -07:00
Max Graey
8aaac80ddd
[NFC] Use more isa and isa_and_nonnull instead dyn_cast for predicates (#137393)
Also fix some typos in comments

---------

Co-authored-by: Mehdi Amini <joker.eph@gmail.com>
2025-05-13 22:34:42 +08:00
Kazu Hirata
921d162460
[mlir] Remove unused local variables (NFC) (#138642) 2025-05-06 07:55:50 -07:00
Kazu Hirata
15f7c6ed70
[mlir] Remove unused local variables (NFC) (#138481) 2025-05-05 10:08:00 -07:00
Kazu Hirata
356ff75e07
[mlir] Use llvm::less_first (NFC) (#136398) 2025-04-18 20:34:42 -07:00
Connector Switch
cc354d6a6d
[NFC] Fix destroy typo. (#135640) 2025-04-15 08:20:44 +08:00
Jakub Kuderski
0078cf79ad
[mlir] Remove deprecated cast member functions (#135556)
These have been deprecated for over two years now in favor of free
functions.

See the relevant discourse thread:

https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443
and the deprecation notice: https://mlir.llvm.org/deprecation/.
2025-04-14 09:08:34 -04:00