[InputConversion][TOSA]: change TOSA level to none (#24667)

For some TOSA lowering use-cases, we will have dynamic batch sizes and
this will trigger the level check. Here we set the level to none so that
dynamic dimensions are allowed in TOSA IR.

The TOSA level check ensures that tensor sizes are within a certain
threshold but for our use-case with TFlite this is not always the case.

---

LIT tests created by Claude

---------

Co-authored-by: Artem Gindinson <gindinson@roofline.ai>
diff --git a/compiler/plugins/input/TOSA/InputConversion/Passes.cpp b/compiler/plugins/input/TOSA/InputConversion/Passes.cpp
index 9208c5b..ef0e07c 100644
--- a/compiler/plugins/input/TOSA/InputConversion/Passes.cpp
+++ b/compiler/plugins/input/TOSA/InputConversion/Passes.cpp
@@ -52,10 +52,15 @@
 
   TosaToLinalgNamedOptions tosaToLinalgNamedOptions;
   tosaToLinalgNamedOptions.preferConv2DKernelLayoutHWCF = true;
-  tosa::TosaValidationOptions tosaValidationOptions;
   tosa::TosaAttachTargetOptions tosaTargetOptions;
   tosaTargetOptions.extensions = {"dynamic", "doubleround"};
   tosaTargetOptions.profiles = {"pro_int", "pro_fp"};
+  // TOSA's default level ("8k") rejects any operation with a dynamic shape.
+  // Models commonly have dynamic dimensions (e.g. a dynamic batch size),
+  // so target the unrestricted level while still running full profile and
+  // data type validation.
+  tosaTargetOptions.level = tosa::Level::none;
+  tosa::TosaValidationOptions tosaValidationOptions;
   tosa::addTosaToLinalgPasses(passManager, TosaToLinalgOptions(),
                               tosaToLinalgNamedOptions, tosaValidationOptions,
                               tosaTargetOptions);
diff --git a/compiler/plugins/input/TOSA/InputConversion/test/BUILD.bazel b/compiler/plugins/input/TOSA/InputConversion/test/BUILD.bazel
index ce2ef38..9a474c1 100644
--- a/compiler/plugins/input/TOSA/InputConversion/test/BUILD.bazel
+++ b/compiler/plugins/input/TOSA/InputConversion/test/BUILD.bazel
@@ -22,6 +22,7 @@
             "auto_input_conversion.mlir",
             "convert_i48_to_i64.mlir",
             "strip_signedness.mlir",
+            "tosa_target_level.mlir",
             "tosa_to_linalg_ext.mlir",
             "verify_compiler_tosa_input_legality.mlir",
         ],
diff --git a/compiler/plugins/input/TOSA/InputConversion/test/CMakeLists.txt b/compiler/plugins/input/TOSA/InputConversion/test/CMakeLists.txt
index 799d324..2d5cf66 100644
--- a/compiler/plugins/input/TOSA/InputConversion/test/CMakeLists.txt
+++ b/compiler/plugins/input/TOSA/InputConversion/test/CMakeLists.txt
@@ -19,6 +19,7 @@
     "auto_input_conversion.mlir"
     "convert_i48_to_i64.mlir"
     "strip_signedness.mlir"
+    "tosa_target_level.mlir"
     "tosa_to_linalg_ext.mlir"
     "verify_compiler_tosa_input_legality.mlir"
   TOOLS
diff --git a/compiler/plugins/input/TOSA/InputConversion/test/tosa_target_level.mlir b/compiler/plugins/input/TOSA/InputConversion/test/tosa_target_level.mlir
new file mode 100644
index 0000000..5b5fc44
--- /dev/null
+++ b/compiler/plugins/input/TOSA/InputConversion/test/tosa_target_level.mlir
@@ -0,0 +1,23 @@
+// RUN: iree-opt --split-input-file \
+// RUN:   --pass-pipeline="builtin.module(iree-tosa-input-transformation-pipeline)" \
+// RUN:   --verify-diagnostics %s | FileCheck %s
+
+// IREE targets TOSA level=none so that models with dynamic dimensions
+// (e.g. a dynamic batch size) compile, but we're still able to run profile and
+// data type validation.
+
+// CHECK-LABEL: @dynamic_shape
+func.func @dynamic_shape(%arg0: tensor<?x4xf32>) -> tensor<?x4xf32> {
+  // CHECK: linalg.generic
+  %0 = tosa.clamp %arg0 {max_val = 1.0 : f32, min_val = 0.0 : f32} : (tensor<?x4xf32>) -> tensor<?x4xf32>
+  return %0 : tensor<?x4xf32>
+}
+
+// -----
+
+// Genuine profile/data type violations, unrelated to shape, must be rejected.
+func.func @out_of_profile(%arg0: tensor<4xf8E4M3FN>) -> tensor<4xf8E4M3FN> {
+  // expected-error@+1 {{operand/result data types did not align with any profile or extension}}
+  %0 = tosa.abs %arg0 : (tensor<4xf8E4M3FN>) -> tensor<4xf8E4M3FN>
+  return %0 : tensor<4xf8E4M3FN>
+}