Skip to content
This repository was archived by the owner on Apr 23, 2021. It is now read-only.

Commit 19cb0d1

Browse files
Mahesh Ravishankartensorflower-gardener
authored andcommitted
Allow memref_cast from static strides to dynamic strides.
Memref_cast supports cast from static shape to dynamic shape memrefs. The same should be true for strides as well, i.e a memref with static strides can be casted to a memref with dynamic strides. PiperOrigin-RevId: 282381862
1 parent 67c7ea4 commit 19cb0d1

4 files changed

Lines changed: 57 additions & 3 deletions

File tree

include/mlir/Dialect/StandardOps/Ops.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,16 @@ def MemRefCastOp : CastOp<"memref_cast"> {
831831
%2 = memref_cast %1 : memref<?x?xf32> to memref<4x4xf32>
832832
Erase static shape information, replacing it with dynamic information.
833833
%3 = memref_cast %1 : memref<4xf32> to memref<?xf32>
834+
835+
The same holds true for offsets and strides.
836+
837+
Assert that the input dynamic shape matches the destination static stride.
838+
%4 = memref_cast %1 : memref<12x4xf32, offset:?, strides: [?, ?]> to
839+
memref<12x4xf32, offset:5, strides: [4, 1]>
840+
Erase static offset and stride information, replacing it with
841+
dynamic information.
842+
%5 = memref_cast %1 : memref<12x4xf32, offset:5, strides: [4, 1]> to
843+
memref<12x4xf32, offset:?, strides: [?, ?]>
834844
}];
835845

836846
let arguments = (ins AnyMemRef:$source);

lib/Dialect/StandardOps/Ops.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,8 +1777,28 @@ bool MemRefCastOp::areCastCompatible(Type a, Type b) {
17771777
return false;
17781778
if (aT.getElementType() != bT.getElementType())
17791779
return false;
1780-
if (aT.getAffineMaps() != bT.getAffineMaps())
1781-
return false;
1780+
if (aT.getAffineMaps() != bT.getAffineMaps()) {
1781+
int64_t aOffset, bOffset;
1782+
SmallVector<int64_t, 4> aStrides, bStrides;
1783+
if (failed(getStridesAndOffset(aT, aStrides, aOffset)) ||
1784+
failed(getStridesAndOffset(bT, bStrides, bOffset)) ||
1785+
aStrides.size() != bStrides.size())
1786+
return false;
1787+
1788+
// Strides along a dimension/offset are compatible if the value in the
1789+
// source memref is static and the value in the target memref is the
1790+
// same. They are also compatible if either one is dynamic (see description
1791+
// of MemRefCastOp for details).
1792+
auto checkCompatible = [](int64_t a, int64_t b) {
1793+
return (a == MemRefType::getDynamicStrideOrOffset() ||
1794+
b == MemRefType::getDynamicStrideOrOffset() || a == b);
1795+
};
1796+
if (!checkCompatible(aOffset, bOffset))
1797+
return false;
1798+
for (auto aStride : enumerate(aStrides))
1799+
if (!checkCompatible(aStride.value(), bStrides[aStride.index()]))
1800+
return false;
1801+
}
17821802
if (aT.getMemorySpace() != bT.getMemorySpace())
17831803
return false;
17841804

test/IR/core-ops.mlir

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// CHECK-DAG: #[[VIEW_MAP3:map[0-9]+]] = (d0, d1)[s0] -> (d0 * s0 + d1)
1414

1515
// CHECK-DAG: #[[BASE_MAP0:map[0-9]+]] = (d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)
16+
// CHECK-DAG: #[[BASE_MAP3:map[0-9]+]] = (d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)
1617
// CHECK-DAG: #[[SUBVIEW_MAP0:map[0-9]+]] = (d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + d1 * s2 + d2 * s3 + s0)
1718

1819
// CHECK-DAG: #[[BASE_MAP1:map[0-9]+]] = (d0)[s0] -> (d0 + s0)
@@ -476,12 +477,19 @@ func @tensor_cast(%arg0: tensor<*xf32>, %arg1 : tensor<4x4xf32>, %arg2: tensor<?
476477
}
477478

478479
// CHECK-LABEL: func @memref_cast(%arg0
479-
func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref<?xf32>) {
480+
func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref<?xf32>, %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]>) {
480481
// CHECK: %0 = memref_cast %arg0 : memref<4xf32> to memref<?xf32>
481482
%0 = memref_cast %arg0 : memref<4xf32> to memref<?xf32>
482483

483484
// CHECK: %1 = memref_cast %arg1 : memref<?xf32> to memref<4xf32>
484485
%1 = memref_cast %arg1 : memref<?xf32> to memref<4xf32>
486+
487+
// CHECK: {{%.*}} = memref_cast %arg2 : memref<64x16x4xf32, #[[BASE_MAP0]]> to memref<64x16x4xf32, #[[BASE_MAP3]]>
488+
%2 = memref_cast %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]> to memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]>
489+
490+
// CHECK: {{%.*}} = memref_cast {{%.*}} : memref<64x16x4xf32, #[[BASE_MAP3]]> to memref<64x16x4xf32, #[[BASE_MAP0]]>
491+
%3 = memref_cast %2 : memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]> to memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]>
492+
485493
return
486494
}
487495

test/IR/invalid-ops.mlir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,3 +951,19 @@ func @invalid_subview(%arg0 : index, %arg1 : memref<?x8x?xf32>) {
951951
%0 = subview %arg1[%c0, %c0, %c0][%c1, %arg0, %c1][%c1, %c1, %c1] : memref<?x8x?xf32> to memref<?x8x?xf32, offset:?, strides:[?, ?, ?]>
952952
return
953953
}
954+
955+
// -----
956+
957+
func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]>) {
958+
// expected-error@+1{{operand type 'memref<12x4x16xf32, (d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2)>' and result type 'memref<12x4x16xf32, (d0, d1, d2) -> (d0 * 128 + d1 * 32 + d2 * 2)>' are cast incompatible}}
959+
%0 = memref_cast %arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]> to memref<12x4x16xf32, offset:0, strides:[128, 32, 2]>
960+
return
961+
}
962+
963+
// -----
964+
965+
func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]>) {
966+
// expected-error@+1{{operand type 'memref<12x4x16xf32, (d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2)>' and result type 'memref<12x4x16xf32, (d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2 + 16)>' are cast incompatible}}
967+
%0 = memref_cast %arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]> to memref<12x4x16xf32, offset:16, strides:[64, 16, 1]>
968+
return
969+
}

0 commit comments

Comments
 (0)