Commit Graph

348 Commits

Author SHA1 Message Date
Ryan Holt
847a6f8f0a [mlir][MemRef] Add runtime bounds checking (#75817)
This change adds (runtime) bounds checks for `memref` ops using the
existing `RuntimeVerifiableOpInterface`. For `memref.load` and
`memref.store`, we check that the indices are in-bounds of the memref's
index space. For `memref.reinterpret_cast` and `memref.subview` we check
that the resulting address space is in-bounds of the input memref's
address space.
2023-12-22 11:49:15 +09:00
Rik Huijzer
672f1a036a [mlir][memref] Make LoadOp::verify error more clear (#75831)
While debugging https://github.com/llvm/llvm-project/issues/71326, the
`LoadOp::verify` code and error were very confusing. This PR improves
that.

This code was a part from the reverted PR
https://github.com/llvm/llvm-project/pull/75519. Fixing the
`-convert-vector-to-scf` issue is going to take a bit longer and this
code was out of scope anyway.

Co-authored-by: Benjamin Maxwell <macdue@dueutil.tech>
2023-12-18 18:41:05 +01:00
Rik Huijzer
9f5afc3de9 Revert "[mlir][vector] Fix invalid LoadOp indices being created (#75519)"
This reverts commit 3a1ae2f46d.
2023-12-17 12:34:17 +01:00
Rik Huijzer
3a1ae2f46d [mlir][vector] Fix invalid LoadOp indices being created (#75519)
Fixes https://github.com/llvm/llvm-project/issues/71326.

The cause of the issue was that a new `LoadOp` was created which looked
something like:
```mlir
%arg4 = 
func.func main(%arg1 : index, %arg2 : index) {
  %alloca_0 = memref.alloca() : memref<vector<1x32xi1>>
  %1 = vector.type_cast %alloca_0 : memref<vector<1x32xi1>> to memref<1xvector<32xi1>>
  %2 = memref.load %1[%arg1, %arg2] : memref<1xvector<32xi1>>
  return
}
```
which crashed inside the `LoadOp::verify`. Note here that `%alloca_0` is
0 dimensional, `%1` has one dimension, but `memref.load` tries to index
`%1` with two indices.

This is now fixed by using the fact that `unpackOneDim` always unpacks
one dim


1bce61e6b0/mlir/lib/Conversion/VectorToSCF/VectorToSCF.cpp (L897-L903)

and so the `loadOp` should just index only one dimension.

---------

Co-authored-by: Benjamin Maxwell <macdue@dueutil.tech>
2023-12-17 11:42:35 +01:00
Rik Huijzer
68f0bc6f2e [mlir] Fix a zero stride canonicalizer crash (#74200)
This PR fixes https://github.com/llvm/llvm-project/issues/73383 and is
another shot at the refactoring proposed in
https://github.com/llvm/llvm-project/pull/72885.

---------

Co-authored-by: Kai Sasaki <lewuathe@gmail.com>
2023-12-06 07:35:18 +01:00
Rik Huijzer
c9c1b3c37f [mlir][memref] Fix an invalid dim loop motion crash (#74204)
Fixes https://github.com/llvm/llvm-project/issues/73382.

This PR suggests to replace two assertions that were introduced in
adabce4118
(https://reviews.llvm.org/D135748). According to the enum definition of
`NotSpeculatable`, an op that invokes undefined behavior is
`NotSpeculatable`.

0c06e8745f/mlir/include/mlir/Interfaces/SideEffectInterfaces.h (L248-L258)

and both `tensor.dim` and `memref.dim` state that "If the dimension
index is out of bounds, the behavior is undefined."

So therefore it seems to me that `DimOp::getSpeculatability()` should
return `NotSpeculatable` if the dimension index is out of bounds.

The added test is just a simplified version of
https://github.com/llvm/llvm-project/issues/73382.
2023-12-04 08:57:59 +01:00
Quinn Dawkins
f310a5d2c1 [mlir][tensor] Add a tensor.concat operation (#72779)
This adds an operation for concatenating ranked tensors along a static
dimension, as well as a decomposition mirroring the existing lowering
from TOSA to Tensor. This offers a convergence point for "input" like
dialects that include various lowerings for concatenation operations,
easing later analysis. In the future, this op can implement the
necessary interfaces for tiling, as well as potentially add conversions
to some kind of linalg and/or memref counterpart.

This patch adds the op, the decomposition, and some basic
folding/canonicalization. Replacing lowerings with the op (such as the
TOSA lowering) will come as a follow up.

See
https://discourse.llvm.org/t/rfc-tensor-add-a-tensor-concatenate-operation/74858
2023-12-01 15:05:29 -05:00
Max191
3a6f02a658 [mlir] Add subbyte emulation support for memref.store. (#73174)
This adds a conversion for narrow type emulation of memref.store ops.
The conversion replaces the memref.store with two memref.atomic_rmw ops.
Atomics are used to prevent race conditions on same-byte accesses, in
the event that two threads are storing into the same byte.

Fixes https://github.com/openxla/iree/issues/15370
2023-11-28 11:51:30 -08:00
Max191
b823f8469b [mlir] Add support for memref.alloca sub-byte emulation (#73138)
Adds a similar case to `memref.alloc` for `memref.alloca` in
EmulateNarrowTypes.

Fixes https://github.com/openxla/iree/issues/15515
2023-11-27 16:28:22 -08:00
Max191
b29332a318 [mlir] Add narrow type emulation for memref.reinterpret_cast (#73144) 2023-11-27 10:41:14 -08:00
Rik Huijzer
1949fe90bf [mlir] Verify non-negative offset and size (#72059)
In #71153, the `memref.subview` canonicalizer crashes due to a negative
`size` being passed as an operand. During `SubViewOp::verify` this
negative `size` is not yet detectable since it is dynamic and only
available after constant folding, which happens during the
canonicalization passes. As discussed in
<https://discourse.llvm.org/t/rfc-more-opfoldresult-and-mixed-indices-in-ops-that-deal-with-shaped-values/72510>,
the verifier should not be extended as it should "only verify local
aspects of an operation".

This patch fixes #71153 by not folding in aforementioned situation.

Also, this patch adds a basic offset and size check in the
`OffsetSizeAndStrideOpInterface` verifier.

Note: only `offset` and `size` are checked because `stride` is allowed
to be negative
(54d81e49e3).
2023-11-16 07:42:37 +01:00
Max191
dae3c44ce6 [mlir] Add vector.store/maskedstore of memref.subview memref alias folding (#72184)
Fixes https://github.com/openxla/iree/issues/15575
2023-11-14 14:24:54 -08:00
long.chen
1609f1c2a5 [mlir][affine][nfc] cleanup deprecated T.cast style functions (#71269)
detail see the docment: https://mlir.llvm.org/deprecation/

Not all changes are made manually, most of them are made through a clang
tool I wrote https://github.com/lipracer/cpp-refactor.
2023-11-14 13:01:19 +08:00
Felix Schneider
6343ee7292 [mlir] Fix handling of "no rank reduction" case in two Patterns (#71293)
This patch fixes two checks where a `SmallBitVector` containing the
potential dropped dims of a SubView/ExtractSlice operation was queried
via `empty()` instead of `none()`.
2023-11-10 08:20:51 +01:00
Quinn Dawkins
48f980c535 [mlir][memref] Add memref alias folding for masked transfers (#71476)
The contents of a mask on a masked transfer are unaffected by the
particular region of memory being read/stored to, so just forward the
mask in subview folding patterns.
2023-11-07 08:56:54 -05:00
tyb0807
5aa2c65abd [mlir][MemRef] Add subview folding pattern for vector.maskedload (#71380)
This is required for fixing https://github.com/openxla/iree/issues/15031
2023-11-06 20:08:30 +01:00
Théo Degioanni
b142501e92 [mlir][memref] Fix segfault in SROA (#71063)
Fixes #70902.

The out of bounds check in the SROA implementation for MemRef was not
actually testing anything because it only operated on a store op which
does not trigger the logic by itself. It is now checked for real and the
underlying bug is fixed.

I checked the LLVM implementation just in case but this should not
happen as out-of-bound checks happen in GEP's verifier there.
2023-11-06 13:53:16 +01:00
Matthias Springer
437c62178c [mlir][memref] Remove redundant memref.tensor_store op (#71010)
`bufferization.materialize_in_destination` should be used instead. Both
ops bufferize to a memcpy. This change also conceptually cleans up the
memref dialect a bit: the memref dialect no longer contains ops that
operate on tensor values.
2023-11-05 12:47:18 +09:00
Christian Ulmann
da5b382d8c [MLIR][MemRefToLLVM] Remove last typed pointer remnants (#71113)
This commit removes the last typed pointer remnants from the MemRef to
LLVM conversions, including the transform dialect operation. Typed
pointers have been deprecated for a while now and it's planned to soon
remove them from the LLVM dialect.

Related PSA:
https://discourse.llvm.org/t/psa-removal-of-typed-pointers-from-the-llvm-dialect/74502
2023-11-03 10:55:11 +01:00
Jie Fu
c308cb9da6 [mlir] Fix -Wsign-compare in ResolveShapedTypeResultDims.cpp (NFC)
/llvm-project/mlir/lib/Dialect/MemRef/Transforms/ResolveShapedTypeResultDims.cpp:98:19: error: comparison of integers of different signs: 'value_type' (aka 'long long') and 'size_t' (aka 'unsigned long') [-Werror,-Wsign-compare]
    if (*dimIndex >= reifiedResultShapes[resultNumber].size())
        ~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-10-31 19:04:37 +08:00
Matthias Springer
6086c272a3 [mlir][memref] Fix out-of-bounds crash when reifying result dims (#70774)
Do not crash when the input IR is invalid, i.e., when the index of the
dimension operand of a `tensor.dim`/`memref.dim` is out-of-bounds. This
fixes #70180.
2023-10-31 17:26:56 +09:00
Felix Schneider
f32b3e1caa [mlir][memref] Fix index delinearization for CollapseShapeOp folding (#68833)
The `resolveSourceIndicesCollapseShape` method is used to compute
indices into the source `MemRef` of a `CollapseShapeOp` from the
collapsed indices. This method didn't check for dynamic sizes of the
source shape which led to a crash.

Fix https://github.com/llvm/llvm-project/issues/68483
2023-10-12 07:12:43 +02:00
Kunwar Grover
8f397e04e5 [mlir][memref] Fix emulate narrow types for strided memref offset (#68181)
This patch fixes strided memref offset calculation for emulating narrow
types.

As a side effect, this patch also adds support for a 1-D subviews with
static sizes, static offsets and strides of 1 for testing. Emulate
narrow types pass was not tested for strided memrefs before this patch.
2023-10-06 04:52:33 +05:30
qcolombet
932dc9d8c4 [mlir][MemRef] Add a pattern to simplify `extract_strided_metadata(ca… (#68291)
…st)`

`expand-strided-metadata` was missing a pattern to get rid of
`memref.cast`.
The pattern is straight foward:
Produce a new `extract_strided_metadata` with the source of the cast and
fold the static information (sizes, strides, offset) along the way.
2023-10-05 14:32:42 +02:00
Stella Laurenzo
8d203100e8 Revert "[mlir][memref] Fix offset update in emulating narrow type for strided memref (#67714)"
This reverts commit 35ec6ea644.

Breaks downstream narrow type execution tests.
2023-09-29 18:49:33 -07:00
Kunwar Grover
35ec6ea644 [mlir][memref] Fix offset update in emulating narrow type for strided memref (#67714)
The offset when converting type in emulating narrow types did not
account for the offset in strided memrefs. This patch fixes this.
2023-09-29 01:08:43 +05:30
Ingo Müller
991cb14715 [mlir][memref][transform] Add new alloca_to_global op. (#66511)
This PR adds a new transform op that replaces `memref.alloca`s with
`memref.get_global`s to newly inserted `memref.global`s. This is useful,
for example, for allocations that should reside in the shared memory of
a GPU, which have to be declared as globals.
2023-09-21 18:17:00 +02:00
Martin Erhart
65341b09b0 [mlir][bufferization][NFC] Move memref specific implementation of AllocationOpInterface to memref dialect directory (#66637)
Follow-up on #65578
2023-09-20 14:49:52 +02:00
Matthias Springer
9b5ef2bea8 [mlir][Interfaces] LoopLikeOpInterface: Support ops with multiple regions (#66754)
This commit implements `LoopLikeOpInterface` on `scf.while`. This
enables LICM (and potentially other transforms) on `scf.while`.

`LoopLikeOpInterface::getLoopBody()` is renamed to `getLoopRegions` and
can now return multiple regions.

Also fix a bug in the default implementation of
`LoopLikeOpInterface::isDefinedOutsideOfLoop()`, which returned "false"
for some values that are defined outside of the loop (in a nested op, in
such a way that the value does not dominate the loop). This interface is
currently only used for LICM and there is no way to trigger this bug, so
no test is added.
2023-09-19 17:35:38 +02:00
Daniil Dudkin
01e80a0f41 [mlir] Add maxnumf and minnumf to AtomicRMWKind (#66442)
This commit adds the mentioned kinds of `AtomicRMWKind`
as well as code generation for them.
2023-09-15 22:41:51 +03:00
Daniil Dudkin
6f4a528698 [mlir][memref] Use dedicated ops in AtomicRMWOpConverter (#66437)
This patch refactors the `AtomicRMWOpConverter` class to use
the dedicated operations from Arith dialect instead of using
`cmpf` + `select` pattern.
Also, a test for `minimumf` kind of `atomic_rmw` has been added.
2023-09-15 00:52:35 +03:00
Daniil Dudkin
c46a04339a [mlir][arith] Rename AtomicRMWKind's maxfmaximumf, minfminimumf (#66135)
This patch is part of a larger initiative aimed at fixing floating-point
`max` and `min` operations in MLIR:
https://discourse.llvm.org/t/rfc-fix-floating-point-max-and-min-operations-in-mlir/72671.

This commit renames `maxf` and `minf` enumerators of `AtomicRMWKind`
to better reflect the current naming scheme and the goals of the RFC.
2023-09-14 01:09:37 +03:00
Oleksandr "Alex" Zinenko
e55e36de7a [mlir] alloc-to-alloca conversion for memref (#65335)
Introduce a simple conversion of a memref.alloc/dealloc pair into an
alloca in the same scope. Expose it as a transform op and a pattern.

Allocas typically lower to stack allocations as opposed to alloc/dealloc
that lower to significantly more expensive malloc/free calls. In
addition, this can be combined with allocation hoisting from loops to
further improve performance.
2023-09-05 17:58:22 +02:00
Martin Erhart
8037deb7af [mlir][memref] Add pass to expand realloc operations, simplify lowering to LLVM
There are two motivations for this change:
1. It considerably simplifies adding support for the realloc operation to the
   new buffer deallocation pass by lowering the realloc such that no
   deallocation operation is inserted and the deallocation pass itself can
   insert that dealloc
2. The lowering is expressed on a higher level and thus easier to understand,
   and the lowerings of the memref operations it is composed of don't have to
   be duplicated in the MemRefToLLVM lowering (also see discussion in
   https://reviews.llvm.org/D133424)

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D159430
2023-09-05 08:58:40 +00:00
Fangrui Song
7557530f42 [mlir] Fix duplicate word typos; NFC
Those fixes were taken from https://reviews.llvm.org/D137338
2023-09-01 20:53:08 -07:00
Hanhan Wang
c5dee18b63 [mlir][memref] Add support for erasing dead allocations.
Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D159135
2023-09-01 13:30:26 -07:00
Andrey Turetskiy
01f4390a51 [MLIR] Fold memref.reinterpret_cast(x) -> x when the type is fully static and
does not change.

Differential Revision: https://reviews.llvm.org/D149296
2023-08-30 20:50:18 -07:00
Mikhail Goncharov
0a0aff2d24 fix unused variable warnings in conditionals
warning was updated in 92023b1509
2023-08-30 19:09:27 +02:00
Markus Böck
4dd744ac9c Reland "[mlir] Use a type for representing branch points in RegionBranchOpInterface"
This reverts commit b26bb30b46.
2023-08-30 09:31:54 +02:00
Markus Böck
b26bb30b46 Revert "[mlir] Use a type for representing branch points in RegionBranchOpInterface"
This reverts commit 024f562da6.

Forgot to update flang
2023-08-29 20:17:50 +02:00
Markus Böck
024f562da6 [mlir] Use a type for representing branch points in RegionBranchOpInterface
The current implementation is not very ergonomic or descriptive: It uses `std::optional<unsigned>` where `std::nullopt` represents the parent op and `unsigned` is the region number.
This doesn't give us any useful methods specific to region control flow and makes the code fragile to changes due to now taking the region number into account.

This patch introduces a new type called `RegionBranchPoint`, replacing all uses of `std::optional<unsigned>` in the interface. It can be implicitly constructed from a region or a `RegionSuccessor`, can be compared with a region to check whether the branch point is branching from the parent, adds `isParent` to check whether we are coming from a parent op and adds `RegionSuccessor::parent` as a descriptive way to indicate branching from the parent.

Differential Revision: https://reviews.llvm.org/D159116
2023-08-29 20:02:23 +02:00
Adrian Kuegel
6cde64a949 [mlir] Apply ClangTidy fix (NFC)
Prefer to use empty() instead of checking size() > 0.
2023-08-29 09:33:48 +02:00
Matthias Springer
e3373c6c83 [mlir][memref] Fix crash in SubViewReturnTypeCanonicalizer
`SubViewReturnTypeCanonicalizer` is used by `OpWithOffsetSizesAndStridesConstantArgumentFolder`, which folds constant SSA value (dynamic) sizes into static sizes. The previous implementation crashed when a dynamic size was folded into a static `1` dimension, which was then mistaken as a rank reduction.

Differential Revision: https://reviews.llvm.org/D158721
2023-08-25 16:01:49 +02:00
Jie Fu
c730c62715 [mlir] Fix -Wctad-maybe-unsupported in MemRefUtils.cpp (NFC)
/Users/jiefu/llvm-project/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp:56:3: error: 'SmallVector' may not intend to support class template argument deduction [-Werror,-Wctad-maybe-unsupported]
  SmallVector indicesVec = llvm::to_vector(indices);
  ^
/Users/jiefu/llvm-project/mlir/include/mlir/Support/LLVM.h:69:7: note: add a deduction guide to suppress this warning
class SmallVector;
      ^
1 error generated.
2023-08-18 07:13:48 +08:00
Mahesh Ravishankar
0f8bab8d59 [mlir] Revamp implementation of sub-byte load/store emulation.
When handling sub-byte emulation, the sizes of the converted `memref`s
also need to be updated (this was not done in the current
implementation). This adds the additional complexity of having to
linearize the `memref`s as well. Consider a `memref<3x3xi4>` where the
`i4` elements are packed. This has a overall size of 5 bytes (rounded
up to number of bytes). This can only be represented by a
`memref<5xi8>`. A `memref<3x2xi8>` would imply an implicit padding of
4 bits at the end of each row. So incorporate linearization into the
sub-byte load-store emulation.

This patch also updates some of the utility functions to make better
use of statically available information using `OpFoldResult` and
`makeComposedFoldedAffineApplyOps`.

Reviewed By: hanchung, yzhang93

Differential Revision: https://reviews.llvm.org/D158125
2023-08-17 20:27:53 +00:00
Matthias Springer
a02ad6c177 [mlir][bufferization] Generalize getAliasingOpResults to getAliasingValues
This revision is needed to support bufferization of `cf.br`/`cf.cond_br`. It will also be useful for better analysis of loop ops.

This revision generalizes `getAliasingOpResults` to `getAliasingValues`. An OpOperand can now not only alias with OpResults but also with BlockArguments. In the case of `cf.br` (will be added in a later revision): a `cf.br` operand will alias with the corresponding argument of the destination block.

If an op does not implement the `BufferizableOpInterface`, the analysis in conservative. It previously assumed that an OpOperand may alias with each OpResult. It now assumes that an OpOperand may alias with each OpResult and each BlockArgument of the entry block.

Differential Revision: https://reviews.llvm.org/D157957
2023-08-15 15:02:47 +02:00
Hanhan Wang
f6897c37a2 [mlir][MemRef] Bail out for unsupported cases in FoldMemRefAliasOps pass
The pass uses `computeSuffixProduct` method which only allows static
shapes. This revision adds an early-exit for dynamic cases to avoid
crash.

Reviewed By: mravishankar

Differential Revision: https://reviews.llvm.org/D157668
2023-08-11 14:52:53 -07:00
Nicolas Vasilache
920c461219 [mlir][Transform] Add support to drive conversions of func to LLVM with TD
This revision adds a `transform.apply_conversion_patterns.func.func_to_llvm` transformation.

It is unclear at this point whether this should be spelled out as a standalone transformation
or whether it should resemble `transform.apply_conversion_patterns.dialect_to_llvm "fun"`.

This is dependent on how we want to handle the type converter creation.
In particular the current implementation exhibits the fact that
`transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter` was not rich enough
and did not match the LowerToLLVMOptions.

Keeping those options in sync across all the passes that lower to LLVM is very error prone.
Instead, we should have a single `to_llvm_type_converter`.

Differential Revision: https://reviews.llvm.org/D157553
2023-08-10 13:17:00 +00:00
Markus Böck
138df29820 [mlir] Revamp RegionBranchOpInterface successor mechanism
The `RegionBranchOpInterface` had a few fundamental issues caused by the API design of `getSuccessorRegions`.

It always required passing values for the `operands` parameter. This is problematic as the operands parameter actually changes meaning depending on which predecessor `index` is referring to. If coming from a region, you'd have to find a `RegionBranchTerminatorOpInterface` in that region, get its operand count, and then create a `SmallVector` of that size.
This is not only inconvenient, but also error-prone, which has lead to a bug in the implementation of a previously existing `getSuccessorRegions` overload.

Additionally, this made the method dual-use, trying to serve two different use-cases: 1) Trying to determine possible control flow edges between regions and 2) Trying to determine the region being branched to based on constant operands.

This patch fixes these issues by changing the interface methods and adding new ones:
* The `operands` argument of `getSuccessorRegions` has been removed. The method is now only responsible for returning possible control flow edges between regions.
* An optional `getEntrySuccessorRegions` method has been added. This is used to determine which regions are branched to from the parent op based on constant operands of the parent op. By default, it calls `getSuccessorRegions`. This is analogous to `getSuccessorForOperands` from `BranchOpInterface`.
* Add `getSuccessorRegions` to `RegionBranchTerminatorOpInterface`. This is used to get the possible successors of the terminator based on constant operands. By default, it calls the containing `RegionBranchOpInterface`s `getSuccessorRegions` method.
* `getSuccessorEntryOperands` was renamed to `getEntrySuccessorOperands` for consistency.

Differential Revision: https://reviews.llvm.org/D157506
2023-08-10 10:27:27 +02:00
Matthias Springer
7ec88f06d5 [mlir][memref][transform] Add vector_to_llvm conversion patterns
These patterns are exposed via a new "apply_conversion_patterns" op.

Also provide a new type converter that converts from memref to LLVM types. Conversion patterns that lower to LLVM are special: they require an `LLVMTypeConverter`; a normal `TypeConverter` is not enough. This revision also adds a new interface method to pattern descriptor ops to verify that the default type converter of the enclosing "apply_conversion_patterns" op is compatible with the set of patterns. At the moment, a simple `StringRef` is used. This can evolve to a richer type in the future if needed.

Differential Revision: https://reviews.llvm.org/D157369
2023-08-09 11:27:53 +02:00