[Mlir-commits] [mlir] [mlir][tosa] Apply error_if checks in tosa validation without strict mode (PR #235741)

Luke Hutton llvmlistbot at llvm.org
Tue Oct 27 04:11:26 PDT 2026


https://github.com/lhutton1 updated https://github.com/llvm/llvm-project/pull/235741

>From 3cae9cd547528d41154999f397f5caf970def0a3 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  |  79 +++++++++++
 ...heck.mlir => tosa-validation-invalid.mlir} |  84 +-----------
 4 files changed, 176 insertions(+), 171 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} (77%)

diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
index 19f7bb32649f6..3739c0af9a7cf 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.
@@ -1520,11 +1525,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();
 }
@@ -1714,7 +1720,7 @@ void TosaValidation::runOnOperation() {
       signalPassFailure();
 
     // do error if checks
-    if (strictOpSpecAlignment && failed(applyErrorIfCheck(op)))
+    if (failed(applyErrorIfCheck(op)))
       signalPassFailure();
   });
 }
diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir
index cde4f4d9e3fde..33e430680db10 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 0000000000000..b14fc653f46c6
--- /dev/null
+++ b/mlir/test/Dialect/Tosa/tosa-validation-invalid-strict.mlir
@@ -0,0 +1,79 @@
+// 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>
+}
diff --git a/mlir/test/Dialect/Tosa/error_if_check.mlir b/mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
similarity index 77%
rename from mlir/test/Dialect/Tosa/error_if_check.mlir
rename to mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
index ab02aa35f01d7..12c4579609b75 100644
--- a/mlir/test/Dialect/Tosa/error_if_check.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-validation-invalid.mlir
@@ -1,18 +1,4 @@
-// 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"
-
-// -----
-
-// 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 profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,dynamic" -tosa-validate="validate-function-signature=false"
 
 // CHECK-LABEL: test_resize_invalid_scale_numerator
 func.func @test_resize_invalid_scale_numerator(%arg0: tensor<1x9x9x8xf32>) -> tensor<?x?x?x?xf32> {
@@ -38,54 +24,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>
@@ -358,23 +296,3 @@ func.func @test_while_loop_body_not_isolated_from_above(%arg0: tensor<i32>, %arg
   }) : (tensor<i32>) -> (tensor<i32>)
   return
 }
-
-// -----
-
-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>
-}



More information about the Mlir-commits mailing list