Commit Graph

317 Commits

Author SHA1 Message Date
Diego Caballero
204eb70af8 [mlir][Vector] Canonicalize empty vector.mask into arith.select (#140976)
This PR adds a missing canonicalization for empty `vector.mask` ops with
a passthru value.

```
   %0 = vector.mask %mask, %passthru { vector.yield %a : vector<8xf32> } :
     vector<8xi1> -> vector<8xf32>

 becomes:

   %0 = arith.select %mask, %a, %passthru : vector<8xf32>
```
2025-05-23 08:29:57 -07:00
Diego Caballero
d6f394e141 [mlir][Vector] Move vector.mask canonicalization to folder (#140324)
This MR moves the canonicalization that elides empty `vector.mask` ops
to folders.
2025-05-21 17:25:01 -07:00
Diego Caballero
fd8bc37b45 [mlir][Vector][NFC] Run extractInsertFoldConstantOp earlier in the folder (#140814)
This PR moves `extractInsertFoldConstantOp` earlier in the folder lists
of `vector.extract` and `vector.insert`. Many folders require having
non-dynamic indices so `extractInsertFoldConstantOp` is a requirement
for them to trigger.
2025-05-21 13:57:01 -07:00
Diego Caballero
6cac792bf9 [mlir][Vector] Improve vector.mask verifier (#139823)
This PR improves the `vector.mask` verifier to make sure it's not
applying masking semantics to operations defined outside of the
`vector.mask` region. Documentation is updated to emphasize that and
make it clearer, even though it already stated that.

As part of this change, the logic that ensures that a terminator is
present in the region mask has been simplified to make it less
surprising to the user when a `vector.yield` is explicitly provided in
the IR.
2025-05-20 15:31:45 -07:00
Diego Caballero
b6dfe4dbfe [mlir][Vector] Fix vector.mask parser for incorrect passthru cases (#140319)
This MR fixes a crash when parsing an invalid `vector.mask` with a
passtru operand.
2025-05-19 11:20:45 -07:00
Momchil Velikov
38d2306b62 [MLIR] Minor fixes to FoldTransposeBroadcast rewrite (#140083)
This patch contains two minor changes, which I believe were the original
author's intent.

* when folding `transpose(broadcast(x))` emit `broadcast(x)` instead of
`broadcast(broadcast(x))`. The latter causes transient verifier
failures with `mlir-opt --debug` , e.g.
```
mlir-asm-printer: 'func.func' failed to verify and will be printed in generic form
"func.func"() <{function_type = (vector<4x1x1x7xi8>) -> vector<3x2x4x5x6x7xi8>, sym_name = "broadcast_transpose_mixed_example"}> ({
^bb0(%arg0: vector<4x1x1x7xi8>):
  %0 = "vector.broadcast"(%arg0) : (vector<4x1x1x7xi8>) -> vector<2x3x4x5x6x7xi8>
  %1 = "vector.broadcast"(%0) : (vector<2x3x4x5x6x7xi8>) -> vector<3x2x4x5x6x7xi8>
  "func.return"(%1) : (vector<3x2x4x5x6x7xi8>) -> ()
}) : () -> ()
```

* when checking permutation groups the variable `low` was set just once
to zero, thus checking was quadratic. It looks the intent was for `low`
to track the beginning of each dimension groups. (Nevertheless the check
was correct).
2025-05-19 09:45:41 +01:00
James Newling
21f1a616d6 [mlir][vector] Additional transpose folding (#138347)
Fold transpose with unit-dimensions. Seen in the wild:
```
 %0 = vector.transpose %arg, [0, 2, 1, 3] : vector<6x1x1x4xi8> to vector<6x1x1x4xi8>
```

This transpose can be folded because (1) it preserves the shape and (2)
the shuffled dims are unit extent.

Also addresses comment about static vs anonymous namespace:
https://github.com/llvm/llvm-project/pull/135841#discussion_r2071869067

---------

Signed-off-by: James Newling <james.newling@gmail.com>
2025-05-14 14:56:35 -07:00
Andrzej Warzyński
c45cc3e420 [mlir][vector] Standardize base Naming Across Vector Ops (NFC) (#137859)
[mlir][vector] Standardize base Naming Across Vector Ops (NFC)

This change standardizes the naming convention for the argument
representing the value to read from or write to in Vector ops that
interface with Tensors or MemRefs. Specifically, it ensures that all
such ops use the name `base` (i.e., the base address or location to
which offsets are applied).

Updated operations:

* `vector.transfer_read`,
* `vector.transfer_write`.

For reference, these ops already use `base`:

* `vector.load`, `vector.store`, `vector.scatter`, `vector.gather`,
  `vector.expandload`, `vector.compressstore`, `vector.maskedstore`,
  `vector.maskedload`.

This is a non-functional change (NFC) and does not alter the semantics of these
operations. However, it does require users of the XFer ops to switch from
`op.getSource()` to `op.getBase()`.

To ease the transition, this PR temporarily adds a `getSource()` interface
method for compatibility. This is intended for downstream use only and should
not be relied on upstream. The method will be removed prior to the LLVM 21
release.

Implements #131602
2025-05-12 09:44:50 +01:00
Kazu Hirata
921d162460 [mlir] Remove unused local variables (NFC) (#138642) 2025-05-06 07:55:50 -07:00
James Newling
1a44f38d2a [mlir][vector] Canonicalize/fold 'order preserving' transposes (#135841)
Handles special case where transpose doesn't permute any non-1
dimensions (and so is effectively a shape_cast) and is adjacent to a
shape_cast that it can fold into. For example

```
%1 = vector.transpose %0, [1, 0, 3, 2] : vector<4x1x1x6xf32> to vector<1x4x6x1xf32>
```

can be folded into an adjacent shape_cast. An alternative to this PR
would be to canonicalize such transposes to shape_casts directly, but I
think it'll be difficult getting consensus that shape_cast is 'more
canonical' than transpose, so this PR compromises with the less
opinionated claim that

1) shape_cast is more canonical than shape_cast(transpose)
2) shape_cast is more canonical than transpose(shape_cast)

The pattern `ConvertIllegalShapeCastOpsToTransposes` that is specific to
transposes with scalable dimensions reverses the canonicalization added
here, so I've I've disabled this canonicalization for scalable vectors
2025-05-01 15:50:55 -07:00
James Newling
5718460b22 [mlir][vector] Relax constraints on shape_cast (#136587)
`vector.shape_cast` was initially designed to be the union of
collapse_shape and expand_shape. There was an inconsistency in the
verifier that allowed any shape casts when the rank did not change, which
led to a strange middle ground where you could cast from shape (4,3) to
(3,4) but not from (4,3) to (2,3,2). That issue was fixed (verifier made stricter) 
in https://github.com/llvm/llvm-project/pull/135855, but further feedback
there (and polling) suggests that vector.shape_cast should rather allow all 
shape casts (so more like tensor.reshape than 
tensor.collapse_shape/tensor.expand_shape). This PR makes this simplification
by relaxing the verifier.
2025-05-01 10:18:33 -07:00
Andrzej Warzyński
8c2233b304 [mlir][vector] Update docs + add tests (#137144)
This is a small follow-on for #133721:
* Renamed `getRealVectorRank` as `getEffectiveVectorRankForXferOp` (to
  emphasise that this method was written specifically for transfer Ops).
* Marginally tweaked the description for
  `getEffectiveVectorRankForXferOp` (mostly to highlight the two edge
  cases being covered).
* Added tests for cases when the element type (of the shaped type) is a
  vector.
* Unified the naming (and the order) of arguments in tests with the
  surrounding tests (e.g. `%vec_to_write` -> `%arg1`). Mostly for
  consistency (it would be good to use self-documenting names like
  `%vec_to_write` throughout).
2025-04-25 07:42:21 +01:00
Andrzej Warzyński
ebceb732d5 [mlir][vector] Update the folder for vector.{insert|extract} (#136579)
This is a minor follow-up to #135498. It ensures that operations like
the following are not treated as out-of-bounds accesses and can be
folded correctly (*):

```mlir
  %c_neg_1 = arith.constant -1 : index
  %0 = vector.insert %value_to_store, %dest[%c_neg_1] : vector<5xf32> into vector<4x5xf32>
  %1 = vector.extract %src[%c_neg_1, 0] : f32 from vector<4x5xf32>
```

In addition to adding tests for the case above, this PR also relocates
the tests from #135498 to be alongside existing tests for the
`vector.{insert|extract}` folder, and reformats them to follow:
  * https://mlir.llvm.org/getting_started/TestingGuide/

For example:
  * The "no_fold" prefix is now used to label negative tests.
  * Redundant check lines have been removed (e.g., CHECK: vector.insert
    is sufficient to verify that folding did not occur).

(*) As per https://mlir.llvm.org/docs/Dialects/Vector/#vectorinsert-vectorinsertop,
these are poison values.
2025-04-24 10:43:25 +01:00
Cedric
a68c8e8314 [mlir][vector] Fix parser of vector.transfer_read (#133721)
This PR adds a check in the parser to prevent a crash when
vector.transfer_read fails to create minor identity permutation. map.
Fixes #132851

a.mlir

```
module {
  func.func @test_vector.transfer_read(%arg1: memref<?xindex>) -> vector<3x4xi32> {
    %c3_i32 = arith.constant 3 : i32
    %0 = vector.transfer_read %arg1[%c3_i32, %c3_i32], %c3_i32 : memref<?xindex>, vector<3x4xi32>
    return %0 : vector<3x4xi32>
  }
}
```
2025-04-24 09:21:51 +08:00
Fehr Mathieu
2721f5af12 [mlir][vector] Prevent folding of OOB values in insert/extract (#135498)
Out of bound position values should not be folded in vector.extract and
vector.insert operations, as only in bounds constants and -1 are valid.

Fixes #134516
2025-04-18 05:53:26 +02:00
James Newling
c7fae59ac5 [mlir][vector] Move extract_strided_slice canonicalization to folding (#135676)
Folders are preferred:
https://mlir.llvm.org/docs/Canonicalization/#when-to-use-the-fold-method-vs-rewriterpatterns-for-canonicalizations

Included here : some missing `-----` between lit test file with mlir-opt
with `-split-input-file` flag
2025-04-16 16:20:05 -04:00
James Newling
eea86489dd [mlir][vector] Fold broadcast(poison) -> poison (#135677)
In addition to the new folder, I've also a test for broadcast(splat) ->
splat which I think was missing

Signed-off-by: James Newling <james.newling@gmail.com>
2025-04-16 13:12:38 -04:00
James Newling
73b8750a97 [mlir][vector] fold transpose(poison) -> poison (#135675)
Following on from https://github.com/llvm/llvm-project/pull/133988

---------

Signed-off-by: James Newling <james.newling@gmail.com>
2025-04-16 13:10:23 -04:00
James Newling
0daf20b360 [mlir][vector] transpose(broadcast) -> broadcast canonicalization (#135096)
Example seen in the 'real world':
 
 ```
 %0 = vector.broadcast %arg0 : vector<1xi8> to vector<1x8xi8>
 %1 = vector.transpose %0, [1, 0] : vector<1x8xi8> to vector<8x1xi8>
 ```
 
 This PR adds a canonicalizer that rewrites the above as
 
```
  %1 = vector.broadcast %arg0 : vector<1xi8> to vector<8x1xi8>
```

It works by determining if a transpose is only shuffling contiguous
broadcast dimensions.
2025-04-16 13:08:36 -04: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
Jakub Kuderski
b0acbbee88 [mlir][vector] Fix deprecation warning for .isa. NFC. (#135512)
This was introduced in: https://github.com/llvm/llvm-project/pull/135371
2025-04-12 21:49:40 -04:00
Sagar Kulkarni
357e3803bb [mlir][vector] Prevent folding non memref-type gather into maskedload (#135371)
This patch fixes an issue in the FoldContiguousGather pattern which was
incorrectly folding vector.gather operations with contiguous indices
into vector.maskedload operations regardless of the base operand type.

While vector.gather operations can work on both tensor and memref types,
vector.maskedload operations are only valid for memref types. The
pattern was incorrectly lowering a tensor-based gather into a
masked-load, which is invalid.

This fix adds a type check to ensure the pattern only applies to
memref-based gather operations.

Co-authored-by: Sagar Kulkarni <sagar@rain.ai>
2025-04-12 04:15:51 +03:00
Andrzej Warzyński
fedd79bdcd [mlir][vector] Tighten the semantics of vector.{load|store} (#135151)
This change refines the verifier for `vector.load` and `vector.store` to
disallow the use of vectors with higher rank than the source or
destination memref. For example, the following is now rejected:

```mlir
  %0 = vector.load %src[%c0] : memref<?xi8>, vector<16x16xi8>
  vector.store %vec, %dest[%c0] : memref<?xi8>, vector<16x16xi8>
```

This pattern was previously used in SME end-to-end tests and "happened"
to work by implicitly assuming row-major memory layout. However, there
is no guarantee that such an assumption will always hold, and we should
avoid relying on it unless it can be enforced deterministically.

Notably, production ArmSME lowering pipelines do not rely on this
behavior. Instead, the expected usage (illustrated here with scalable
vector syntax) would be:

```mlir
  %0 = vector.load %src[%c0, %c0] : memref<?x?xi8>, vector<[16]x[16]xi8>
```

This PR updates the verifier accordingly and adjusts all affected tests.
These tests are either removed (if no longer relevant) or updated to use
memrefs with appropriately matching rank.
2025-04-11 20:08:08 +01:00
James Newling
409def2867 [mlir][vector] shape_cast(broadcast) -> broadcast canonicalization (#134939)
Add additional cases of this canonicalization, by checking the 'source
of truth' function `isBroadcastableTo` to check when it is possible to
broadcast directly to the shape resulting from the shape_cast.

---------

Signed-off-by: James Newling <james.newling@gmail.com>
2025-04-11 15:15:03 +01:00
James Newling
cd85f5dbdf [mlir] canonicalizer: shape_cast(poison) -> poison (#133988)
Based on the ShapeCastConstantFolder, this pattern replaces

%0 = ub.poison : vector<2x3xf32>
%1 = vector.shape_cast %0 vector<2x3xf32> to vector<6xf32>

with 

%1 = ub.poison : vector<6xf32>

---------

Signed-off-by: James Newling <james.newling@gmail.com>
2025-04-11 15:13:03 +01:00
Andrzej Warzyński
2f6bc47a18 [mlir][vector] Standardise valueToStore Naming Across Vector Ops (NFC) (#134206)
This change standardises the naming convention for the argument
representing the value to store in various vector operations.
Specifically, it ensures that all vector ops storing a value—whether
into memory, a tensor, or another vector — use `valueToStore` for the
corresponding argument name.

Updated operations:
* `vector.transfer_write`, `vector.insert`, `vector.scalable_insert`,
  `vector.insert_strided_slice`.

For reference, here are operations that currently use `valueToStore`:
* `vector.store` `vector.scatter`, `vector.compressstore`,
  `vector.maskedstore`.

This change is non-functional (NFC) and does not affect the
functionality of these operations.

Implements #131602
2025-04-07 13:56:54 +01:00
Longsheng Mou
22a11be8ab [mlir][vector] Fix parser of vector.contract (#133434)
This PR adds a check in the parser to prevent a crash when
`vector.contract` lacks the `iterator_types` attribute.
Fixes #132886.
2025-03-29 09:24:42 +08:00
Kazu Hirata
a1bb750745 [mlir] Use a range constructor of DenseSet (NFC) (#133355) 2025-03-27 20:13:30 -07:00
Kunwar Grover
f3fa54a191 [mlir][Vector] Handle 0-rank case in fold instead of RewriterPattern (#130168)
For vector.extract, the folder always canonicalizes to a vector.extract
operation, while the rewrite pattern canonicalizes to a vector.broadcast
except in the case of 0-rank vectors.

Remove this special casing, and instead handle the 0-rank vector case in
the folder.
2025-03-24 13:14:24 +00:00
Kunwar Grover
dc28e0d5d2 [mlir][Vector] Remove more special case uses for extractelement/insertelement (#130166)
A number of places in our codebase special case to use
extractelement/insertelement for 0D vectors, because extract/insert did
not support 0D vectors previously. Since insert/extract support 0D
vectors now, use them instead of special casing.
2025-03-24 13:04:16 +00:00
Kunwar Grover
24a8e18f5a [mlir][vector] Allow multi dim vectors in vector.scatter (#132217)
This patch matches the definition of vector.scatter as a counter part of
vector.gather.

All of the changes done in this patch make vector.scatter match
vector.gather 's multi dimensional definition.

Unrolling for vector.scatter will be implemented in subsequent patches.

Discourse Discussion:
https://discourse.llvm.org/t/rfc-improving-gather-codegen-for-vector-dialect/85011/13
2025-03-24 12:52:46 +00:00
Kazu Hirata
3041fa6c7a [mlir] Use *Set::insert_range (NFC) (#132326)
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently
gained C++23-style insert_range.  This patch replaces:

  Dest.insert(Src.begin(), Src.end());

with:

  Dest.insert_range(Src);

This patch does not touch custom begin like succ_begin for now.
2025-03-20 22:24:17 -07:00
Kunwar Grover
d10dca6ba7 [mlir][Vector] Move vector.insert canonicalizers for DenseElementsAttr to folders (#128040)
This PR moves vector.insert canonicalizers for DenseElementsAttr (splat
and non splat case) to folders. Folders are local, and it's always
better to implement a folder than a canonicalizer.

This PR is mostly NFC-ish, because the functionality mostly remains
same, but is now run as part of a folder, which is why some tests are
changed, because GreedyPatternRewriter tries to fold by default.
2025-03-06 18:24:38 +00:00
Kunwar Grover
98542a3d6d [mlir][Vector] Move vector.extract canonicalizers for DenseElementsAttr to folders (#127995)
This PR moves vector.extract canonicalizers for DenseElementsAttr (splat
and non splat case) to folders. Folders are local, and it's always
better to implement a folder than a canonicalization pattern.

This PR is mostly NFC-ish, because the functionality mostly remains
same, but is now run as part of a folder, which is why some tests are
changed, because GreedyPatternRewriter tries to fold by default.

There is also a test change which makes the indices of a vector.extract
test dynamic. This is so that it doesn't fold away after this pr.
2025-02-26 10:58:24 +05:30
Kunwar Grover
61fb954109 [mlir][Vector] Improve support for vector.extract(broadcast) (#116234)
This patch improves support for vector.extract(broadcast) dynamic
dimension folders. This is mostly a matter of moving a conservative
condition for dynamic dimensions. The broadcast folder for
vector.extract now covers the cases that the vector.extractelement +
broadcast folder does.

This patch also improves test coverage for vector.extract + broadcast
folders/canonicalizers. The folders/canonicalizers now enumerate every
supported / unsupported case.
2025-02-24 16:17:38 +05:30
Longsheng Mou
3e223e3a20 [mlir][vector] Fix out-of-bounds access (#126734)
This PR fixes an out-of-bounds bug that occurs when there are no overlap
dimensions between the `sizes` and source of
`vector.extract_strided_slice`, causing access to `sizes` to go out of
bounds. Fixes #126196.
2025-02-13 09:17:43 +08:00
Andrzej Warzyński
fcbf04e40e [mlir][vector][nfc] Add clarification on "dim-1" bcast (#125425)
Adds a small note to VectorOps.td on what "dim-1" broadcast is. Also
updates comments to consistently use quotes, i.e.

* "dim-1" broadcasting instead of dim-1 broadcasting.

This way it is clear that we are referring to "stretching" one of the
trailing dims rather than e.g. broadcasting a dim at idx 1.
2025-02-11 21:37:23 +00:00
lonely eagle
7ae78a6cdb [mlir][vector]add extractInsertFoldConstantOp fold function and apply it to extractOp and insertOp. (#124399)
add extractInsertFoldConstantOp fold function and apply it to extractOp and insertOp.
2025-02-11 00:21:59 +08:00
Diego Caballero
68325148d3 [mlir][Vector] Fold vector.extract from poison vector (#126122)
This PR adds a folder for `vector.extract(ub.poison) -> ub.poison`. It
also replaces `create` with `createOrFold` insert/extract ops in vector
unroll and transpose lowering patterns to trigger the poison foldings
introduced recently.
2025-02-07 10:20:07 -08:00
Ivan Butygin
6e52a12811 [mlir][vector] Create VectorToLLVMDialectInterface (#121440)
Create `VectorToLLVMDialectInterface` which allows automatic conversion
discovery by generic `--convert-to-llvm` pass. This only covers final
dialect conversion step and not any previous preparation steps. Also,
currently there is no way to pass any additional parameters through this
conversion interface, but most users using default parameters anyway.
2025-02-05 23:21:25 +03:00
Diego Caballero
c6eef00a09 [mlir][Vector] Add vector.shuffle fold for poison inputs (#125608)
https://github.com/llvm/llvm-project/pull/124863 added folding support
for poison indices to `vector.shuffle`. This PR adds support for folding
`vector.shuffle` ops with one or two poison input vectors.
2025-02-04 18:03:26 -08:00
Diego Caballero
d13940ee26 [mlir][Vector] Teach how to materialize UB constant to Vector (#125596)
This PR adds support for UB constant materialization (i.e., generating
`ub::PoisonOp` to `VectorDialect::materializeConstant`. This was the
reason why the vector folders generating poison didn't work.
2025-02-04 11:18:30 -08:00
Diego Caballero
c3c326213e [mlir][Vector] Fix vector.shuffle folder for poison indices (#124863)
This PR fixes the folder of a `vector.shuffle` with constant input
vectors in the presence of a poison index. Partially poison vectors are
currently not supported in UB so the folder select v1[0] for elements
indexed by poison.
2025-01-31 15:47:47 -08:00
Jay Foad
aa2952165c Fix typo "tranpose" (#124929) 2025-01-29 17:49:54 +00:00
Diego Caballero
35df525fd0 [mlir][Vector] Add support for poison indices to Extract/IndexOp (#123488)
Following up on #122188, this PR adds support for poison indices to
`ExtractOp` and `InsertOp`. It also includes canonicalization patterns
to turn extract/insert ops with poison indices into `ub.poison`.
2025-01-28 13:51:50 -08:00
Ivan Butygin
88136f9645 [mlir][vector] Canonicalize gathers/scatters with trivial offsets (#117939)
Canonicalize gathers/scatters with contiguous (i.e. [0, 1, 2, ...])
offsets into vector masked load/store ops.
2025-01-24 14:14:53 +03:00
Matthias Springer
6aaa8f25b6 [mlir][IR][NFC] Move free-standing functions to MemRefType (#123465)
Turn free-standing `MemRefType`-related helper functions in
`BuiltinTypes.h` into member functions.
2025-01-21 08:48:09 +01:00
Diego Caballero
eae5ca9b45 [mlir][Vector] Support poison in vector.shuffle mask (#122188)
This PR extends the existing poison support in
https://mlir.llvm.org/docs/Dialects/UBOps/ by representing poison mask
values in `vector.shuffle`. Similar to LLVM (see
https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Instructions.h#L1884)
this requires defining an integer value (`-1`) to represent poison in
the `vector.shuffle` mask.
2025-01-18 15:16:51 -08:00
Kai Sasaki
d3846eca20 [mlir] Guard sccp pass from crashing with different source type (#120656)
Vector::BroadCastOp expects the identical element type in folding. It
causes the crash if the different source type is given to the SCCP pass.
We need to guard the pass from crashing if the nonidentical element type
is given, but still compatible. (e.g. index vs integer type)

https://github.com/llvm/llvm-project/issues/120193
2024-12-25 12:19:52 +09:00
Kazu Hirata
6e41483b84 [MemRef] Migrate away from PointerUnion::{is,get} (NFC) (#120382)
Note that PointerUnion::{is,get} have been soft deprecated in
PointerUnion.h:

  // FIXME: Replace the uses of is(), get() and dyn_cast() with
  //        isa<T>, cast<T> and the llvm::dyn_cast<T>

I'm not touching PointerUnion::dyn_cast for now because it's a bit
complicated; we could blindly migrate it to dyn_cast_if_present, but
we should probably use dyn_cast when the operand is known to be
non-null.
2024-12-18 10:56:27 -08:00