| { |
| "op": "ai.onnx.Loop", |
| "cases": [ |
| { |
| "name": "lowered_add_step_scan", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, -1.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.5, 2.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [4, 2], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_cond_false_zero_iterations", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } }, |
| "v_initial": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [7.0] } }, |
| "step": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 1], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_ort_projection_single_iteration_scan_value", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.Opset11WithNoVariadicInputsAndOutputs", |
| "notes": "Projection onto the framework's lowered add-step loop: one true iteration produces one scan output value." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.0] } }, |
| "step": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [1, 1], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_ort_projection_zero_iterations_initial_passthrough", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ZeroIterations", |
| "notes": "Projection onto the framework's lowered add-step loop: trip count zero must leave carried state unchanged and produce no scan elements." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [123.0, -456.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [99.0, 99.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [0, 2], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_ort_projection_exit_due_to_max_iterations", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "Projection onto the framework's lowered add-step loop: two iterations advance the carried state and produce two scan values." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [2] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.0] } }, |
| "step": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [3.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [2, 1], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_trip_count_exceeds_scan_capacity", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [6] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [10.0, -10.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, -2.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 2], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_zero_trip_count_cond_true", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [5.0] } }, |
| "step": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [99.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [1], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [0, 1], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_trip_count_less_than_scan_capacity_tail_zero", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [2] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, -1.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.25, -0.5] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [5, 2], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_zero_step_preserves_lane", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [2.0, -2.0, 5.0] } }, |
| "step": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [0.0, 1.5, -2.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [3], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 3], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_scalar_trip_count_and_cond", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "ONNX Loop trip count and initial condition are scalar values. The project-lowered add-step form should accept scalar logical uint32 metadata as well as [1] tensors." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [3] } }, |
| "cond": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, -2.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.5, 3.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 2], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_bool_scalar_cond_true", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "ONNX Loop conditions are bool tensors. This lowered add-step projection verifies scalar logical bool storage enables iteration." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [2] } }, |
| "cond": { "dtype": "bool", "shape": [], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, -3.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [4.0, 0.5] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0 }, |
| "scan_output": { "dtype": "float32", "shape": [2, 2], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "lowered_bool_len1_cond_false_zero_iterations", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ZeroIterations", |
| "notes": "Length-1 logical bool false condition must prevent all iterations, leave state unchanged, and zero-fill the bounded scan output." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [5] } }, |
| "cond": { "dtype": "bool", "shape": [1], "data": { "kind": "values", "values": [0] } }, |
| "v_initial": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, -1.0, 10.0] } }, |
| "step": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [100.0, 100.0, 100.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [3], "tolerance": 0 }, |
| "scan_output": { "dtype": "float32", "shape": [4, 3], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "lowered_noncanonical_cond_true_value_two", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "ONNX only requires the loop condition to be a bool; runtimes that store it as an integer may emit any nonzero value. The lowered kernel must treat any nonzero cond (here 2) as true via cond[0] != 0u, matching the reference's !== 0 test, not a literal == 1 comparison." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [2] } }, |
| "v_initial": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, -1.0] } }, |
| "step": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.5, 2.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [2], "tolerance": 0 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 2], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "lowered_trip_count_equals_capacity_full_fill_wide_dim64", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "Realistic carried-state width (dim 64, a typical small recurrent hidden size) with trip count exactly equal to the scan capacity so every scan row is produced by an iteration and the tail-zero branch is never taken. Exercises the min(m, scanSteps) clamp at its equality boundary across many lanes." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { |
| "dtype": "float32", |
| "shape": [64], |
| "data": { |
| "kind": "values", |
| "values": [-0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4] |
| } |
| }, |
| "step": { |
| "dtype": "float32", |
| "shape": [64], |
| "data": { |
| "kind": "values", |
| "values": [-0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4] |
| } |
| } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [64], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [8, 64], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_clamped_trip_count_partial_fill_wide_dim33_unaligned", |
| "provenance": { |
| "source": "onnxruntime/test/providers/cpu/controlflow/loop_test.cc", |
| "test": "Loop.ExitDueToMaxIterations", |
| "notes": "Non-multiple-of-4 carried-state width (dim 33) combined with a trip count larger than the scan capacity. iterations = min(m, scanSteps) clamps to the capacity, the first rows accumulate, and the unaligned final lane must still be written correctly by the scalar per-lane loop with no vec4 over-read at the dim tail." |
| }, |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { |
| "dtype": "float32", |
| "shape": [33], |
| "data": { |
| "kind": "values", |
| "values": [-0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1, -0.5, 0.2, -0.2, 0.5, 0.1, -0.3, 0.4, 0.0, -0.4, 0.3, -0.1] |
| } |
| }, |
| "step": { |
| "dtype": "float32", |
| "shape": [33], |
| "data": { |
| "kind": "values", |
| "values": [-0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3, -0.1, 0.4, 0.0, -0.4, 0.1, -0.3, 0.2, -0.2, 0.3] |
| } |
| } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [33], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [6, 33], "tolerance": 0.000001 } |
| } |
| }, |
| { |
| "name": "lowered_positive_m_zero_scan_capacity_preserves_initial", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [5] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.0, -2.0, 3.5] } }, |
| "step": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [100.0, 100.0, 100.0] } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [3], "tolerance": 0 }, |
| "scan_output": { "dtype": "float32", "shape": [0, 3], "tolerance": 0 } |
| } |
| }, |
| { |
| "name": "lowered_dim_straddles_workgroup_boundary_dim258", |
| "inputs": { |
| "m": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } }, |
| "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } }, |
| "v_initial": { "dtype": "float32", "shape": [258], "data": { "kind": "constant", "value": 1.0 } }, |
| "step": { "dtype": "float32", "shape": [258], "data": { "kind": "constant", "value": 0.5 } } |
| }, |
| "outputs": { |
| "v_final": { "dtype": "float32", "shape": [258], "tolerance": 0.000001 }, |
| "scan_output": { "dtype": "float32", "shape": [3, 258], "tolerance": 0.000001 } |
| } |
| } |
| ] |
| } |
|
|