Skip to content

Commit 2472c45

Browse files
authored
[mlir][tensor] Enhance pack/unpack simplification for identity outer_dims_perm cases. (#77409)
They can be simplified to reshape ops if outer_dims_perm is an identity permutation. The revision adds a `isIdentityPermutation` method to IndexingUtils.
1 parent d4b4ded commit 2472c45

File tree

5 files changed

+58
-5
lines changed

5 files changed

+58
-5
lines changed

mlir/include/mlir/Dialect/Utils/IndexingUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ void applyPermutationToVector(SmallVector<T, N> &inVec,
228228
/// Helper method to apply to inverse a permutation.
229229
SmallVector<int64_t> invertPermutationVector(ArrayRef<int64_t> permutation);
230230

231+
/// Returns true if `permutation` is an identity permutation.
232+
bool isIdentityPermutation(ArrayRef<int64_t> permutation);
233+
231234
/// Method to check if an interchange vector is a permutation.
232235
bool isPermutationVector(ArrayRef<int64_t> interchange);
233236

mlir/lib/Dialect/Tensor/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_mlir_dialect_library(MLIRTensorTransforms
2727
MLIRArithUtils
2828
MLIRBufferizationDialect
2929
MLIRBufferizationTransforms
30+
MLIRDialectUtils
3031
MLIRIR
3132
MLIRLinalgDialect
3233
MLIRMemRefDialect

mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ struct SimplifyPackToExpandShape : public OpRewritePattern<PackOp> {
3939
if (packOp.getPaddingValue())
4040
return rewriter.notifyMatchFailure(packOp, "expects no padding value");
4141

42-
if (!packOp.getOuterDimsPerm().empty())
43-
return rewriter.notifyMatchFailure(packOp, "expects no outer_dims_perm");
42+
auto outerDimsPerm = packOp.getOuterDimsPerm();
43+
if (!outerDimsPerm.empty() && !isIdentityPermutation(outerDimsPerm)) {
44+
return rewriter.notifyMatchFailure(
45+
packOp,
46+
"expects outer_dims_perm is empty or an identity permutation");
47+
}
4448

4549
RankedTensorType sourceType = packOp.getSourceType();
4650
RankedTensorType destType = packOp.getDestType();
@@ -75,9 +79,11 @@ struct SimplifyUnPackToCollapseShape : public OpRewritePattern<UnPackOp> {
7579

7680
LogicalResult matchAndRewrite(UnPackOp unpackOp,
7781
PatternRewriter &rewriter) const override {
78-
if (!unpackOp.getOuterDimsPerm().empty()) {
79-
return rewriter.notifyMatchFailure(unpackOp,
80-
"expects no outer_dims_perm");
82+
auto outerDimsPerm = unpackOp.getOuterDimsPerm();
83+
if (!outerDimsPerm.empty() && !isIdentityPermutation(outerDimsPerm)) {
84+
return rewriter.notifyMatchFailure(
85+
unpackOp,
86+
"expects outer_dims_perm is empty or an identity permutation");
8187
}
8288

8389
RankedTensorType sourceType = unpackOp.getSourceType();

mlir/lib/Dialect/Utils/IndexingUtils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ mlir::invertPermutationVector(ArrayRef<int64_t> permutation) {
213213
return inversion;
214214
}
215215

216+
bool mlir::isIdentityPermutation(ArrayRef<int64_t> permutation) {
217+
for (auto i : llvm::seq<int64_t>(0, permutation.size()))
218+
if (permutation[i] != i)
219+
return false;
220+
return true;
221+
}
222+
216223
bool mlir::isPermutationVector(ArrayRef<int64_t> interchange) {
217224
assert(llvm::all_of(interchange, [](int64_t s) { return s >= 0; }) &&
218225
"permutation must be non-negative");

mlir/test/Dialect/Tensor/simplify-pack-unpack.mlir

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,30 @@ func.func @single_last_inner_dim_packing(%arg0: tensor<5x256xf32>) -> tensor<5x8
3737

3838
// -----
3939

40+
// CHECK-LABEL: func.func @pack_1d_with_outer_dims_perm(
41+
// CHECK-SAME: %[[ARG0:.+]]: tensor<64xf32>)
42+
// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] : tensor<64xf32> into tensor<2x32xf32>
43+
// CHECK: return %[[EXPANDED]] : tensor<2x32xf32>
44+
func.func @pack_1d_with_outer_dims_perm(%arg0: tensor<64xf32>) -> tensor<2x32xf32> {
45+
%empty = tensor.empty() : tensor<2x32xf32>
46+
%pack = tensor.pack %arg0 outer_dims_perm = [0] inner_dims_pos = [0] inner_tiles = [32] into %empty : tensor<64xf32> -> tensor<2x32xf32>
47+
return %pack : tensor<2x32xf32>
48+
}
49+
50+
// -----
51+
52+
// CHECK-LABEL: func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm(
53+
// CHECK-SAME: %[[ARG0:.+]]: tensor<5x256xf32>)
54+
// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x256xf32> into tensor<5x8x32xf32>
55+
// CHECK: return %[[EXPANDED]] : tensor<5x8x32xf32>
56+
func.func @single_last_inner_dim_packing_with_identity_outer_dims_perm(%arg0: tensor<5x256xf32>) -> tensor<5x8x32xf32> {
57+
%empty = tensor.empty() : tensor<5x8x32xf32>
58+
%0 = tensor.pack %arg0 outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [32] into %empty : tensor<5x256xf32> -> tensor<5x8x32xf32>
59+
return %0 : tensor<5x8x32xf32>
60+
}
61+
62+
// -----
63+
4064
// CHECK-LABEL: func.func @packing_with_outer_dims_perm(
4165
// CHECK-NOT: tensor.expand_shape
4266
// CHECK: tensor.pack
@@ -109,6 +133,18 @@ func.func @single_last_inner_dim_unpacking(%arg0: tensor<5x8x32xf32>) -> tensor<
109133

110134
// -----
111135

136+
// CHECK-LABEL: func.func @single_last_inner_dim_unpacking_with_identity_outer_dims_perm(
137+
// CHECK-SAME: %[[ARG0:.+]]: tensor<5x8x32xf32>)
138+
// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<5x8x32xf32> into tensor<5x256xf32>
139+
// CHECK: return %[[COLLAPSED]] : tensor<5x256xf32>
140+
func.func @single_last_inner_dim_unpacking_with_identity_outer_dims_perm(%arg0: tensor<5x8x32xf32>) -> tensor<5x256xf32> {
141+
%empty = tensor.empty() : tensor<5x256xf32>
142+
%0 = tensor.unpack %arg0 outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [32] into %empty : tensor<5x8x32xf32> -> tensor<5x256xf32>
143+
return %0 : tensor<5x256xf32>
144+
}
145+
146+
// -----
147+
112148
// CHECK-LABEL: func.func @unpacking_with_outer_dims_perm(
113149
// CHECK-NOT: tensor.collpase_shape
114150
// CHECK: tensor.unpack

0 commit comments

Comments
 (0)