[Mlir-commits] [mlir] [mlir][tosa] Add verifier check for Slice Op (PR #135853)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Apr 15 13:49:30 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-tosa
Author: Tai Ly (Tai78641)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/135853.diff
3 Files Affected:
- (modified) mlir/lib/Dialect/Tosa/IR/TosaOps.cpp (+18-11)
- (modified) mlir/test/Dialect/Tosa/invalid.mlir (-32)
- (modified) mlir/test/Dialect/Tosa/verifier.mlir (+43)
``````````diff
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>
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/135853
More information about the Mlir-commits
mailing list