[Mlir-commits] [mlir] 98845fc - [mlir][tosa] Disallow shape type in function argument/return types (#175754)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Apr 10 09:22:43 PDT 2026
Author: Luke Hutton
Date: 2026-04-10T17:22:38+01:00
New Revision: 98845fccd93865417dc732251fdc09e3eb15edb8
URL: https://github.com/llvm/llvm-project/commit/98845fccd93865417dc732251fdc09e3eb15edb8
DIFF: https://github.com/llvm/llvm-project/commit/98845fccd93865417dc732251fdc09e3eb15edb8.diff
LOG: [mlir][tosa] Disallow shape type in function argument/return types (#175754)
This commit adds an additional check to the TOSA validation pass to
disallow use of shape types in function arguments and return types. The
specification requires these types be tensor types.
Added:
Modified:
mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
mlir/test/Dialect/Tosa/dynamic_extension.mlir
mlir/test/Dialect/Tosa/invalid.mlir
mlir/test/Dialect/Tosa/invalid_extension.mlir
mlir/test/Dialect/Tosa/level_check.mlir
mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
index 8c00603d7abb4..3e2cda9d37666 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
@@ -176,6 +176,7 @@ struct TosaValidation : public tosa::impl::TosaValidationBase<TosaValidation> {
return success();
}
+ LogicalResult applyFunctionSignatureCheck(func::FuncOp op);
LogicalResult applyLevelCheck(Operation *op);
LogicalResult applyAttributeCheck(Operation *op);
@@ -1428,6 +1429,19 @@ LogicalResult TosaValidation::applyErrorIfCheck(Operation *op) {
return success();
}
+LogicalResult TosaValidation::applyFunctionSignatureCheck(func::FuncOp op) {
+ const auto isShapeType = [](Type type) { return isa<tosa::shapeType>(type); };
+ if (llvm::any_of(op.getArgumentTypes(), isShapeType))
+ return op.emitOpError()
+ << "Function argument types must be a tensor type to be TOSA "
+ "compliant, got !tosa.shape type";
+ if (llvm::any_of(op.getResultTypes(), isShapeType))
+ return op.emitOpError()
+ << "Function return types must be a tensor type to be TOSA "
+ "compliant, got !tosa.shape type";
+ return success();
+}
+
bool TosaValidation::isValidElementType(Type type, const bool allowUnsigned) {
if (isa<FloatType>(type)) {
return isa<Float32Type, Float16Type, BFloat16Type, Float8E4M3FNType,
@@ -1473,6 +1487,12 @@ void TosaValidation::runOnOperation() {
return signalPassFailure();
targetEnv = *maybeTargetEnv;
+ const auto functions = modOp.getOps<func::FuncOp>();
+ if (llvm::any_of(functions, [&](func::FuncOp func) {
+ return failed(applyFunctionSignatureCheck(func));
+ }))
+ return signalPassFailure();
+
modOp.walk([&](Operation *op) {
if (op->getDialect() != tosaDialect)
return;
diff --git a/mlir/test/Dialect/Tosa/dynamic_extension.mlir b/mlir/test/Dialect/Tosa/dynamic_extension.mlir
index 4d4c000946bf5..5f5ab795459f7 100644
--- a/mlir/test/Dialect/Tosa/dynamic_extension.mlir
+++ b/mlir/test/Dialect/Tosa/dynamic_extension.mlir
@@ -99,8 +99,8 @@ func.func @test_avg_pool2d_adaptive_non_const_zps(%arg0: tensor<1x32x32x8xf32>,
// -----
-func.func @test_slice_shape_non_const_start_size(%arg0: tensor<1xi32>, %arg1: tensor<1xi32>) -> !tosa.shape<3> {
+func.func @test_slice_shape_non_const_start_size(%arg0: tensor<1xi32>, %arg1: tensor<1xi32>) {
%0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6>
%3 = tosa.slice_shape %0, %arg0, %arg1 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3>
- return %3 : !tosa.shape<3>
+ return
}
diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir
index 79e5b4688bda1..4458ffb5f3fe0 100644
--- a/mlir/test/Dialect/Tosa/invalid.mlir
+++ b/mlir/test/Dialect/Tosa/invalid.mlir
@@ -1088,26 +1088,26 @@ func.func @test_shape_type(%arg0: !tosa.shape<-1>) -> !tosa.shape<-1> {
// -----
-func.func @test_const_shape() -> !tosa.shape<4> {
+func.func @test_const_shape() {
// expected-error at +1 {{'tosa.const_shape' op attribute 'values' failed to satisfy constraint: index elements attribute}}
%cst = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xi32>} : () -> !tosa.shape<4>
- return %cst : !tosa.shape<4>
+ return
}
// -----
-func.func @test_const_shape_values() -> !tosa.shape<5> {
+func.func @test_const_shape_values() {
// expected-error at +1 {{'tosa.const_shape' op expect number of elements in attribute values (4) to be equal to the rank (5) for the result shape type}}
%cst = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<5>
- return %cst : !tosa.shape<5>
+ return
}
// -----
-func.func @test_const_shape_values() -> !tosa.shape<4> {
+func.func @test_const_shape_values() {
// expected-error at +1 {{'tosa.const_shape' op expect elements in attribute values with rank 1}}
%cst = tosa.const_shape {values = dense<[[1, 2], [3, 4]]> : tensor<2x2xindex>} : () -> !tosa.shape<4>
- return %cst : !tosa.shape<4>
+ return
}
// -----
@@ -2263,22 +2263,22 @@ func.func @test_rfft2d(%arg0: tensor<13x8x16xbf16>) -> (tensor<13x8x9xbf16>, ten
// -----
-func.func @test_slice_shape_non_const_start(%arg0: tensor<1xi32>) -> !tosa.shape<3> {
+func.func @test_slice_shape_non_const_start(%arg0: tensor<1xi32>) {
%0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6>
%2 = "tosa.const"() {values = dense<3> : tensor<1xi32>} : () -> tensor<1xi32>
// expected-error at +1 {{'tosa.slice_shape' op expected compile time resolvable constant, but got variable value for operand #1}}
%3 = tosa.slice_shape %0, %arg0, %2 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3>
- return %3 : !tosa.shape<3>
+ return
}
// -----
-func.func @test_slice_shape_non_const_size(%arg0: tensor<1xi32>) -> !tosa.shape<3> {
+func.func @test_slice_shape_non_const_size(%arg0: tensor<1xi32>) {
%0 = tosa.const_shape {values = dense<[4, 5, 6, 7, 8, 9]> : tensor<6xindex>} : () -> !tosa.shape<6>
%1 = "tosa.const"() {values = dense<3> : tensor<1xi32>} : () -> tensor<1xi32>
// expected-error at +1 {{'tosa.slice_shape' op expected compile time resolvable constant, but got variable value for operand #2}}
%3 = tosa.slice_shape %0, %1, %arg0 : (!tosa.shape<6>, tensor<1xi32>, tensor<1xi32>) -> !tosa.shape<3>
- return %3 : !tosa.shape<3>
+ return
}
// -----
@@ -2291,3 +2291,18 @@ func.func @test_conv2d_block_scaled(%arg0: tensor<*xf4E2M1FN>, %arg1: tensor<*xf
%3 = tosa.conv2d_block_scaled %arg0, %arg1, %arg2, %arg3, %arg4, %0, %1, %2 {block_size = BLOCK_SIZE_32} : (tensor<*xf4E2M1FN>, tensor<*xf8E8M0FNU>, tensor<*xf4E2M1FN>, tensor<*xf8E8M0FNU>, tensor<*xf16>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<*xf16>
return %3 : tensor<*xf16>
}
+
+// -----
+
+// expected-error at +1 {{func.func' op Function argument types must be a tensor type to be TOSA compliant, got !tosa.shape type}}
+func.func @test_shape_func_input(%arg0: !tosa.shape<1>) {
+ return
+}
+
+// -----
+
+// expected-error at +1 {{'func.func' op Function return types must be a tensor type to be TOSA compliant, got !tosa.shape type}}
+func.func @test_shape_func_output() -> !tosa.shape<4> {
+ %cst = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
+ return %cst : !tosa.shape<4>
+}
diff --git a/mlir/test/Dialect/Tosa/invalid_extension.mlir b/mlir/test/Dialect/Tosa/invalid_extension.mlir
index 1519b6845dd7e..8a9b014864c74 100644
--- a/mlir/test/Dialect/Tosa/invalid_extension.mlir
+++ b/mlir/test/Dialect/Tosa/invalid_extension.mlir
@@ -560,30 +560,30 @@ func.func @test_avg_pool2d_adaptive_missing_bf16_extension(%arg0: tensor<1x7x7x9
// -----
-func.func @test_mul_shape() -> !tosa.shape<4> {
+func.func @test_mul_shape() {
%a = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.const_shape {values = dense<[5, 6, 7, 8]> : tensor<4xindex>} : () -> !tosa.shape<4>
// expected-error at +1 {{'tosa.mul_shape' op illegal: requires [shape] but not enabled in target}}
%c = tosa.mul_shape %a, %b : (!tosa.shape<4>, !tosa.shape<4>) -> !tosa.shape<4>
- return %c : !tosa.shape<4>
+ return
}
// -----
-func.func @test_max_shape() -> !tosa.shape<4> {
+func.func @test_max_shape() {
%a = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.const_shape {values = dense<[5, 6, 7, 8]> : tensor<4xindex>} : () -> !tosa.shape<4>
// expected-error at +1 {{'tosa.max_shape' op illegal: requires [shape] but not enabled in target}}
%c = tosa.max_shape %a, %b : (!tosa.shape<4>, !tosa.shape<4>) -> !tosa.shape<4>
- return %c : !tosa.shape<4>
+ return
}
// -----
-func.func @test_min_shape() -> !tosa.shape<4> {
+func.func @test_min_shape() {
%a = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.const_shape {values = dense<[5, 6, 7, 8]> : tensor<4xindex>} : () -> !tosa.shape<4>
// expected-error at +1 {{'tosa.min_shape' op illegal: requires [shape] but not enabled in target}}
%c = tosa.min_shape %a, %b : (!tosa.shape<4>, !tosa.shape<4>) -> !tosa.shape<4>
- return %c : !tosa.shape<4>
+ return
}
diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir
index ca4d2dca0e7c9..5ffeafcb0ab2f 100644
--- a/mlir/test/Dialect/Tosa/level_check.mlir
+++ b/mlir/test/Dialect/Tosa/level_check.mlir
@@ -1310,9 +1310,9 @@ func.func @test_while_loop_tensor_size_invalid(%arg0: tensor<536870912xi32>, %ar
// -----
-func.func @test_const_shape() -> !tosa.shape<4> {
+func.func @test_const_shape() {
%cst = tosa.const_shape {values = dense<[1, 1, 536870912, 1]> : tensor<4xindex>} : () -> !tosa.shape<4>
- return %cst : !tosa.shape<4>
+ return
}
// -----
@@ -1841,67 +1841,67 @@ func.func @test_cast_to_block_scaled_invalid_rank(%arg0: tensor<1x2x3x4x5x6x7x32
// -----
-func.func @test_add_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_add_shape_invalid_rank() {
%a = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
%b = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.add_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%c = tosa.add_shape %a, %b : (!tosa.shape<17>, !tosa.shape<17>) -> !tosa.shape<17>
- return %c : !tosa.shape<17>
+ return
}
// -----
-func.func @test_div_floor_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_div_floor_shape_invalid_rank() {
%a = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
%b = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.div_floor_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%c = tosa.div_floor_shape %a, %b : (!tosa.shape<17>, !tosa.shape<17>) -> !tosa.shape<17>
- return %c : !tosa.shape<17>
+ return
}
// -----
-func.func @test_dim(%arg0: tensor<1x2x3x4x5x6x7x8xi32>) -> !tosa.shape<1> {
+func.func @test_dim(%arg0: tensor<1x2x3x4x5x6x7x8xi32>) {
// expected-error at +1 {{'tosa.dim' op failed level check: operand rank(shape) <= MAX_RANK}}
%0 = tosa.dim %arg0 {axis = 2 : i32} : (tensor<1x2x3x4x5x6x7x8xi32>) -> !tosa.shape<1>
- return %0 : !tosa.shape<1>
+ return
}
// -----
-func.func @test_exp2_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_exp2_shape_invalid_rank() {
%0 = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.exp2_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%1 = tosa.exp2_shape %0 : (!tosa.shape<17>) -> !tosa.shape<17>
- return %1 : !tosa.shape<17>
+ return
}
// -----
-func.func @test_log2_floor_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_log2_floor_shape_invalid_rank() {
%0 = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.log2_floor_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%1 = tosa.log2_floor_shape %0 : (!tosa.shape<17>) -> !tosa.shape<17>
- return %1 : !tosa.shape<17>
+ return
}
// -----
-func.func @test_log2_ceil_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_log2_ceil_shape_invalid_rank() {
%0 = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.log2_ceil_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%1 = tosa.log2_ceil_shape %0 : (!tosa.shape<17>) -> !tosa.shape<17>
- return %1 : !tosa.shape<17>
+ return
}
// -----
-func.func @test_mod_shape_invalid_rank() -> !tosa.shape<17> {
+func.func @test_mod_shape_invalid_rank() {
%a = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
%b = tosa.const_shape {values = dense<0> : tensor<17xindex>} : () -> !tosa.shape<17>
// expected-error at +1 {{'tosa.mod_shape' op failed shape type level check: '!tosa.shape<17>' exceeds MAX_SHAPE_LEN}}
%c = tosa.mod_shape %a, %b : (!tosa.shape<17>, !tosa.shape<17>) -> !tosa.shape<17>
- return %c : !tosa.shape<17>
+ return
}
// -----
diff --git a/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir b/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
index 0cd01a3949c12..49ac4904002b3 100644
--- a/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
@@ -352,19 +352,19 @@ func.func @test_dynamic_dims(%arg0: tensor<?x8x16xi8>) -> tensor<?x16xi32> {
// -----
// CHECK-LABEL: test_add_shape
-func.func @test_add_shape() -> !tosa.shape<4> {
+func.func @test_add_shape() {
%a = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.const_shape {values = dense<[5, 6, 7, 8]> : tensor<4xindex>} : () -> !tosa.shape<4>
%c = tosa.add_shape %a, %b : (!tosa.shape<4>, !tosa.shape<4>) -> !tosa.shape<4>
- return %c : !tosa.shape<4>
+ return
}
// -----
// CHECK-LABEL: test_dim
-func.func @test_dim(%arg0: tensor<1x2x3x4xi32>) -> !tosa.shape<1> {
+func.func @test_dim(%arg0: tensor<1x2x3x4xi32>) {
%0 = tosa.dim %arg0 {axis = 2 : i32} : (tensor<1x2x3x4xi32>) -> !tosa.shape<1>
- return %0 : !tosa.shape<1>
+ return
}
// -----
@@ -377,28 +377,28 @@ func.func @test_dim_bf16(%0: tensor<6x4x6x9xbf16>) {
// -----
// CHECK-LABEL: test_exp2_shape
-func.func @test_exp2_shape() -> !tosa.shape<4> {
+func.func @test_exp2_shape() {
%a = tosa.const_shape {values = dense<[5, 7, 10, 1]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.exp2_shape %a : (!tosa.shape<4>) -> !tosa.shape<4>
- return %b : !tosa.shape<4>
+ return
}
// -----
// CHECK-LABEL: test_log2_ceil_shape
-func.func @test_log2_ceil_shape() -> !tosa.shape<4> {
+func.func @test_log2_ceil_shape() {
%a = tosa.const_shape {values = dense<[5, 7, 10, 1]> : tensor<4xindex>} : () -> !tosa.shape<4>
%b = tosa.log2_ceil_shape %a : (!tosa.shape<4>) -> !tosa.shape<4>
- return %b : !tosa.shape<4>
+ return
}
// -----
// CHECK-LABEL: test_mod_shape
-func.func @test_mod_shape() -> !tosa.shape<3> {
+func.func @test_mod_shape() {
%a = tosa.const_shape {values = dense<[10, 11, 12]> : tensor<3xindex>} : () -> !tosa.shape<3>
%b = tosa.const_shape {values = dense<[3, 5, 2]> : tensor<3xindex>} : () -> !tosa.shape<3>
%c = tosa.mod_shape %a, %b : (!tosa.shape<3>, !tosa.shape<3>) -> !tosa.shape<3>
- return %c : !tosa.shape<3>
+ return
}
// -----
More information about the Mlir-commits
mailing list