[all-commits] [llvm/llvm-project] a1a806: [memref] Support non-scalar copies in `reinterpret...
ioana ghiban via All-commits
all-commits at lists.llvm.org
Mon Jul 13 07:39:31 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: a1a806bb371550661aaee787d2a3622d9e84d528
https://github.com/llvm/llvm-project/commit/a1a806bb371550661aaee787d2a3622d9e84d528
Author: ioana ghiban <ioana.ghiban at arm.com>
Date: 2026-07-13 (Mon, 13 Jul 2026)
Changed paths:
M mlir/include/mlir/Dialect/MemRef/Transforms/Passes.td
M mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt
M mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
M mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
Log Message:
-----------
[memref] Support non-scalar copies in `reinterpret_cast` elision (#203873)
Extends `memref-elide-reinterpret-cast` from scalar-only copy
transformation to also handle copies of effectively 1D and static
multidimensional regions.
The rewrite is limited to cases where each non-unit `reinterpret_cast`
result dimension maps directly to a distinct identity-layout source
dimension with the same stride and sufficient static size. This lets the
rewrite use each loop IV
directly as a source memref index. Cases where result strides do not
match source identity strides are left untouched because they would
require linearization/delinearization across source dimensions.
Assisted-by: Codex (refine implementation + tests). I reviewed all code
and tests before submission.
## Examples
Scalar copy, unchanged(*) behavior:
```mlir
// BEFORE
%view = memref.reinterpret_cast %dst
to offset: [1], sizes: [1, 1], strides: [1, 1]
: memref<1x108xf32> to memref<1x1xf32, strided<[1, 1], offset: 1>>
memref.copy %src, %view : memref<1x1xf32> to memref<1x1xf32, strided<[1, 1], offset: 1>>
// AFTER
%v = memref.load %src[%c0, %c0] : memref<1x1xf32>
memref.store %v, %dst[%c0, %c1] : memref<1x108xf32>
```
Effectively 1D copy:
```mlir
// BEFORE
%view = memref.reinterpret_cast %dst
to offset: [0], sizes: [1, 33, 1], strides: [1386, 42, 1]
: memref<1x33x42xf32> to memref<1x33x1xf32, strided<[1386, 42, 1]>>
memref.copy %src, %view : memref<1x33x1xf32> to memref<1x33x1xf32, strided<[1386, 42, 1]>>
// AFTER
scf.for %i = %c0 to %c33 step %c1 {
%v = memref.load %src[%c0, %i, %c0] : memref<1x33x1xf32>
memref.store %v, %dst[%c0, %i, %c0] : memref<1x33x42xf32>
}
```
Static 2D copy with offset becomes a nested loop with the static offset
folded into the `reinterpret_cast` source store indices.
```mlir
// BEFORE
%view = memref.reinterpret_cast %dst
to offset: [16], sizes: [1, 33, 4], strides: [1386, 42, 1]
: memref<1x33x42xf32>
to memref<1x33x4xf32, strided<[1386, 42, 1], offset: 16>>
memref.copy %src, %view
// AFTER
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c4 = arith.constant 4 : index
%c16 = arith.constant 16 : index
%c33 = arith.constant 33 : index
scf.for %i = %c0 to %c33 step %c1 {
scf.for %j = %c0 to %c4 step %c1 {
%v = memref.load %src[%c0, %i, %j]
memref.store %v, %dst[%c0, %i, %c16 + %j]
}
}
```
## Scope
Supported:
- ranked, static-shape copy source and `reinterpret_cast` source/result
memrefs
- identity-layout `reinterpret_cast` sources
- rank-preserving `reinterpret_cast`s
- scalar copies, including dynamic result strides because all result
indices are zero
- non-scalar copies where every non-unit result dimension has a static
stride matching a distinct source dimension with sufficient static size
- static offsets, delinearized into source indices
- dynamic offsets only when the `reinterpret_cast` source has at most
one non-unit dimension and the result has at most one mapped non-unit
dimension
Not addressed:
- unranked or dynamic-shape copy/reinterpret_cast operands
- non-identity-layout `reinterpret_cast` sources
- rank-changing `reinterpret_cast`s
- dynamic strides on non-unit result dimensions
- result dimensions whose strides do not match source identity strides
- result dimensions that reuse a source dimension or cross source
dimension boundaries
- dynamic offsets requiring runtime div/rem delinearization
## Correctness
Result indices are translated to source indices by direct dimension
mapping: each non-unit result dimension must have the same stride as a
distinct source dimension.
Static offsets are delinearized into source indices before rewriting.
Dynamic offsets are only accepted when they can be used directly in the
single non-unit source dimension.
Cases assumed invalid by `reinterpret_cast`/`copy` semantics are guarded
with assertions.
(*) NFC to scalar copy case, we're now only creating zero constants for
indices once.
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list