[Mlir-commits] [mlir] [mlir][tosa] Apply error_if checks in tosa validation without strict mode (PR #235741)
Luke Hutton
llvmlistbot at llvm.org
Fri Oct 30 05:04:35 PDT 2026
https://github.com/lhutton1 updated https://github.com/llvm/llvm-project/pull/235741
>From 0550383bcab4e1f2b8cb5cd066de46fb572e921d Mon Sep 17 00:00:00 2001
From: Luke Hutton <luke.hutton at arm.com>
Date: Fri, 23 Oct 2026 17:05:32 +0100
Subject: [PATCH] [mlir][tosa] Apply error_if checks in tosa validation without
strict mode
Enable most error_if checks by default rather than requiring
`strict-op-spec-alignment`. As a consequence, enable error_if checks
in the tosa-to-linalg lowering pipeline.
For resize in particular, behaviour such as broadcasting the input
height and width is now disallowed by default. However, some checks
are omitted as they can be too strict for some implementations, such
as scaling limits.
Also note that the current implementation requires
cond_if and while_loop operations be isolated from above. If this
restriction is too strict, the check can be relaxed similarly to resize.
The commit also includes a small refactor, opting to split the
error if checks between two new files: tosa-validation-invalid-strict
and tosa-validation-invalid.
Change-Id: I851fb98dab57299f1d92f999146723ee1a58ec51
---
.../Tosa/Transforms/TosaValidation.cpp | 60 +++++----
mlir/test/Dialect/Tosa/level_check.mlir | 124 +++++++++---------
.../Tosa/tosa-validation-invalid-strict.mlir | 91 +++++++++++++
...heck.mlir => tosa-validation-invalid.mlir} | 62 +--------
4 files changed, 188 insertions(+), 149 deletions(-)
create mode 100644 mlir/test/Dialect/Tosa/tosa-validation-invalid-strict.mlir
rename mlir/test/Dialect/Tosa/{error_if_check.mlir => tosa-validation-invalid.mlir} (87%)
diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
index 9b5e8a298f219c..69e1682ffd075b 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
@@ -1106,7 +1106,8 @@ LogicalResult TosaValidation::applyVariableCheck(Operation *op) {
return success();
}
-LogicalResult checkErrorIfResize(Operation *op) {
+LogicalResult checkErrorIfResize(Operation *op,
+ bool checkStrictSpecConformance) {
auto resize = dyn_cast<tosa::ResizeOp>(op);
if (!resize)
return success();
@@ -1123,7 +1124,8 @@ LogicalResult checkErrorIfResize(Operation *op) {
// Ensure the image size is supported by GPU APIs and that for integer
// implementations, position * stride does not overflow int32_t.
- if (inputType.hasStaticShape() && outputType.hasStaticShape()) {
+ if (checkStrictSpecConformance && inputType.hasStaticShape() &&
+ outputType.hasStaticShape()) {
const SmallVector<int64_t, 4> sizes = {
outputType.getDimSize(1), outputType.getDimSize(2),
inputType.getDimSize(1), inputType.getDimSize(2)};
@@ -1166,27 +1168,30 @@ LogicalResult checkErrorIfResize(Operation *op) {
const int64_t offsetY = offset[0];
const int64_t offsetX = offset[1];
- // Set a consistent lower limit of 1/16 downscale to simplify
- // implementations
- if (offsetY < -scaleYN || offsetY >= 16 * scaleYN)
- return op->emitOpError(
- "expect offsetY / scaleYNumerator to be in range [-1, 16), got ")
- << offsetY << "/" << scaleYN;
- if (offsetX < -scaleXN || offsetX >= 16 * scaleXN)
- return op->emitOpError(
- "expect offsetX / scaleXNumerator to be in range [-1, 16), got ")
- << offsetX << "/" << scaleXN;
-
const int64_t borderY = border[0];
const int64_t borderX = border[1];
- if (borderY < -16 * scaleYN || borderY >= scaleYN)
- return op->emitOpError(
- "expect borderY / scaleYNumerator to be in range [-16, 1), got ")
- << borderY << "/" << scaleYN;
- if (borderX < -16 * scaleXN || borderX >= scaleXN)
- return op->emitOpError(
- "expect borderX / scaleXNumerator to be in range [-16, 1), got ")
- << borderX << "/" << scaleXN;
+
+ // Set a consistent lower limit of 1/16 downscale to simplify
+ // implementations
+ if (checkStrictSpecConformance) {
+ if (offsetY < -scaleYN || offsetY >= 16 * scaleYN)
+ return op->emitOpError("expect offsetY / scaleYNumerator to be in range "
+ "[-1, 16), got ")
+ << offsetY << "/" << scaleYN;
+ if (offsetX < -scaleXN || offsetX >= 16 * scaleXN)
+ return op->emitOpError("expect offsetX / scaleXNumerator to be in range "
+ "[-1, 16), got ")
+ << offsetX << "/" << scaleXN;
+
+ if (borderY < -16 * scaleYN || borderY >= scaleYN)
+ return op->emitOpError("expect borderY / scaleYNumerator to be in range "
+ "[-16, 1), got ")
+ << borderY << "/" << scaleYN;
+ if (borderX < -16 * scaleXN || borderX >= scaleXN)
+ return op->emitOpError("expect borderX / scaleXNumerator to be in range "
+ "[-16, 1), got ")
+ << borderX << "/" << scaleXN;
+ }
// In TOSA specification, we do not support broadcast behavior. Here is a
// strict check to conform to the specification.
@@ -1569,11 +1574,12 @@ LogicalResult checkErrorIfScatter(Operation *op) {
}
LogicalResult TosaValidation::applyErrorIfCheck(Operation *op) {
- if (failed(checkErrorIfResize(op)) || failed(checkErrorIfMul(op)) ||
- failed(checkErrorIfTable(op)) || failed(checkErrorIfRescale(op)) ||
- failed(checkErrorIfPad(op)) || failed(checkErrorIfReshape(op)) ||
- failed(checkErrorIfSlice(op)) || failed(checkErrorIfCondIf(op)) ||
- failed(checkErrorIfWhileLoop(op)) || failed(checkErrorIfScatter(op)))
+ if (failed(checkErrorIfResize(op, strictOpSpecAlignment)) ||
+ failed(checkErrorIfMul(op)) || failed(checkErrorIfTable(op)) ||
+ failed(checkErrorIfRescale(op)) || failed(checkErrorIfPad(op)) ||
+ failed(checkErrorIfReshape(op)) || failed(checkErrorIfSlice(op)) ||
+ failed(checkErrorIfCondIf(op)) || failed(checkErrorIfWhileLoop(op)) ||
+ failed(checkErrorIfScatter(op)))
return failure();
return success();
}
@@ -1763,7 +1769,7 @@ void TosaValidation::runOnOperation() {
return signalPassFailure();
// do error if checks
- if (strictOpSpecAlignment && failed(applyErrorIfCheck(op)))
+ if (failed(applyErrorIfCheck(op)))
return signalPassFailure();
});
}
diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir
index cde4f4d9e3fdec..33e430680db105 100644
--- a/mlir/test/Dialect/Tosa/level_check.mlir
+++ b/mlir/test/Dialect/Tosa/level_check.mlir
@@ -1202,19 +1202,6 @@ func.func @test_resize_scale_x(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x7970
// -----
-// A non-positive scale is invalid and reported by the ERROR_IF check under
-// strict-op-spec-alignment. Here (non-strict), the level check must skip the
-// scale ratio comparison to avoid dividing by scale_x_d = 0.
-func.func @test_resize_nonpositive_scale_skips_level_check(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
- %scale = tosa.const_shape values(dense<[4, 2, 1, 0]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x32x32x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x64x64x8xf32>
- return %1 : tensor<1x64x64x8xf32>
-}
-
-// -----
-
func.func @test_tensor_size_valid(%arg0: tensor<1x536870911xf32>) {
%0 = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
%1 = tosa.const_shape values(dense<1> : tensor<2xindex>) : () -> !tosa.shape<2>
@@ -1403,19 +1390,19 @@ module {
func.func @test_while_loop_tensor_size_invalid(%arg0: tensor<536870912xi32>, %arg1: tensor<i32>) {
%0 = "tosa.const"() <{values = dense<0> : tensor<i32>}> : () -> tensor<i32>
// expected-error at +1 {{'tosa.while_loop' op failed level check: operand tensor size (in bytes) <= (1 << MAX_LOG2_SIZE - 1)}}
- %1:3 = tosa.while_loop (%arg2 = %0, %arg3 = %0, %arg4 = %arg0) : (tensor<i32>, tensor<i32>, tensor<536870912xi32>) -> (tensor<i32>, tensor<i32>, tensor<536870912xi32>) {
- %2 = tosa.greater_equal %arg3, %arg1 : (tensor<i32>, tensor<i32>) -> tensor<i1>
+ %1:4 = tosa.while_loop (%arg2 = %0, %arg3 = %0, %arg4 = %arg0, %arg5 = %arg1) : (tensor<i32>, tensor<i32>, tensor<536870912xi32>, tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<536870912xi32>, tensor<i32>) {
+ %2 = tosa.greater_equal %arg3, %arg5 : (tensor<i32>, tensor<i32>) -> tensor<i1>
%3 = tosa.logical_not %2 : (tensor<i1>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
- ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<536870912xi32>):
+ ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<536870912xi32>, %arg5: tensor<i32>):
%2 = "tosa.const"() <{values = dense<1> : tensor<i32>}> : () -> tensor<i32>
%3 = "tosa.const"() <{values = dense<4> : tensor<1xi32>}> : () -> tensor<1xi32>
%4 = tosa.add %arg3, %2 : (tensor<i32>, tensor<i32>) -> tensor<i32>
// expected-error at +1 {{'tosa.add' op failed level check: operand tensor size (in bytes) <= (1 << MAX_LOG2_SIZE - 1)}}
%5 = tosa.add %arg4, %3 : (tensor<536870912xi32>, tensor<1xi32>) -> tensor<536870912xi32>
%6 = tosa.add %arg2, %2 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %6, %4, %5 : tensor<i32>, tensor<i32>, tensor<536870912xi32>
+ tosa.yield %6, %4, %5, %arg5 : tensor<i32>, tensor<i32>, tensor<536870912xi32>, tensor<i32>
}
return
}
@@ -1474,17 +1461,17 @@ module {
// CHECK-LABEL: @test_while_loop
func.func @test_while_loop(%arg0: tensor<1x1x1x1x1x1x1xf32>, %arg1: tensor<i32>) {
%0 = "tosa.const"() <{values = dense<0> : tensor<i32>}> : () -> tensor<i32>
- %1:2 = "tosa.while_loop"(%0, %arg0) ({
- ^bb0(%arg3: tensor<i32>, %arg4: tensor<1x1x1x1x1x1x1xf32>):
- %2 = "tosa.greater_equal"(%arg3, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i1>
+ %1:3 = "tosa.while_loop"(%0, %arg0, %arg1) ({
+ ^bb0(%arg3: tensor<i32>, %arg4: tensor<1x1x1x1x1x1x1xf32>, %arg5: tensor<i32>):
+ %2 = "tosa.greater_equal"(%arg3, %arg5) : (tensor<i32>, tensor<i32>) -> tensor<i1>
%3 = "tosa.logical_not"(%2) : (tensor<i1>) -> tensor<i1>
"tosa.yield"(%3) : (tensor<i1>) -> ()
}, {
- ^bb0(%arg3: tensor<i32>, %arg4: tensor<1x1x1x1x1x1x1xf32>):
+ ^bb0(%arg3: tensor<i32>, %arg4: tensor<1x1x1x1x1x1x1xf32>, %arg5: tensor<i32>):
%2 = "tosa.const"() <{values = dense<1> : tensor<i32>}> : () -> tensor<i32>
%3 = "tosa.add"(%arg3, %2) : (tensor<i32>, tensor<i32>) -> tensor<i32>
- "tosa.yield"(%3, %arg4) : (tensor<i32>, tensor<1x1x1x1x1x1x1xf32>) -> ()
- }) : (tensor<i32>, tensor<1x1x1x1x1x1x1xf32>) -> (tensor<i32>, tensor<1x1x1x1x1x1x1xf32>)
+ tosa.yield %3, %arg4, %arg5 : tensor<i32>, tensor<1x1x1x1x1x1x1xf32>, tensor<i32>
+ }) : (tensor<i32>, tensor<1x1x1x1x1x1x1xf32>, tensor<i32>) -> (tensor<i32>, tensor<1x1x1x1x1x1x1xf32>, tensor<i32>)
return
}
@@ -1733,7 +1720,7 @@ func.func @test_while_tensor_list_size(%arg0: tensor<1x1x1x1x1x1x1xf32>, %arg1:
%0 = "tosa.const"() <{values = dense<0> : tensor<1xi32>}> : () -> tensor<1xi32>
// expected-error at +1 {{'tosa.while_loop' op failed level check: length(tensor_list_shape(inputs)) <= MAX_TENSOR_LIST_SIZE (64), got 65}}
%1:65 = "tosa.while_loop"(%0, %arg0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
+ %arg1, %0, %0, %0, %0, %0, %0, %0, %0, %0,
%0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
%0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
%0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
@@ -1750,7 +1737,7 @@ func.func @test_while_tensor_list_size(%arg0: tensor<1x1x1x1x1x1x1xf32>, %arg1:
%50: tensor<1xi32>, %51: tensor<1xi32>, %52: tensor<1xi32>, %53: tensor<1xi32>, %54: tensor<1xi32>, %55: tensor<1xi32>, %56: tensor<1xi32>, %57: tensor<1xi32>, %58: tensor<1xi32>, %59: tensor<1xi32>,
%60: tensor<1xi32>, %61: tensor<1xi32>, %62: tensor<1xi32>
):
- %2 = "tosa.greater_equal"(%arg3, %arg1) : (tensor<1xi32>, tensor<1xi32>) -> tensor<1xi1>
+ %2 = "tosa.greater_equal"(%arg3, %00) : (tensor<1xi32>, tensor<1xi32>) -> tensor<1xi1>
%3 = "tosa.logical_not"(%2) : (tensor<1xi1>) -> tensor<1xi1>
"tosa.yield"(%3) : (tensor<1xi1>) -> ()
}, {
@@ -1766,13 +1753,13 @@ func.func @test_while_tensor_list_size(%arg0: tensor<1x1x1x1x1x1x1xf32>, %arg1:
%2 = "tosa.const"() <{values = dense<1> : tensor<1xi32>}> : () -> tensor<1xi32>
%3 = "tosa.add"(%arg3, %2) : (tensor<1xi32>, tensor<1xi32>) -> tensor<1xi32>
"tosa.yield"(%3, %arg4,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0, %0, %0, %0, %0, %0, %0, %0,
- %0, %0, %0
+ %00, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01, %01, %01, %01, %01, %01, %01, %01,
+ %01, %01, %01
) : (
tensor<1xi32>, tensor<1x1x1x1x1x1x1xf32>,
tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>, tensor<1xi32>,
@@ -1808,38 +1795,48 @@ func.func @test_while_tensor_list_size(%arg0: tensor<1x1x1x1x1x1x1xf32>, %arg1:
// -----
-func.func @test_cond_if_max_nested_depth(%arg0: tensor<f32>, %arg1: tensor<f32>, %arg2: tensor<i1>, %arg3: tensor<i1>) -> tensor<f32> {
+func.func @test_cond_if_max_nested_depth(%arg2: tensor<i1>) -> tensor<f32> {
%0 = tosa.cond_if %arg2 : tensor<i1> -> tensor<f32> {
- %1 = tosa.cond_if %arg3 : tensor<i1>-> tensor<f32> {
- %2 = tosa.cond_if %arg2 : tensor<i1> -> tensor<f32> {
- %3 = tosa.cond_if %arg3 : tensor<i1> -> tensor<f32> {
- %4 = tosa.cond_if %arg2 : tensor<i1> -> tensor<f32> {
+ %arg4 = tosa.const values(dense<true> : tensor<i1>) : () -> tensor<i1>
+ %1 = tosa.cond_if %arg4 : tensor<i1> -> tensor<f32> {
+ %arg5 = tosa.const values(dense<true> : tensor<i1>) : () -> tensor<i1>
+ %2 = tosa.cond_if %arg5 : tensor<i1> -> tensor<f32> {
+ %arg6 = tosa.const values(dense<true> : tensor<i1>) : () -> tensor<i1>
+ %3 = tosa.cond_if %arg6 : tensor<i1> -> tensor<f32> {
+ %arg7 = tosa.const values(dense<true> : tensor<i1>) : () -> tensor<i1>
+ %4 = tosa.cond_if %arg7 : tensor<i1> -> tensor<f32> {
+ %arg8 = tosa.const values(dense<true> : tensor<i1>) : () -> tensor<i1>
// expected-error at +1 {{'tosa.cond_if' op failed level check: tosa_nesting_depth < MAX_NESTING (6), got 6}}
- %5 = tosa.cond_if %arg3 : tensor<i1> -> tensor<f32> {
- %res = tosa.sub %arg0, %arg1 : (tensor<f32>, tensor<f32>) -> tensor<f32>
+ %5 = tosa.cond_if %arg8 : tensor<i1> -> tensor<f32> {
+ %res = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
tosa.yield %res : tensor<f32>
} else {
- tosa.yield %arg0 : tensor<f32>
+ %arg9 = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
+ tosa.yield %arg9 : tensor<f32>
}
tosa.yield %5 : tensor<f32>
} else {
- tosa.yield %arg0 : tensor<f32>
+ %arg9 = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
+ tosa.yield %arg9 : tensor<f32>
}
tosa.yield %4 : tensor<f32>
} else {
- tosa.yield %arg0 : tensor<f32>
+ %arg9 = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
+ tosa.yield %arg9 : tensor<f32>
}
tosa.yield %3 : tensor<f32>
} else {
- tosa.yield %arg0 : tensor<f32>
+ %arg9 = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
+ tosa.yield %arg9 : tensor<f32>
}
tosa.yield %2 : tensor<f32>
} else {
- tosa.yield %arg0 : tensor<f32>
+ %arg9 = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
+ tosa.yield %arg9 : tensor<f32>
}
tosa.yield %1 : tensor<f32>
} else {
- %res = tosa.sub %arg0, %arg1 : (tensor<f32>, tensor<f32>) -> tensor<f32>
+ %res = tosa.const values(dense<0.0> : tensor<f32>) : () -> tensor<f32>
tosa.yield %res : tensor<f32>
}
return %0 : tensor<f32>
@@ -1849,54 +1846,59 @@ func.func @test_cond_if_max_nested_depth(%arg0: tensor<f32>, %arg1: tensor<f32>,
func.func @test_while_loop_max_nested_depth(%arg0: tensor<i32>) {
%init_0 = "tosa.const"() <{values = dense<0> : tensor<i32>}> : () -> tensor<i32>
- %cst_1 = "tosa.const"() <{values = dense<1> : tensor<i32>}> : () -> tensor<i32>
%1:2 = tosa.while_loop (%arg2 = %init_0, %arg3 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg3, %arg2 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg2: tensor<i32>, %arg2b: tensor<i32>):
- %1:2 = tosa.while_loop (%arg4 = %init_0, %arg5 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
+ %1:2 = tosa.while_loop (%arg4 = %arg2, %arg5 = %arg2b) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg5, %arg4 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg4: tensor<i32>, %arg4b: tensor<i32>):
- %1:2 = tosa.while_loop (%arg6 = %init_0, %arg7 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
+ %1:2 = tosa.while_loop (%arg6 = %arg4, %arg7 = %arg4b) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg7, %arg6 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg6: tensor<i32>, %arg6b: tensor<i32>):
- %1:2 = tosa.while_loop (%arg8 = %init_0, %arg9 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
+ %1:2 = tosa.while_loop (%arg8 = %arg6, %arg9 = %arg6b) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg9, %arg8 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg8: tensor<i32>, %arg8b: tensor<i32>):
- %1:2 = tosa.while_loop (%arg10 = %init_0, %arg11 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
+ %1:2 = tosa.while_loop (%arg10 = %arg8, %arg11 = %arg8b) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg11, %arg10 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg10: tensor<i32>, %arg10b: tensor<i32>):
// expected-error at +1 {{'tosa.while_loop' op failed level check: tosa_nesting_depth < MAX_NESTING (6), got 6}}
- %1:2 = tosa.while_loop (%arg12 = %init_0, %arg13 = %arg0) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
+ %1:2 = tosa.while_loop (%arg12 = %arg10, %arg13 = %arg10b) : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>) {
%2 = tosa.greater_equal %arg13, %arg12 : (tensor<i32>, tensor<i32>) -> tensor<i1>
tosa.yield %2 : tensor<i1>
} do {
^bb0(%arg12: tensor<i32>, %arg12b: tensor<i32>):
- %3 = tosa.add %arg12, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
+ %arg14 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
+ %3 = tosa.add %arg12, %arg14 : (tensor<i32>, tensor<i32>) -> tensor<i32>
+ tosa.yield %arg12, %3: tensor<i32>, tensor<i32>
}
- %3 = tosa.add %arg10, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
+ %arg14 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
+ %3 = tosa.add %arg10, %arg14 : (tensor<i32>, tensor<i32>) -> tensor<i32>
+ tosa.yield %arg10, %3: tensor<i32>, tensor<i32>
}
- %3 = tosa.add %arg8, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
+ %arg14 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
+ %3 = tosa.add %arg8, %arg14 : (tensor<i32>, tensor<i32>) -> tensor<i32>
+ tosa.yield %arg8, %3: tensor<i32>, tensor<i32>
}
- %3 = tosa.add %arg6, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
+ %arg14 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
+ %3 = tosa.add %arg6, %arg14 : (tensor<i32>, tensor<i32>) -> tensor<i32>
+ tosa.yield %arg6, %3: tensor<i32>, tensor<i32>
}
- %3 = tosa.add %arg4, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
- tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
+ %arg14 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
+ %3 = tosa.add %arg4, %arg14 : (tensor<i32>, tensor<i32>) -> tensor<i32>
+ tosa.yield %arg4, %3: tensor<i32>, tensor<i32>
}
+ %cst_1 = tosa.const values(dense<1> : tensor<i32>) : () -> tensor<i32>
%3 = tosa.add %arg2, %cst_1 : (tensor<i32>, tensor<i32>) -> tensor<i32>
tosa.yield %arg2, %3: tensor<i32>, tensor<i32>
}
diff --git a/mlir/test/Dialect/Tosa/tosa-validation-invalid-strict.mlir b/mlir/test/Dialect/Tosa/tosa-validation-invalid-strict.mlir
new file mode 100644
index 00000000000000..451f3a8b40fa8a
--- /dev/null
+++ b/mlir/test/Dialect/Tosa/tosa-validation-invalid-strict.mlir
@@ -0,0 +1,91 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics -tosa-attach-target="level=none profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,dynamic" -tosa-validate="strict-op-spec-alignment validate-function-signature=false"
+
+func.func @test_matmul_rank3_lhs_broadcast_dynamic_rhs(%arg0: tensor<1x4x7xf32>, %arg1: tensor<?x7x5xf32>) -> tensor<2x4x5xf32> {
+ %azp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>
+ %bzp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>
+ // expected-error at +1 {{'tosa.matmul' op MATMUL ranks other than 3 or batch broadcasting require TOSA specification version 1.1.draft}}
+ %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<1x4x7xf32>, tensor<?x7x5xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x4x5xf32>
+ return %0 : tensor<2x4x5xf32>
+}
+
+// -----
+
+func.func @test_matmul_rank3_rhs_broadcast_dynamic_lhs(%arg0: tensor<?x4x7xf32>, %arg1: tensor<1x7x5xf32>) -> tensor<2x4x5xf32> {
+ %azp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>
+ %bzp0 = "tosa.const"() <{values = dense<0.0> : tensor<1xf32>}> : () -> tensor<1xf32>
+ // expected-error at +1 {{'tosa.matmul' op MATMUL ranks other than 3 or batch broadcasting require TOSA specification version 1.1.draft}}
+ %0 = tosa.matmul %arg0, %arg1, %azp0, %bzp0 : (tensor<?x4x7xf32>, tensor<1x7x5xf32>, tensor<1xf32>, tensor<1xf32>) -> tensor<2x4x5xf32>
+ return %0 : tensor<2x4x5xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_large_image_size
+func.func @test_resize_large_image_size(%arg0: tensor<1x16384x16384x8xf32>) -> tensor<1x32767x32767x8xf32> {
+ %scale = tosa.const_shape values(dense<[2, 1, 2, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect input/output height/width dims to be < 16384, got [OH, OW, IH, IW] = 32767, 32767, 16384, 16384}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x16384x16384x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x32767x32767x8xf32>
+ return %1 : tensor<1x32767x32767x8xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_offset_x
+func.func @test_resize_invalid_offset_x(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
+ %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<[0, -2]> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect offsetX / scaleXNumerator to be in range [-1, 16), got -2/1}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
+ return %1 : tensor<?x?x?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_border_x
+func.func @test_resize_invalid_boarder_x(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
+ %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<[0, 2]> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect borderX / scaleXNumerator to be in range [-16, 1), got 2/1}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
+ return %1 : tensor<?x?x?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_offset_y
+func.func @test_resize_invalid_offset_y(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
+ %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<[17, 0]> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect offsetY / scaleYNumerator to be in range [-1, 16), got 17/1}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
+ return %1 : tensor<?x?x?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_invalid_border_y
+func.func @test_resize_invalid_boarder_y(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
+ %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<[-17, 0]> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect borderY / scaleYNumerator to be in range [-16, 1), got -17/1}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
+ return %1 : tensor<?x?x?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: test_resize_large_image_size
+func.func @test_resize_large_image_size(%arg0: tensor<1x16384x16384x8xf32>) -> tensor<1x32767x32767x8xf32> {
+ %scale = tosa.const_shape values(dense<[2, 1, 2, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
+ %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
+ // expected-error at +1 {{'tosa.resize' op expect input/output height/width dims to be < 16384, got [OH, OW, IH, IW] = 32767, 32767, 16384, 16384}}
+ %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x16384x16384x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x32767x32767x8xf32>
+ return %1 : tensor<1x32767x32767x8xf32>
+}
diff --git a/mlir/test/Dialect/Tosa/error_if_check.mlir b/mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
similarity index 87%
rename from mlir/test/Dialect/Tosa/error_if_check.mlir
rename to mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
index edd82bc4b6d023..9a73d52eb812b3 100644
--- a/mlir/test/Dialect/Tosa/error_if_check.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
@@ -1,16 +1,4 @@
-// RUN: mlir-opt %s -split-input-file -verify-diagnostics -tosa-attach-target="level=none specification_version=1.1.draft profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,dynamic,mx_common,mx_fp4e2m1,shape" -tosa-validate="strict-op-spec-alignment validate-function-signature=false"
-
-// -----
-
-// CHECK-LABEL: test_resize_large_image_size
-func.func @test_resize_large_image_size(%arg0: tensor<1x16384x16384x8xf32>) -> tensor<1x32767x32767x8xf32> {
- %scale = tosa.const_shape values(dense<[2, 1, 2, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- // expected-error at +1 {{'tosa.resize' op expect input/output height/width dims to be < 16384, got [OH, OW, IH, IW] = 32767, 32767, 16384, 16384}}
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x16384x16384x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<1x32767x32767x8xf32>
- return %1 : tensor<1x32767x32767x8xf32>
-}
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics -tosa-attach-target="level=none specification_version=1.1.draft profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,dynamic,mx_common,mx_fp4e2m1,shape" -tosa-validate="validate-function-signature=false"
// -----
@@ -38,54 +26,6 @@ func.func @test_resize_invalid_downscale(%arg0: tensor<1x37x37x8xf32>) -> tensor
// -----
-// CHECK-LABEL: test_resize_invalid_offset_y
-func.func @test_resize_invalid_offset_y(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
- %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<[17, 0]> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- // expected-error at +1 {{'tosa.resize' op expect offsetY / scaleYNumerator to be in range [-1, 16), got 17/1}}
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
- return %1 : tensor<?x?x?x?xf32>
-}
-
-// -----
-
-// CHECK-LABEL: test_resize_invalid_offset_x
-func.func @test_resize_invalid_offset_x(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
- %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<[0, -2]> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- // expected-error at +1 {{'tosa.resize' op expect offsetX / scaleXNumerator to be in range [-1, 16), got -2/1}}
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
- return %1 : tensor<?x?x?x?xf32>
-}
-
-// -----
-
-// CHECK-LABEL: test_resize_invalid_border_y
-func.func @test_resize_invalid_boarder_y(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
- %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<[-17, 0]> : tensor<2xindex>) : () -> !tosa.shape<2>
- // expected-error at +1 {{'tosa.resize' op expect borderY / scaleYNumerator to be in range [-16, 1), got -17/1}}
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
- return %1 : tensor<?x?x?x?xf32>
-}
-
-// -----
-
-// CHECK-LABEL: test_resize_invalid_border_x
-func.func @test_resize_invalid_boarder_x(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
- %scale = tosa.const_shape values(dense<[1, 1, 1, 1]> : tensor<4xindex>) : () -> !tosa.shape<4>
- %offset = tosa.const_shape values(dense<0> : tensor<2xindex>) : () -> !tosa.shape<2>
- %border = tosa.const_shape values(dense<[0, 2]> : tensor<2xindex>) : () -> !tosa.shape<2>
- // expected-error at +1 {{'tosa.resize' op expect borderX / scaleXNumerator to be in range [-16, 1), got 2/1}}
- %1 = tosa.resize %arg0, %scale, %offset, %border mode<BILINEAR> : (tensor<1x8x8x8xf32>, !tosa.shape<4>, !tosa.shape<2>, !tosa.shape<2>) -> tensor<?x?x?x?xf32>
- return %1 : tensor<?x?x?x?xf32>
-}
-
-// -----
-
// CHECK-LABEL: test_resize_nonpositive_scale
func.func @test_resize_nonpositive_scale(%arg0: tensor<1x8x8x8xf32>) -> tensor<?x?x?x?xf32> {
%scale = tosa.const_shape values(dense<[2, 0, -1, 2]> : tensor<4xindex>) : () -> !tosa.shape<4>
More information about the Mlir-commits
mailing list