[Mlir-commits] [mlir] b76d8f7 - [mlir][tosa] Verify zero-dim tensors in the input
Kai Sasaki
llvmlistbot at llvm.org
Mon Jul 10 17:22:08 PDT 2023
Author: Kai Sasaki
Date: 2023-07-11T08:44:23+09:00
New Revision: b76d8f7d976365a2668694deceff48133e78f529
URL: https://github.com/llvm/llvm-project/commit/b76d8f7d976365a2668694deceff48133e78f529
DIFF: https://github.com/llvm/llvm-project/commit/b76d8f7d976365a2668694deceff48133e78f529.diff
LOG: [mlir][tosa] Verify zero-dim tensors in the input
As TOSA does not support the tensor with zero dimensions, we can check the zero value for the static shape input.
Ideally, we should be able to check the tensor shape more broadly, such as using `CPred` in the TOSA type definition. But based on [[ https://discourse.llvm.org/t/where-can-we-put-the-shared-verification-among-multiple-dialect-ops/71806 | the discussion here
]] It makes input type verification complicated and hard to maintain and still only applies to the case the input is statically shaped. Therefore, in this change, we have put the zero dimension check in the verification of each op, which would be flexible and maintainable.
See: https://github.com/llvm/llvm-project/issues/63212
Reviewed By: eric-k256
Differential Revision: https://reviews.llvm.org/D154569
Added:
Modified:
mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
mlir/test/Dialect/Tosa/invalid.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index 69bce5209b8710..563af3ed08c120 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -100,6 +100,19 @@ Operation *TosaDialect::materializeConstant(OpBuilder &builder, Attribute value,
// TOSA Operator Verifiers.
//===----------------------------------------------------------------------===//
+static bool hasZeroDimension(ShapedType shapedType) {
+ auto rank = shapedType.getRank();
+
+ for (int i = 0; i < rank; i++) {
+ if (shapedType.isDynamicDim(i))
+ continue;
+ if (shapedType.getDimSize(i) == 0)
+ return true;
+ }
+
+ return false;
+}
+
template <typename T> static LogicalResult verifyConvOp(T op) {
// All TOSA conv ops have an input() and weight().
auto inputType = llvm::dyn_cast<RankedTensorType>(op.getInput().getType());
@@ -115,6 +128,10 @@ template <typename T> static LogicalResult verifyConvOp(T op) {
return failure();
}
+ if (hasZeroDimension(inputType))
+ return op.emitOpError() << "tensor has a dimension with size zero. Each "
+ "dimension of a tensor must have size >= 1";
+
auto inputEType = inputType.getElementType();
auto weightEType = weightType.getElementType();
@@ -142,7 +159,12 @@ template <typename T> static LogicalResult verifyConvOp(T op) {
}
LogicalResult tosa::AvgPool2dOp::verify() {
- auto inputETy = llvm::cast<ShapedType>(getInput().getType()).getElementType();
+ auto inputType = llvm::cast<ShapedType>(getInput().getType());
+ if (hasZeroDimension(inputType))
+ return emitOpError() << "tensor has a dimension with size zero. Each "
+ "dimension of a tensor must have size >= 1";
+
+ auto inputETy = inputType.getElementType();
auto resultETy = llvm::cast<ShapedType>(getType()).getElementType();
if (auto quantType =
@@ -758,6 +780,10 @@ mlir::LogicalResult tosa::ReshapeOp::verify() {
ShapedType inputType = llvm::cast<ShapedType>(getInput1().getType());
ShapedType outputType = llvm::cast<ShapedType>(getType());
+ if (hasZeroDimension(inputType) || hasZeroDimension(outputType))
+ return emitOpError() << "tensor has a dimension with size zero. Each "
+ "dimension of a tensor must have size >= 1";
+
if (inputType.hasStaticShape() && outputType.hasStaticShape()) {
int64_t inputElementsNum = inputType.getNumElements();
int64_t outputElementsNum = outputType.getNumElements();
diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir
index 5bdcc9c1e326ab..b99b15c3301bb8 100644
--- a/mlir/test/Dialect/Tosa/invalid.mlir
+++ b/mlir/test/Dialect/Tosa/invalid.mlir
@@ -150,3 +150,56 @@ func.func @test_const_attribute_type_mismatch() -> tensor<100x100xf32> {
%0 = "tosa.const"() {value = dense<0.000000e+00> : tensor<1x1xf32>} : () -> tensor<100x100xf32>
return %0 : tensor<100x100xf32>
}
+
+// -----
+
+func.func @test_reshape_static_zero_dim_input(%arg0 : tensor<13x0x3xf32>) -> () {
+ // expected-error at +1 {{'tosa.reshape' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 13, 21, 3>} : (tensor<13x0x3xf32>) -> tensor<13x0x3xf32>
+ return
+}
+
+// -----
+
+func.func @test_reshape_zero_dim_input(%arg0 : tensor<?x0x3xf32>) -> () {
+ // expected-error at +1 {{'tosa.reshape' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 13, 21, 3>} : (tensor<?x0x3xf32>) -> tensor<13x0x3xf32>
+ return
+}
+
+// -----
+
+func.func @test_conv2d_static_zero_dim_input(%arg0: tensor<1x29x0x4xf32>, %arg1: tensor<16x3x3x4xf32>, %arg2: tensor<16xf32>) -> tensor<1x27x27x16xf32> {
+ // expected-error at +1 {{'tosa.conv2d' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = array<i64: 1, 1>, pad = array<i64: 0, 0, 0, 0>, stride = array<i64: 1, 1>}
+ : (tensor<1x29x0x4xf32>, tensor<16x3x3x4xf32>, tensor<16xf32>) -> tensor<1x27x27x16xf32>
+ return %0 : tensor<1x27x27x16xf32>
+}
+
+// -----
+
+func.func @test_conv2d_zero_dim_input(%arg0: tensor<1x?x0x4xf32>, %arg1: tensor<16x3x3x4xf32>, %arg2: tensor<16xf32>) -> tensor<1x27x27x16xf32> {
+ // expected-error at +1 {{'tosa.conv2d' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = array<i64: 1, 1>, pad = array<i64: 0, 0, 0, 0>, stride = array<i64: 1, 1>}
+ : (tensor<1x?x0x4xf32>, tensor<16x3x3x4xf32>, tensor<16xf32>) -> tensor<1x27x27x16xf32>
+ return %0 : tensor<1x27x27x16xf32>
+}
+
+
+// -----
+
+func.func @test_avg_pool2d_static_zero_dim_input(%arg0: tensor<1x0x7x9xf32>) -> tensor<1x7x7x9xf32> {
+ // expected-error at +1 {{'tosa.avg_pool2d' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.avg_pool2d"(%arg0) {acc_type = f32, kernel = array<i64: 2, 2>, pad = array<i64: 0, 1, 0, 1>, stride = array<i64: 1, 1>}
+ : (tensor<1x0x7x9xf32>) -> tensor<1x7x7x9xf32>
+ return %0 : tensor<1x7x7x9xf32>
+}
+
+// -----
+
+func.func @test_avg_pool2d_zero_dim_input(%arg0: tensor<1x0x?x9xf32>) -> tensor<1x7x7x9xf32> {
+ // expected-error at +1 {{'tosa.avg_pool2d' op tensor has a dimension with size zero. Each dimension of a tensor must have size >= 1}}
+ %0 = "tosa.avg_pool2d"(%arg0) {acc_type = f32, kernel = array<i64: 2, 2>, pad = array<i64: 0, 1, 0, 1>, stride = array<i64: 1, 1>}
+ : (tensor<1x0x?x9xf32>) -> tensor<1x7x7x9xf32>
+ return %0 : tensor<1x7x7x9xf32>
+}
More information about the Mlir-commits
mailing list