Skip to content

Commit 2bac720

Browse files
authored
[mlir][vector] Take dim sizes into account in DropInnerMostUnitDims. (llvm#71752)
The `stride == 1` does not imply that we can drop it. Because it could load more than 1 elements. We should also take source sizes and vector sizes into account. Otherwise it generates invalid IRs. E.g., ```mlir func.func @foo(%arg0: memref<1x1xf32>) -> vector<4x8xf32> { %c0 = arith.constant 0 : index %cst = arith.constant 0.000000e+00 : f32 %0 = vector.transfer_read %arg0[%c0, %c0], %cst : memref<1x1xf32>, vector<4x8xf32> return %0 : vector<4x8xf32> } ``` Fixes iree-org/iree#15493
1 parent b88308b commit 2bac720

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,10 +1184,19 @@ class DropInnerMostUnitDims : public OpRewritePattern<vector::TransferReadOp> {
11841184
if (failed(getStridesAndOffset(srcType, srcStrides, srcOffset)))
11851185
return failure();
11861186

1187+
// According to vector.transfer_read semantics, the result can be a slice.
1188+
// It pads the indices with `1` starting from beginning. Thus, we have to
1189+
// offset the check index with `rankDiff` in `srcStrides` and source dim
1190+
// sizes.
11871191
size_t dimsToDrop = 0;
1188-
for (size_t i = 1; i < srcStrides.size(); ++i) {
1189-
int dim = srcType.getRank() - i - 1;
1190-
if (srcStrides[dim] == 1) {
1192+
int rankDiff = srcType.getRank() - targetType.getRank();
1193+
for (int64_t i = 0, e = targetType.getRank(); i < e; ++i) {
1194+
// Check that the inner dim size is 1 for both memref/tensor type and
1195+
// vector slice. It can be folded only if they are 1 and the stride is 1.
1196+
int dim = targetType.getRank() - i - 1;
1197+
if (srcStrides[dim + rankDiff] == 1 &&
1198+
srcType.getDimSize(dim + rankDiff) == 1 &&
1199+
targetType.getDimSize(dim) == 1) {
11911200
dimsToDrop++;
11921201
} else {
11931202
break;

mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,19 @@ func.func @contiguous_inner_most_dim_bounds_2d(%A: memref<1000x1x1xf32>, %i:inde
6060
// CHECK: %[[V:.+]] = vector.transfer_read %[[SRC_1]]
6161
// CHECK-SAME: {in_bounds = [true]}
6262
// CHECK-SAME: vector<4xf32>
63+
64+
// -----
65+
66+
func.func @contiguous_inner_most_dim_out_of_bounds_2d(%arg0: memref<1x1xf32>) -> vector<4x8xf32> {
67+
%c0 = arith.constant 0 : index
68+
%cst = arith.constant 0.000000e+00 : f32
69+
%0 = vector.transfer_read %arg0[%c0, %c0], %cst : memref<1x1xf32>, vector<4x8xf32>
70+
return %0 : vector<4x8xf32>
71+
}
72+
// The inner most unit dim can not be dropped. In this context, we do not
73+
// generate rank-reduced memref.subview ops.
74+
// CHECK: func.func @contiguous_inner_most_dim_out_of_bounds_2d
75+
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]
76+
// CHECK-NOT: memref.subview
77+
// CHECK: %[[READ:.+]] = vector.transfer_read %[[SRC]]
78+
// CHECK: return %[[READ]] : vector<4x8xf32>

0 commit comments

Comments
 (0)