[Mlir-commits] [mlir] [mlir][tosa] Add verifier check for Slice Op (PR #135853)
Tai Ly
llvmlistbot at llvm.org
Tue Apr 15 13:48:51 PDT 2025
https://github.com/Tai78641 created https://github.com/llvm/llvm-project/pull/135853
Add verifier check for Slice Op to make sure input1 and output have same ranks.
Added test in verifier.mlir
Also moved existing slice verifier tests in invalid.mlir to verfier.mlir
>From 97f12adb6ac33be8e06f9432b3986fd9d8e71ec3 Mon Sep 17 00:00:00 2001
From: Tai Ly <tai.ly at arm.com>
Date: Tue, 8 Apr 2025 15:36:34 +0000
Subject: [PATCH] [mlir][tosa] Add verifier check for Slice Op
Add verifier check for Slice Op to make sure input1 and output have
same ranks.
Added test in verifier.mlir
Also moved existing slice verifier tests in invalid.mlir to verfier.mlir
Signed-off-by: Tai Ly <tai.ly at arm.com>
Change-Id: I83b8a198585a56c15a28ba26a62cf9138955c7eb
---
mlir/lib/Dialect/Tosa/IR/TosaOps.cpp | 29 ++++++++++++-------
mlir/test/Dialect/Tosa/invalid.mlir | 32 ---------------------
mlir/test/Dialect/Tosa/verifier.mlir | 43 ++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 43 deletions(-)
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index bce5b226635f3..4c9dd5d83c07c 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -1447,19 +1447,26 @@ LogicalResult tosa::SliceOp::verify() {
/* outType = */ getOutput().getType())
.failed())
return failure();
- auto inputType = llvm::dyn_cast<RankedTensorType>(getInput1().getType());
- if (!inputType)
- return success();
- auto startShapeRank =
- llvm::cast<tosa::shapeType>(getStart().getType()).getRank();
- if (inputType.getRank() != startShapeRank)
- return emitOpError("length of start is not equal to rank of input shape");
+ const ShapeAdaptor inputShape(getInput1().getType());
+ if (inputShape.hasRank()) {
+ const auto inputRank = inputShape.getRank();
+ const ShapeAdaptor outputShape(getOutput().getType());
+ if (outputShape.hasRank() && inputRank != outputShape.getRank())
+ return emitOpError(
+ "expect input1 and output to have the same ranks, got ")
+ << inputRank << " and " << outputShape.getRank();
+
+ const auto startShapeRank =
+ llvm::cast<tosa::shapeType>(getStart().getType()).getRank();
+ if (inputRank != startShapeRank)
+ return emitOpError("length of start is not equal to rank of input shape");
- auto sizeShapeRank =
- llvm::cast<tosa::shapeType>(getSize().getType()).getRank();
- if (inputType.getRank() != sizeShapeRank)
- return emitOpError("length of size is not equal to rank of input shape");
+ const auto sizeShapeRank =
+ llvm::cast<tosa::shapeType>(getSize().getType()).getRank();
+ if (inputRank != sizeShapeRank)
+ return emitOpError("length of size is not equal to rank of input shape");
+ }
return success();
}
diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir
index c0b251885de5c..fc98aa95ed5b3 100644
--- a/mlir/test/Dialect/Tosa/invalid.mlir
+++ b/mlir/test/Dialect/Tosa/invalid.mlir
@@ -660,28 +660,6 @@ func.func @test_variable_write_shape(%arg0: tensor<1x4x8xi8>) -> () {
// -----
-func.func @test_slice_invalid_start() {
- %0 = tensor.empty() : tensor<4x31x31xf32>
- %start = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2>
- %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>
- // expected-error at +1 {{'tosa.slice' op length of start is not equal to rank of input shape}}
- %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<2>, !tosa.shape<3>) -> tensor<*xf32>
- return
-}
-
-// -----
-
-func.func @test_slice_invalid_size() {
- %0 = tensor.empty() : tensor<4x31x31xf32>
- %start = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>
- %size = tosa.const_shape {values = dense<[1]> : tensor<1xindex>} : () -> !tosa.shape<1>
- // expected-error at +1 {{'tosa.slice' op length of size is not equal to rank of input shape}}
- %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<1>) -> tensor<*xf32>
- return
-}
-
-// -----
-
func.func @test_tile_invalid_multiples() {
%0 = tensor.empty() : tensor<4x31x31xf32>
%cst = tosa.const_shape { values = dense<1> : tensor<1xindex> } : () -> !tosa.shape<1>
@@ -1938,16 +1916,6 @@ func.func @test_scalar_reverse(%arg0: tensor<f32>) -> tensor<f32> {
// -----
-func.func @test_scalar_slice(%arg0: tensor<f32>) -> tensor<f32> {
- %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
- %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
- // expected-error at +1 {{'tosa.slice' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor<f32>'}}
- %2 = tosa.slice %arg0, %0, %1 : (tensor<f32>, !tosa.shape<0>, !tosa.shape<0>) -> tensor<f32>
- return %2 : tensor<f32>
-}
-
-// -----
-
func.func @test_scalar_tile(%arg0: tensor<f32>) -> tensor<*xf32> {
%cst = tosa.const_shape { values = dense<[]> : tensor<0xindex> } : () -> !tosa.shape<0>
// expected-error at +1 {{'tosa.tile' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor<f32>'}}
diff --git a/mlir/test/Dialect/Tosa/verifier.mlir b/mlir/test/Dialect/Tosa/verifier.mlir
index c49cbecd25c78..efdd26a9346fb 100644
--- a/mlir/test/Dialect/Tosa/verifier.mlir
+++ b/mlir/test/Dialect/Tosa/verifier.mlir
@@ -124,3 +124,46 @@ func.func @test_scalar_output_transpose(%arg0: tensor<*xf32>) -> tensor<f32> {
%1 = tosa.transpose %arg0 {perms = array<i32: 2, 0, 1>} : (tensor<*xf32>) -> tensor<f32>
return %1 : tensor<f32>
}
+
+// -----
+
+func.func @test_slice_invalid_output_rank() {
+ %0 = tensor.empty() : tensor<4x31x31xf32>
+ %start = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2>
+ %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>
+ // expected-error at +1 {{'tosa.slice' op expect input1 and output to have the same ranks, got 3 and 4}}
+ %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<2>, !tosa.shape<3>) -> tensor<?x?x?x?xf32>
+ return
+}
+
+// -----
+
+func.func @test_slice_invalid_start() {
+ %0 = tensor.empty() : tensor<4x31x31xf32>
+ %start = tosa.const_shape {values = dense<[1, 1]> : tensor<2xindex>} : () -> !tosa.shape<2>
+ %size = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>
+ // expected-error at +1 {{'tosa.slice' op length of start is not equal to rank of input shape}}
+ %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<2>, !tosa.shape<3>) -> tensor<*xf32>
+ return
+}
+
+// -----
+
+func.func @test_slice_invalid_size() {
+ %0 = tensor.empty() : tensor<4x31x31xf32>
+ %start = tosa.const_shape {values = dense<[1, 1, 1]> : tensor<3xindex>} : () -> !tosa.shape<3>
+ %size = tosa.const_shape {values = dense<[1]> : tensor<1xindex>} : () -> !tosa.shape<1>
+ // expected-error at +1 {{'tosa.slice' op length of size is not equal to rank of input shape}}
+ %3 = tosa.slice %0, %start, %size : (tensor<4x31x31xf32>, !tosa.shape<3>, !tosa.shape<1>) -> tensor<*xf32>
+ return
+}
+
+// -----
+
+func.func @test_scalar_slice(%arg0: tensor<f32>) -> tensor<f32> {
+ %0 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
+ %1 = tosa.const_shape {values = dense<[]> : tensor<0xindex>} : () -> !tosa.shape<0>
+ // expected-error at +1 {{'tosa.slice' op operand #0 must be tosa-conformant tensor of at least rank 1, but got 'tensor<f32>'}}
+ %2 = tosa.slice %arg0, %0, %1 : (tensor<f32>, !tosa.shape<0>, !tosa.shape<0>) -> tensor<f32>
+ return %2 : tensor<f32>
+}
More information about the Mlir-commits
mailing list