[Mlir-commits] [mlir] [mlir][memref] Support reducing copied dims to non-unit in reinterpret_cast elision (PR #209536)
ioana ghiban
llvmlistbot at llvm.org
Wed Jul 15 02:02:50 PDT 2026
https://github.com/ioghiban updated https://github.com/llvm/llvm-project/pull/209536
>From 5905cd319ad0a104d1316e05f53d4a40eff839b3 Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Tue, 14 Jul 2026 17:43:06 +0200
Subject: [PATCH 1/2] [memref] Support reducing copied dims to non-unit in
reinterpret_cast elision
---
.../Transforms/ElideReinterpretCast.cpp | 62 ++++++-------
.../MemRef/elide-reinterpret-cast.mlir | 86 ++++++++++++++++---
2 files changed, 108 insertions(+), 40 deletions(-)
diff --git a/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp b/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
index a24a0ccaa3d67..eb5d673c27a70 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
@@ -84,7 +84,7 @@ delinearizeStaticRCOffset(memref::ReinterpretCastOp rc) {
return offsetIdxs;
}
-static bool hasExactlyOneCollapsedNonUnitDim(memref::ReinterpretCastOp rc) {
+static bool hasExactlyOneReducedNonUnitDim(memref::ReinterpretCastOp rc) {
MemRefType srcType = dyn_cast<MemRefType>(rc.getSource().getType());
MemRefType resType = dyn_cast<MemRefType>(rc.getType());
assert(srcType.hasStaticShape() && resType.hasStaticShape() &&
@@ -92,25 +92,26 @@ static bool hasExactlyOneCollapsedNonUnitDim(memref::ReinterpretCastOp rc) {
assert(srcType.getRank() == resType.getRank() &&
"expected rank-preserving reinterpret_cast");
- unsigned collapsedDims = 0;
+ unsigned reducedDims = 0;
for (auto [srcSize, resSize] :
llvm::zip_equal(srcType.getShape(), resType.getShape())) {
if (srcSize == resSize)
continue;
- // Only allow collapsing one non-unit source dim to a unit result dim.
- if (srcSize != 1 && resSize == 1) {
- ++collapsedDims;
+ // Only one non-unit source dimension may be reduced.
+ if (srcSize != 1 && resSize < srcSize) {
+ ++reducedDims;
continue;
}
- // The sizes differ and both of them are non-unit - ATM not supported.
+ // The size change is not a supported single non-unit source dimension
+ // reduction.
return false;
}
- // Make sure there is only one collapsed dimension.
- return collapsedDims == 1;
+ // Make sure there is only one reduced dimension.
+ return reducedDims == 1;
}
/// Returns the unique non-unit dim or nullopt if # non-unit-dims != 1.
@@ -134,21 +135,19 @@ static std::optional<unsigned> getSingleNonUnitDim(MemRefType type) {
/// offsets, delinearized offset.
///
/// Supports ranked, static-shape, rank-preserving reinterpret_casts from
-/// identity-layout sources. In addition:
-/// identical to the source identity strides, and exactly one non-unit
-/// source
-/// * Non-scalar results must have static offsets, static result strides
-/// dimension collapsed to unit size
-/// Scalar-shaped results may have arbitrary result strides (i.e. for scalars,
-/// strides are effectively irrelevant).
+/// identity-layout sources.
+/// * Scalar-shaped results may have arbitrary result strides.
+/// * Non-scalar results must have static offsets, static result strides
+/// identical to the source identity strides, and exactly one non-unit
+/// source dimension size reduced.
///
-/// Returns nullopt for unsupported
-/// reinterpret_casts.
+/// Returns nullopt for unsupported reinterpret_casts.
///
/// Examples that return info:
///
/// reinterpret_cast memref<1xMxNxf32, identity-layout>
-/// to memref<1xMx1xf32, strided<[M*N, N, 1], offset: OFF>>
+/// to memref<1xMxKxf32, strided<[M*N, N, 1], offset: OFF>>
+/// where K < N
///
/// reinterpret_cast memref<1xMxf32, identity-layout>
/// to memref<1x1xf32, strided<[?, ?], offset: ?>>
@@ -156,10 +155,11 @@ static std::optional<unsigned> getSingleNonUnitDim(MemRefType type) {
/// Examples that return no info:
///
/// reinterpret_cast memref<1xMxNxf32, identity-layout>
-/// to memref<1xMx1xf32, strided<[?, N, 1]>>
+/// to memref<1xMxKxf32, strided<[?, N, 1]>>
///
/// reinterpret_cast memref<1xMxNxf32, identity-layout>
-/// to memref<1xKx1xf32, strided<[M*N, N, 1], offset: OFF>>
+/// to memref<1xNxPxf32, strided<[M*N, N, 1], offset: OFF>>
+/// where M != N && N != P
static std::optional<ResultNonUnitDimsAndOffsetsForRC>
getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
MemRefType srcType = dyn_cast<MemRefType>(rc.getSource().getType());
@@ -221,7 +221,7 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
}))
return std::nullopt;
- if (!hasExactlyOneCollapsedNonUnitDim(rc))
+ if (!hasExactlyOneReducedNonUnitDim(rc))
return std::nullopt;
}
@@ -255,9 +255,9 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
/// the store index is derived from the reinterpret_cast offset.
///
/// 2. Non-scalar reinterpret_cast results that preserve all non-unit source
-/// dimensions except one collapsed-to-unit dimension. Result strides must
-/// be static and identical to the identity strides of the source, and the
-/// static offset selects the collapsed dimension.
+/// dimensions sizes except one. Result
+/// strides must be static and identical to the identity strides of the
+/// source, and the offset must be static.
///
/// // BEFORE (scalar-shaped result)
/// %strided = memref.reinterpret_cast %dst
@@ -268,18 +268,20 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
/// %v = memref.load %src[0, ..., 0]
/// memref.store %v, %dst[delinearized(OFF)]
///
-/// // BEFORE (one collapsed non-unit dimension)
+/// // BEFORE (same-dimension static slice)
/// %strided = memref.reinterpret_cast %dst
-/// to offset: [OFF], sizes: [1, M, 1], strides: [M*N, N, 1]
+/// to offset: [OFF], sizes: [1, M, K], strides: [M*N, N, 1]
/// : memref<1xMxNxf32>
-/// to memref<1xMx1xf32, strided<[M*N, N, 1], offset: OFF>>
+/// to memref<1xMxKxf32, strided<[M*N, N, 1], offset: OFF>>
/// memref.copy %src, %strided
///
/// // AFTER
-/// // Assuming OFF delinearizes to [0, 0, OFF]:
+/// // Assuming OFF delinearizes to [0, 0, j]:
/// scf.for %i = 0 to M step 1 {
-/// %v = memref.load %src[0, %i, 0]
-/// memref.store %v, %dst[0, %i, OFF]
+/// scf.for %k = 0 to K step 1 {
+/// %v = memref.load %src[0, %i, %k]
+/// memref.store %v, %dst[0, %i, j + %k]
+/// }
/// }
struct CopyToLoadAndStore : public OpRewritePattern<memref::CopyOp> {
public:
diff --git a/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir b/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
index 0955d9638f093..1145c7b010ff1 100644
--- a/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
+++ b/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
@@ -262,20 +262,27 @@ func.func private @negative_copy_scalar_into_2D_strided_dynamic_offset(
// Non-scalar (ND) copy
//===----------------------------------------------------------------------===//
-/// The result of collapsing dimensions is not a unit dimension.
-// CHECK-LABEL: func.func private @negative_copy_1D_into_1D_strided(
-func.func private @negative_copy_1D_into_1D_strided(
+// CHECK-LABEL: func.func private @copy_1D_into_1D_strided_zero_offset(
+// CHECK-SAME: %[[SRC:.*]]: memref<4xf32>
+// CHECK-SAME: %[[DST:.*]]: memref<108xf32>
+func.func private @copy_1D_into_1D_strided_zero_offset(
%src : memref<4xf32>, %dst : memref<108xf32>) {
- // CHECK: %reinterpret_cast = memref.reinterpret_cast %arg1
+ // CHECK-NOT: memref.reinterpret_cast
%rc = memref.reinterpret_cast %dst
to offset: [0], sizes: [4], strides: [1]
: memref<108xf32> to memref<4xf32, strided<[1]>>
- // CHECK: memref.copy %arg0, %reinterpret_cast
- // CHECK-NOT: memref.load
- // CHECK-NOT: memref.store
+ // CHECK-NOT: memref.copy
+ // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+ // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+ // CHECK-DAG: %[[UB:.*]] = arith.constant 4 : index
+ // CHECK: scf.for %[[IDX:.*]] = %[[C0]] to %[[UB]] step %[[C1]] {
+ // CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[IDX]]] : memref<4xf32>
+ // CHECK: memref.store %[[VAL]], %[[DST]][%[[IDX]]] : memref<108xf32>
+ // CHECK: }
memref.copy %src, %rc
: memref<4xf32> to memref<4xf32, strided<[1]>>
+ // CHECK-NOT: memref.copy
return
}
@@ -418,9 +425,8 @@ func.func private @negative_copy_1D_into_2D_strided_zero_offset_dynamic_stride(%
return
}
-/// 4 is collapsed to a non-unit dimension.
-// CHECK-LABEL: func.func private @negative_copy_1D_into_2D_strided_diff_dim_sizes(
-func.func private @negative_copy_1D_into_2D_strided_diff_dim_sizes(
+// CHECK-LABEL: func.func private @negative_copy_1D_into_2D_more_reduced_dims(
+func.func private @negative_copy_1D_into_2D_more_reduced_dims(
%src : memref<1x3x1xf32>, %dst : memref<1x4x11xf32>) {
// CHECK: %reinterpret_cast = memref.reinterpret_cast %arg1
%rc = memref.reinterpret_cast %dst
@@ -437,6 +443,66 @@ func.func private @negative_copy_1D_into_2D_strided_diff_dim_sizes(
return
}
+// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_zero_offset(
+// CHECK-SAME: %[[SRC:.*]]: memref<1x3x4xf32>
+// CHECK-SAME: %[[DST:.*]]: memref<1x3x11xf32>
+func.func private @copy_2D_into_2D_strided_zero_offset(
+ %src : memref<1x3x4xf32>, %dst : memref<1x3x11xf32>) {
+ // CHECK-NOT: memref.reinterpret_cast
+ %rc = memref.reinterpret_cast %dst
+ to offset: [0], sizes: [1, 3, 4], strides: [33, 11, 1]
+ : memref<1x3x11xf32>
+ to memref<1x3x4xf32, strided<[33, 11, 1]>>
+
+ // CHECK-NOT: memref.copy
+ // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+ // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+ // CHECK-DAG: %[[UB0:.*]] = arith.constant 3 : index
+ // CHECK-DAG: %[[UB1:.*]] = arith.constant 4 : index
+ // CHECK: scf.for %[[IDX0:.*]] = %[[C0]] to %[[UB0]] step %[[C1]] {
+ // CHECK: scf.for %[[IDX1:.*]] = %[[C0]] to %[[UB1]] step %[[C1]] {
+ // CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[C0]], %[[IDX0]], %[[IDX1]]] : memref<1x3x4xf32>
+ // CHECK: memref.store %[[VAL]], %[[DST]][%[[C0]], %[[IDX0]], %[[IDX1]]] : memref<1x3x11xf32>
+ // CHECK: }
+ // CHECK: }
+ memref.copy %src, %rc
+ : memref<1x3x4xf32>
+ to memref<1x3x4xf32, strided<[33, 11, 1]>>
+ // CHECK-NOT: memref.copy
+ return
+}
+
+// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_nonzero_offset(
+// CHECK-SAME: %[[SRC:.*]]: memref<1x3x4xf32>
+// CHECK-SAME: %[[DST:.*]]: memref<1x3x11xf32>
+func.func private @copy_2D_into_2D_strided_nonzero_offset(
+ %src : memref<1x3x4xf32>, %dst : memref<1x3x11xf32>) {
+ // CHECK-NOT: memref.reinterpret_cast
+ %rc = memref.reinterpret_cast %dst
+ to offset: [6], sizes: [1, 3, 4], strides: [33, 11, 1]
+ : memref<1x3x11xf32>
+ to memref<1x3x4xf32, strided<[33, 11, 1], offset: 6>>
+
+ // CHECK-NOT: memref.copy
+ // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+ // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+ // CHECK-DAG: %[[UB0:.*]] = arith.constant 3 : index
+ // CHECK-DAG: %[[UB1:.*]] = arith.constant 4 : index
+ // CHECK-DAG: %[[OFF:.*]] = arith.constant 6 : index
+ // CHECK: scf.for %[[IDX0:.*]] = %[[C0]] to %[[UB0]] step %[[C1]] {
+ // CHECK: scf.for %[[IDX1:.*]] = %[[C0]] to %[[UB1]] step %[[C1]] {
+ // CHECK: %[[DST_IDX:.*]] = arith.addi %[[OFF]], %[[IDX1]] : index
+ // CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[C0]], %[[IDX0]], %[[IDX1]]] : memref<1x3x4xf32>
+ // CHECK: memref.store %[[VAL]], %[[DST]][%[[C0]], %[[IDX0]], %[[DST_IDX]]] : memref<1x3x11xf32>
+ // CHECK: }
+ // CHECK: }
+ memref.copy %src, %rc
+ : memref<1x3x4xf32>
+ to memref<1x3x4xf32, strided<[33, 11, 1], offset: 6>>
+ // CHECK-NOT: memref.copy
+ return
+}
+
// CHECK-LABEL: func.func private @copy_2D_into_3D_strided_zero_offset(
// CHECK-SAME: %[[SRC:.*]]: memref<3x1x4x1xf32>
// CHECK-SAME: %[[DST:.*]]: memref<3x1x4x11xf32>
>From c96967b11aa5c6fbecdbd1fd4021c8285c8f62aa Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Wed, 15 Jul 2026 11:01:41 +0200
Subject: [PATCH 2/2] Address comments
---
.../Transforms/ElideReinterpretCast.cpp | 22 ++++----
.../MemRef/elide-reinterpret-cast.mlir | 55 +++++++++++++++++--
2 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp b/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
index eb5d673c27a70..47180db268d78 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/ElideReinterpretCast.cpp
@@ -84,7 +84,7 @@ delinearizeStaticRCOffset(memref::ReinterpretCastOp rc) {
return offsetIdxs;
}
-static bool hasExactlyOneReducedNonUnitDim(memref::ReinterpretCastOp rc) {
+static bool hasExactlyOneTruncatedNonUnitDim(memref::ReinterpretCastOp rc) {
MemRefType srcType = dyn_cast<MemRefType>(rc.getSource().getType());
MemRefType resType = dyn_cast<MemRefType>(rc.getType());
assert(srcType.hasStaticShape() && resType.hasStaticShape() &&
@@ -92,16 +92,16 @@ static bool hasExactlyOneReducedNonUnitDim(memref::ReinterpretCastOp rc) {
assert(srcType.getRank() == resType.getRank() &&
"expected rank-preserving reinterpret_cast");
- unsigned reducedDims = 0;
+ unsigned truncatedDims = 0;
for (auto [srcSize, resSize] :
llvm::zip_equal(srcType.getShape(), resType.getShape())) {
if (srcSize == resSize)
continue;
- // Only one non-unit source dimension may be reduced.
+ // Only one non-unit source dimension may be truncated.
if (srcSize != 1 && resSize < srcSize) {
- ++reducedDims;
+ ++truncatedDims;
continue;
}
@@ -110,8 +110,8 @@ static bool hasExactlyOneReducedNonUnitDim(memref::ReinterpretCastOp rc) {
return false;
}
- // Make sure there is only one reduced dimension.
- return reducedDims == 1;
+ // Make sure there is only one truncated dimension.
+ return truncatedDims == 1;
}
/// Returns the unique non-unit dim or nullopt if # non-unit-dims != 1.
@@ -139,7 +139,7 @@ static std::optional<unsigned> getSingleNonUnitDim(MemRefType type) {
/// * Scalar-shaped results may have arbitrary result strides.
/// * Non-scalar results must have static offsets, static result strides
/// identical to the source identity strides, and exactly one non-unit
-/// source dimension size reduced.
+/// source dimension size truncated.
///
/// Returns nullopt for unsupported reinterpret_casts.
///
@@ -221,7 +221,7 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
}))
return std::nullopt;
- if (!hasExactlyOneReducedNonUnitDim(rc))
+ if (!hasExactlyOneTruncatedNonUnitDim(rc))
return std::nullopt;
}
@@ -268,7 +268,7 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
/// %v = memref.load %src[0, ..., 0]
/// memref.store %v, %dst[delinearized(OFF)]
///
-/// // BEFORE (same-dimension static slice)
+/// // BEFORE (one truncated non-unit dimension)
/// %strided = memref.reinterpret_cast %dst
/// to offset: [OFF], sizes: [1, M, K], strides: [M*N, N, 1]
/// : memref<1xMxNxf32>
@@ -276,11 +276,11 @@ getResultNonUnitDimsAndOffsetsForRC(memref::ReinterpretCastOp rc) {
/// memref.copy %src, %strided
///
/// // AFTER
-/// // Assuming OFF delinearizes to [0, 0, j]:
+/// // Assuming OFF delinearizes to [0, 0, OFF]:
/// scf.for %i = 0 to M step 1 {
/// scf.for %k = 0 to K step 1 {
/// %v = memref.load %src[0, %i, %k]
-/// memref.store %v, %dst[0, %i, j + %k]
+/// memref.store %v, %dst[0, %i, OFF + %k]
/// }
/// }
struct CopyToLoadAndStore : public OpRewritePattern<memref::CopyOp> {
diff --git a/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir b/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
index 1145c7b010ff1..f305de1ccd0d8 100644
--- a/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
+++ b/mlir/test/Dialect/MemRef/elide-reinterpret-cast.mlir
@@ -425,8 +425,8 @@ func.func private @negative_copy_1D_into_2D_strided_zero_offset_dynamic_stride(%
return
}
-// CHECK-LABEL: func.func private @negative_copy_1D_into_2D_more_reduced_dims(
-func.func private @negative_copy_1D_into_2D_more_reduced_dims(
+// CHECK-LABEL: func.func private @negative_copy_1D_into_2D_multiple_truncated_dims(
+func.func private @negative_copy_1D_into_2D_multiple_truncated_dims(
%src : memref<1x3x1xf32>, %dst : memref<1x4x11xf32>) {
// CHECK: %reinterpret_cast = memref.reinterpret_cast %arg1
%rc = memref.reinterpret_cast %dst
@@ -443,6 +443,22 @@ func.func private @negative_copy_1D_into_2D_more_reduced_dims(
return
}
+// CHECK-LABEL: func.func private @negative_copy_into_strided_no_truncated_dims(
+func.func private @negative_copy_into_strided_no_truncated_dims(%src : memref<3x4xf32>,
+ %dst : memref<3x4xf32>) {
+ // CHECK: %reinterpret_cast = memref.reinterpret_cast %arg1
+ %rc = memref.reinterpret_cast %dst
+ to offset: [0], sizes: [3, 4], strides: [12, 1]
+ : memref<3x4xf32> to memref<3x4xf32, strided<[12, 1]>>
+
+ // CHECK: memref.copy %arg0, %reinterpret_cast
+ // CHECK-NOT: memref.load
+ // CHECK-NOT: memref.store
+ memref.copy %src, %rc
+ : memref<3x4xf32> to memref<3x4xf32, strided<[12, 1]>>
+ return
+}
+
// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_zero_offset(
// CHECK-SAME: %[[SRC:.*]]: memref<1x3x4xf32>
// CHECK-SAME: %[[DST:.*]]: memref<1x3x11xf32>
@@ -472,10 +488,10 @@ func.func private @copy_2D_into_2D_strided_zero_offset(
return
}
-// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_nonzero_offset(
+// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_nonzero_offset_delinearized_v1(
// CHECK-SAME: %[[SRC:.*]]: memref<1x3x4xf32>
// CHECK-SAME: %[[DST:.*]]: memref<1x3x11xf32>
-func.func private @copy_2D_into_2D_strided_nonzero_offset(
+func.func private @copy_2D_into_2D_strided_nonzero_offset_delinearized_v1(
%src : memref<1x3x4xf32>, %dst : memref<1x3x11xf32>) {
// CHECK-NOT: memref.reinterpret_cast
%rc = memref.reinterpret_cast %dst
@@ -503,6 +519,37 @@ func.func private @copy_2D_into_2D_strided_nonzero_offset(
return
}
+// CHECK-LABEL: func.func private @copy_2D_into_2D_strided_nonzero_offset_delinearized_v2(
+// CHECK-SAME: %[[SRC:.*]]: memref<1x3x11xf32>
+// CHECK-SAME: %[[DST:.*]]: memref<1x10x11xf32>
+func.func private @copy_2D_into_2D_strided_nonzero_offset_delinearized_v2(
+ %src : memref<1x3x11xf32>, %dst : memref<1x10x11xf32>) {
+ // CHECK-NOT: memref.reinterpret_cast
+ %rc = memref.reinterpret_cast %dst
+ to offset: [44], sizes: [1, 3, 11], strides: [110, 11, 1]
+ : memref<1x10x11xf32>
+ to memref<1x3x11xf32, strided<[110, 11, 1], offset: 44>>
+
+ // CHECK-NOT: memref.copy
+ // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+ // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+ // CHECK-DAG: %[[UB0:.*]] = arith.constant 3 : index
+ // CHECK-DAG: %[[UB1:.*]] = arith.constant 11 : index
+ // CHECK-DAG: %[[OFF:.*]] = arith.constant 4 : index
+ // CHECK: scf.for %[[IDX0:.*]] = %[[C0]] to %[[UB0]] step %[[C1]] {
+ // CHECK: %[[DST_IDX:.*]] = arith.addi %[[OFF]], %[[IDX0]] : index
+ // CHECK: scf.for %[[IDX1:.*]] = %[[C0]] to %[[UB1]] step %[[C1]] {
+ // CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[C0]], %[[IDX0]], %[[IDX1]]] : memref<1x3x11xf32>
+ // CHECK: memref.store %[[VAL]], %[[DST]][%[[C0]], %[[DST_IDX]], %[[IDX1]]] : memref<1x10x11xf32>
+ // CHECK: }
+ // CHECK: }
+ memref.copy %src, %rc
+ : memref<1x3x11xf32>
+ to memref<1x3x11xf32, strided<[110, 11, 1], offset: 44>>
+ // CHECK-NOT: memref.copy
+ return
+}
+
// CHECK-LABEL: func.func private @copy_2D_into_3D_strided_zero_offset(
// CHECK-SAME: %[[SRC:.*]]: memref<3x1x4x1xf32>
// CHECK-SAME: %[[DST:.*]]: memref<3x1x4x11xf32>
More information about the Mlir-commits
mailing list