[Mlir-commits] [mlir] Add TOSA -> EmitC tests for MLGO mock models (PR #211833)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Jul 24 08:41:30 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-emitc

Author: ioana ghiban (ioghiban)

<details>
<summary>Changes</summary>

This tests are the first step towards monitoring the recently enabled TOSA -> EmitC path that ML optimization models will switch to, for a fully in-tree, framework free alternative to compile them for inference.

For simplicity, yet testing the core functionality, these tests don't use production models, but rather in-tree mock models, generated by these scripts:
[llvm/lib/Analysis/models/gen-regalloc-eviction-test-model.py](https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/models/gen-regalloc-eviction-test-model.py) /
[llvm/lib/Analysis/models/gen-inline-oz-test-model.py](https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/models/gen-inline-oz-test-model.py)
\+ [llvm/lib/Analysis/models/saved-model-to-tflite.py](https://github.com/llvm/llvm-project/blob/main/llvm/lib/Analysis/models/saved-model-to-tflite.py) + [tosa-converter-for-tflite](https://www.piwheels.org/project/tosa-converter-for-tflite/)

> Note: `saved-model-to-tflite.py` renames the TFLite converted SavedModel function to `main()`, which causes `clang` errors. Changing this behaviour requires interventions in Tensorflow, which are out of scope. Therefore, the functions were manually renamed.

> Note: The includes passed by argument to `clang` should have been handled by EmitC. This only becomes a problem when compiling these models standalone. Embedding the models in LLVM does not cause issues. Nonetheless, future work will ensure `ConvertToEmitC` includes required libraries for these ops. 

---
Full diff: https://github.com/llvm/llvm-project/pull/211833.diff


2 Files Affected:

- (added) mlir/test/Integration/Dialect/EmitC/inline-oz-test-model-tosa.mlir (+57) 
- (added) mlir/test/Integration/Dialect/EmitC/regalloc-eviction-test-model-tosa.mlir (+57) 


``````````diff
diff --git a/mlir/test/Integration/Dialect/EmitC/inline-oz-test-model-tosa.mlir b/mlir/test/Integration/Dialect/EmitC/inline-oz-test-model-tosa.mlir
new file mode 100644
index 0000000000000..ff5de17ba06a0
--- /dev/null
+++ b/mlir/test/Integration/Dialect/EmitC/inline-oz-test-model-tosa.mlir
@@ -0,0 +1,57 @@
+// DEFINE: %{pipeline} = "builtin.module(\
+// DEFINE:   func.func(\
+// DEFINE:     tosa-to-linalg-named,\
+// DEFINE:     tosa-to-linalg,\
+// DEFINE:     tosa-to-arith,\
+// DEFINE:     tosa-to-tensor\
+// DEFINE:   ),\
+// DEFINE:   symbol-privatize,\
+// DEFINE:   scalarize-single-element-tensor-return,\
+// DEFINE:   one-shot-bufferize{\
+// DEFINE:     bufferize-function-boundaries=true\
+// DEFINE:     function-boundary-type-conversion=identity-layout-map\
+// DEFINE:     buffer-alignment=0\
+// DEFINE:   },\
+// DEFINE:   buffer-results-to-out-params{\
+// DEFINE:     hoist-static-allocs=true\
+// DEFINE:   },\
+// DEFINE:   buffer-deallocation-pipeline,\
+// DEFINE:   func.func(\
+// DEFINE:     convert-linalg-to-loops\
+// DEFINE:   ),\
+// DEFINE:   expand-strided-metadata,\
+// DEFINE:   canonicalize,\
+// DEFINE:   memref-elide-reinterpret-cast,\
+// DEFINE:   convert-to-emitc,\
+// DEFINE:   math-expand-ops{\
+// DEFINE:     ops=rsqrt\
+// DEFINE:   },\
+// DEFINE:   arith-expand,\
+// DEFINE:   convert-math-to-emitc,\
+// DEFINE:   convert-arith-to-emitc\
+// DEFINE: )"
+
+// DEFINE: %{lower_to_emitc} = mlir-opt --pass-pipeline=%{pipeline} %s -o %t
+// DEFINE: %{translate} = mlir-translate -mlir-to-cpp %t -o %t.c 
+// DEFINE: %{compile} =  %host_cc -include stdint.h -fsyntax-only -Wpedantic -Wall -Werror -Wno-unused %t.c
+
+/// Lower via the pipeline defined above
+// RUN: rm -f %t && %{lower_to_emitc} && FileCheck %s --input-file=%t && %{translate} && %{compile}
+
+/// Generated with llvm/lib/Analysis/models/gen-inline-oz-test-model.py  + llvm/lib/Analysis/models/saved-model-to-tflite.py
+/// Renamed "main" to avoid:
+///   error: 'main' should not be declared static
+///   error: return type of 'main' is not 'int'
+///   error: too many parameters (40) for 'main': must be 0, 2, or 3
+///   error: first parameter of 'main' (argument count) must be of type 'int'
+///   error: second parameter of 'main' (argument array) must be of type 'char **'
+///   error: third parameter of 'main' (environment) must be of type 'char **'
+
+// CHECK-LABEL: @mock_model
+// CHECK:         emitc.constant
+module attributes {tf_saved_model.semantics, tfl.description = "MLIR Converted.", tfl.metadata = {CONVERSION_METADATA = "\0C\00\00\00\08\00\0E\00\08\00\04\00\08\00\00\00\10\00\00\00$\00\00\00\00\00\06\00\08\00\04\00\06\00\00\00\04\00\00\00\00\00\00\00\00\00\0A\00\10\00\0C\00\08\00\04\00\0A\00\00\00\01\00\00\00\02\00\00\00\04\00\00\00\06\00\00\002.15.1\00\00", min_runtime_version = "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"}, tfl.schema_version = 3 : i32} {
+  func.func @mock_model(%arg0: tensor<i64> {tf_saved_model.index_path = ["callsite_cost"]}, %arg1: tensor<i64> {tf_saved_model.index_path = ["is_multiple_blocks"]}, %arg2: tensor<i64> {tf_saved_model.index_path = ["caller_conditionally_executed_blocks"]}, %arg3: tensor<i64> {tf_saved_model.index_path = ["cold_cc_penalty"]}, %arg4: tensor<i64> {tf_saved_model.index_path = ["callee_conditionally_executed_blocks"]}, %arg5: tensor<i64> {tf_saved_model.index_path = ["callee_users"]}, %arg6: tensor<i64> {tf_saved_model.index_path = ["callee_basic_block_count"]}, %arg7: tensor<i64> {tf_saved_model.index_path = ["nr_ctant_params"]}, %arg8: tensor<i64> {tf_saved_model.index_path = ["load_relative_intrinsic"]}, %arg9: tensor<i64> {tf_saved_model.index_path = ["jump_table_penalty"]}, %arg10: tensor<i64> {tf_saved_model.index_path = ["unsimplified_common_instructions"]}, %arg11: tensor<i64> {tf_saved_model.index_path = ["indirect_call_penalty"]}, %arg12: tensor<i64> {tf_saved_model.index_path = ["load_elimination"]}, %arg13: tensor<i64> {tf_saved_model.index_path = ["is_caller_avail_external"]}, %arg14: tensor<i64> {tf_saved_model.index_path = ["call_penalty"]}, %arg15: tensor<i64> {tf_saved_model.index_path = ["cost_estimate"]}, %arg16: tensor<i64> {tf_saved_model.index_path = ["case_cluster_penalty"]}, %arg17: tensor<i64> {tf_saved_model.index_path = ["node_count"]}, %arg18: tensor<i64> {tf_saved_model.index_path = ["call_argument_setup"]}, %arg19: tensor<i64> {tf_saved_model.index_path = ["sroa_savings"]}, %arg20: tensor<i64> {tf_saved_model.index_path = ["lowered_call_arg_setup"]}, %arg21: tensor<i64> {tf_saved_model.index_path = ["threshold"]}, %arg22: tensor<i64> {tf_saved_model.index_path = ["dead_blocks"]}, %arg23: tensor<i64> {tf_saved_model.index_path = ["constant_args"]}, %arg24: tensor<i64> {tf_saved_model.index_path = ["sroa_losses"]}, %arg25: tensor<i64> {tf_saved_model.index_path = ["simplified_instructions"]}, %arg26: tensor<i64> {tf_saved_model.index_path = ["num_loops"]}, %arg27: tensor<i32> {tf_saved_model.index_path = ["step_type"]}, %arg28: tensor<i64> {tf_saved_model.index_path = ["edge_count"]}, %arg29: tensor<i64> {tf_saved_model.index_path = ["is_callee_avail_external"]}, %arg30: tensor<i64> {tf_saved_model.index_path = ["nested_inlines"]}, %arg31: tensor<i64> {tf_saved_model.index_path = ["caller_basic_block_count"]}, %arg32: tensor<i64> {tf_saved_model.index_path = ["last_call_to_static_bonus"]}, %arg33: tensor<i64> {tf_saved_model.index_path = ["nested_inline_cost_estimate"]}, %arg34: tensor<i64> {tf_saved_model.index_path = ["callsite_height"]}, %arg35: tensor<i64> {tf_saved_model.index_path = ["constant_offset_ptr_args"]}, %arg36: tensor<i64> {tf_saved_model.index_path = ["switch_penalty"]}, %arg37: tensor<f32> {tf_saved_model.index_path = ["discount"]}, %arg38: tensor<i64> {tf_saved_model.index_path = ["caller_users"]}, %arg39: tensor<f32> {tf_saved_model.index_path = ["reward"]}) -> (tensor<i64> {tf_saved_model.index_path = ["inlining_decision"]}) attributes {tf.entry_function = {inputs = "action_callsite_cost:0,action_is_multiple_blocks:0,action_caller_conditionally_executed_blocks:0,action_cold_cc_penalty:0,action_callee_conditionally_executed_blocks:0,action_callee_users:0,action_callee_basic_block_count:0,action_nr_ctant_params:0,action_load_relative_intrinsic:0,action_jump_table_penalty:0,action_unsimplified_common_instructions:0,action_indirect_call_penalty:0,action_load_elimination:0,action_is_caller_avail_external:0,action_call_penalty:0,action_cost_estimate:0,action_case_cluster_penalty:0,action_node_count:0,action_call_argument_setup:0,action_sroa_savings:0,action_lowered_call_arg_setup:0,action_threshold:0,action_dead_blocks:0,action_constant_args:0,action_sroa_losses:0,action_simplified_instructions:0,action_num_loops:0,action_step_type:0,action_edge_count:0,action_is_callee_avail_external:0,action_nested_inlines:0,action_caller_basic_block_count:0,action_last_call_to_static_bonus:0,action_nested_inline_cost_estimate:0,action_callsite_height:0,action_constant_offset_ptr_args:0,action_switch_penalty:0,action_discount:0,action_caller_users:0,action_reward:0", outputs = "PartitionedCall:0"}, tf_saved_model.exported_names = ["action"]} {
+    %0 = "tosa.const"() <{values = dense<1> : tensor<i64>}> : () -> tensor<i64>
+    return %0 : tensor<i64>
+  }
+}
diff --git a/mlir/test/Integration/Dialect/EmitC/regalloc-eviction-test-model-tosa.mlir b/mlir/test/Integration/Dialect/EmitC/regalloc-eviction-test-model-tosa.mlir
new file mode 100644
index 0000000000000..eafbbe814c96a
--- /dev/null
+++ b/mlir/test/Integration/Dialect/EmitC/regalloc-eviction-test-model-tosa.mlir
@@ -0,0 +1,57 @@
+// DEFINE: %{pipeline} = "builtin.module(\
+// DEFINE:   func.func(\
+// DEFINE:     tosa-to-linalg-named,\
+// DEFINE:     tosa-to-linalg,\
+// DEFINE:     tosa-to-arith,\
+// DEFINE:     tosa-to-tensor\
+// DEFINE:   ),\
+// DEFINE:   symbol-privatize,\
+// DEFINE:   scalarize-single-element-tensor-return,\
+// DEFINE:   one-shot-bufferize{\
+// DEFINE:     bufferize-function-boundaries=true\
+// DEFINE:     function-boundary-type-conversion=identity-layout-map\
+// DEFINE:     buffer-alignment=0\
+// DEFINE:   },\
+// DEFINE:   buffer-results-to-out-params{\
+// DEFINE:     hoist-static-allocs=true\
+// DEFINE:   },\
+// DEFINE:   buffer-deallocation-pipeline,\
+// DEFINE:   func.func(\
+// DEFINE:     convert-linalg-to-loops\
+// DEFINE:   ),\
+// DEFINE:   expand-strided-metadata,\
+// DEFINE:   canonicalize,\
+// DEFINE:   memref-elide-reinterpret-cast,\
+// DEFINE:   convert-to-emitc,\
+// DEFINE:   math-expand-ops{\
+// DEFINE:     ops=rsqrt\
+// DEFINE:   },\
+// DEFINE:   arith-expand,\
+// DEFINE:   convert-math-to-emitc,\
+// DEFINE:   convert-arith-to-emitc\
+// DEFINE: )"
+
+// DEFINE: %{lower_to_emitc} = mlir-opt --pass-pipeline=%{pipeline} %s -o %t
+// DEFINE: %{translate} = mlir-translate -mlir-to-cpp %t -o %t.c 
+// DEFINE: %{compile} =  %host_cc -include stddef.h -include stdint.h -include stdlib.h\
+// DEFINE:   -include stdbool.h -fsyntax-only -Wpedantic -Wall -Werror -Wno-unused %t.c
+
+/// Lower via the pipeline defined above
+// RUN: rm -f %t && %{lower_to_emitc} && FileCheck %s --input-file=%t && %{translate} && %{compile}
+
+/// Generated with llvm/lib/Analysis/models/gen-regalloc-eviction-test-model.py + llvm/lib/Analysis/models/saved-model-to-tflite.py
+/// Renamed "main" to avoid:
+///   error: 'main' should not be declared static
+///   error: first parameter of 'main' (argument count) must be of type 'int'
+// CHECK-LABEL: @mock_model
+// CHECK:         for
+// CHECK:         cmp gt
+// CHECK:         conditional
+// CHECK:         assign
+module attributes {tf_saved_model.semantics, tfl.description = "MLIR Converted.", tfl.metadata = {CONVERSION_METADATA = "\0C\00\00\00\08\00\0E\00\08\00\04\00\08\00\00\00\10\00\00\00$\00\00\00\00\00\06\00\08\00\04\00\06\00\00\00\04\00\00\00\00\00\00\00\00\00\0A\00\10\00\0C\00\08\00\04\00\0A\00\00\00\01\00\00\00\02\00\00\00\04\00\00\00\06\00\00\002.15.1\00\00", min_runtime_version = "1.9.0\00\00\00\00\00\00\00\00\00\00\00"}, tfl.schema_version = 3 : i32} {
+  func.func @mock_model(%arg0: tensor<33xi64> {tf_saved_model.index_path = ["mask"]}) -> (tensor<i64> {tf_saved_model.index_path = ["index_to_evict"]}) attributes {tf.entry_function = {inputs = "action_mask:0", outputs = "StatefulPartitionedCall:0"}, tf_saved_model.exported_names = ["action"]} {
+    %0 = tosa.cast %arg0 : (tensor<33xi64>) -> tensor<33xi32>
+    %1 = tosa.argmax %0 {axis = 0 : i32} : (tensor<33xi32>) -> tensor<i64>
+    return %1 : tensor<i64>
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/211833


More information about the Mlir-commits mailing list