From 5c18ae3135d1ff4b9e554480da78bc93e35ef00a Mon Sep 17 00:00:00 2001 From: liqinweng Date: Wed, 4 Jan 2023 13:05:57 -0800 Subject: [PATCH] [MLIR][Tensor] Canonicalize expand/collapse_shape of splat to splat Collapsing / expanding a splatted value can be replaced with a single `tensor.splat` operation. Replace these cases with a simple `tensor.splat` operation. Reviewed By: rsuderman Differential Revision: https://reviews.llvm.org/D140552 --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 21 ++++++++++++++++++ mlir/test/Dialect/Tensor/canonicalize.mlir | 25 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index c87a003fab3b..cd962456ba42 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1382,6 +1382,24 @@ struct FoldReshapeWithConstant : OpRewritePattern { } }; +// Folds TensorReshapeOp(splat x : src_type) : res_type into splat x : res_type. +template +class FoldReshapeWithSplat : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(TensorReshapeOp reshapeOp, + PatternRewriter &rewriter) const override { + auto splatOp = reshapeOp.getSrc().template getDefiningOp(); + if (!splatOp) + return failure(); + + rewriter.replaceOpWithNewOp( + reshapeOp, reshapeOp.getResultType(), splatOp.getInput()); + return success(); + } +}; + /// Reshape of a FromElements can be replaced with a FromElements of the /// result type template @@ -1523,6 +1541,7 @@ void ExpandShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, results.add, ComposeExpandOfCollapseOp, FoldReshapeWithConstant, + FoldReshapeWithSplat, FoldReshapeWithFromElements, FoldDimOfExpandShape, FoldDimOfCollapseShape>(context); } @@ -1533,6 +1552,7 @@ void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, .add, ComposeCollapseOfExpandOp, FoldReshapeWithConstant, + FoldReshapeWithSplat, FoldReshapeWithFromElements, FoldCollapseOfCastOp>( context); } @@ -1540,6 +1560,7 @@ void CollapseShapeOp::getCanonicalizationPatterns(RewritePatternSet &results, OpFoldResult ExpandShapeOp::fold(ArrayRef operands) { return foldReshapeOp(*this, operands); } + OpFoldResult CollapseShapeOp::fold(ArrayRef operands) { return foldReshapeOp(*this, operands); } diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 2b11a3368167..6267c269ab0b 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -1013,9 +1013,34 @@ func.func @reshape_splat_constant_int32() -> tensor<2x4x2xi32> { // CHECK: %[[CST:.*]] = arith.constant dense<{{.*}}> : tensor<2x4x2xi32> // CHECK-NOT: tensor.expand_shape // CHECK: return %[[CST]] +// ----- +func.func @expand_shape_splat(%arg : f32) -> tensor<2x2x2xf32> { + %c0 = tensor.splat %arg : tensor<2x4xf32> + %0 = tensor.expand_shape %c0 [[0], [1, 2]] + : tensor<2x4xf32> into tensor<2x2x2xf32> + return %0 : tensor<2x2x2xf32> +} +// CHECK-LABEL: @expand_shape_splat +// CHECK-SAME: %[[ARG0:.+]]: f32 +// CHECK: %[[CST:.*]] = tensor.splat %[[ARG0:.+]] : tensor<2x2x2xf32> +// CHECK-NOT: tensor.expand_shape +// CHECK: return %[[CST]] // ----- +func.func @collapse_shape_splat(%arg : f32) -> tensor<2x4xf32> { + %c0 = tensor.splat %arg : tensor<2x2x2xf32> + %0 = tensor.collapse_shape %c0 [[0], [1, 2]] + : tensor<2x2x2xf32> into tensor<2x4xf32> + return %0 : tensor<2x4xf32> +} +// CHECK-LABEL: @collapse_shape_splat +// CHECK-SAME: %[[ARG0:.+]]: f32 +// CHECK: %[[CST:.*]] = tensor.splat %[[ARG0:.+]] : tensor<2x4xf32> +// CHECK-NOT: tensor.collapse_shape +// CHECK: return %[[CST]] + +// ----- func.func @reshape_splat_constant_int16() -> tensor<2x4x2xi16> { %c0 = arith.constant dense<42> : tensor<2x8xi16> %0 = tensor.expand_shape %c0 [[0], [1, 2]]