Xenova HF Staff commited on
Commit
b1ec92f
·
verified ·
1 Parent(s): 5205f7a

sync 2e7068faf55e

Browse files
README.md CHANGED
@@ -1,3 +1,74 @@
1
  ---
 
2
  license: apache-2.0
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: kernels
3
  license: apache-2.0
4
+ tags:
5
+ - kernel
6
+ - webgpu
7
+ - wgsl
8
  ---
9
+ # ai.onnx.If
10
+
11
+ `ai.onnx` · internal tensor lowering (non-standard) · reviewed against ONNX opset 25
12
+
13
+ ## Description
14
+
15
+ Support status: the standard ONNX `If` control-flow operator is not implemented because standalone kernel packages cannot carry or execute its `then_branch` and `else_branch` graph attributes. This internal lowering only selects elementwise between two pre-evaluated, equal-sized tensors from a scalar condition and must not be treated as ONNX `If`.
16
+
17
+ See the [standard ONNX `If` spec](https://onnx.ai/onnx/operators/onnx__If.html) for the contract this internal lowering does not implement.
18
+
19
+ ## Inputs
20
+
21
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
+ | --- | --- | --- | --- | --- | --- | --- |
23
+ | `cond` | `cond` | `B` | — | — | Scalar boolean condition that selects which value tensor to output. | required |
24
+ | `then_value` | `then_value` | `T` | — | — | Values to output when `cond` is true. | required |
25
+ | `else_value` | `else_value` | `T` | — | — | Values to output when `cond` is false. | required |
26
+
27
+ ## Outputs
28
+
29
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
30
+ | --- | --- | --- | --- | --- | --- | --- |
31
+ | `y` | `y` | `T` | — | — | Output tensor with the same number of elements as `then_value` and `else_value`. | required |
32
+
33
+ ## Type constraints
34
+
35
+ | Variable | Allowed dtypes |
36
+ | --- | --- |
37
+ | `T` | `float32` |
38
+ | `B` | `uint32`, `bool` |
39
+
40
+ ## Files
41
+
42
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
43
+ - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
44
+ - [`test.json`](build/webgpu/test.json) — correctness cases
45
+ - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
46
+ - [`if-select.wgsl.jinja`](build/webgpu/if-select.wgsl.jinja)
47
+
48
+ ## Use with `@huggingface/kernels`
49
+
50
+ The loader automatically allocates outputs whose metadata it can derive from the manifest contract and this call.
51
+
52
+ The explicit `outputs` entries provide shape and logical dtype metadata for the results listed below:
53
+
54
+ - `y`
55
+
56
+ Each entry either requests an optional result or supplies metadata that cannot be inferred from the inputs.
57
+
58
+ The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
59
+
60
+ Replace each `*Data` placeholder with a typed array containing the corresponding input data.
61
+
62
+ ```js
63
+ import { getKernel } from "@huggingface/kernels";
64
+
65
+ const kernel = await getKernel("webgpu-kernels/ai.onnx.If", { version: 1 });
66
+ // Explicit destinations request optional results or supply metadata that cannot be inferred.
67
+ const { y } = await kernel({
68
+ cond: { data: condData, shape: [1] },
69
+ then_value: { data: then_valueData, shape: [1] },
70
+ else_value: { data: else_valueData, shape: [1] },
71
+ }, {
72
+ outputs: { y: { shape: [1], dtype: "float32" } },
73
+ });
74
+ ```
build/webgpu/bench.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.If",
3
+ "cases": [
4
+ {
5
+ "name": "lowered_select_1m",
6
+ "preset": "smoke",
7
+ "inputs": {
8
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
9
+ "then_value": { "dtype": "float32", "shape": [1048576] },
10
+ "else_value": { "dtype": "float32", "shape": [1048576] }
11
+ },
12
+ "outputs": { "y": { "dtype": "float32", "shape": [1048576] } },
13
+ "bench": {
14
+ "metrics": [
15
+ { "type": "bandwidth", "value": "4 * (numel(shapes.cond) + numel(shapes.then_value) + numel(shapes.y))" }
16
+ ]
17
+ }
18
+ }
19
+ ]
20
+ }
build/webgpu/if-select.wgsl.jinja ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
+ {% if note == "dispatch-limit" %}
3
+ // 2D-folded flat index: gid.y carries the high bits past the
4
+ // maxComputeWorkgroupsPerDimension dispatch limit (outputs > 16.7M elements).
5
+ {% elif note == "limit" %}
6
+ // 2D-folded flat index: gid.y carries the high bits past the
7
+ // maxComputeWorkgroupsPerDimension limit.
8
+ {% elif note == "device-axis" %}
9
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
10
+ // limit; gid.y carries the high portion of the output index.
11
+ {% elif note == "vec4-limit" %}
12
+ // 2D-folded flat vec4 index: gid.y carries the high bits past the
13
+ // maxComputeWorkgroupsPerDimension limit (the dispatch caps x and spills into y).
14
+ {% elif note == "element-limit" %}
15
+ // 2D-folded flat element index: gid.y carries the high bits past the
16
+ // maxComputeWorkgroupsPerDimension limit.
17
+ {% elif note == "dispatch" %}
18
+ // 2D-folded flat index: gid.y carries the high bits past the
19
+ // maxComputeWorkgroupsPerDimension dispatch limit.
20
+ {% endif %}
21
+ {% if bound == "" %}
22
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
23
+ {%- elif guardInline %}
24
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
25
+ if ({{ name }} >= {{ bound }}) { return; }
26
+ {%- else %}
27
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
28
+ if ({{ name }} >= {{ bound }}) {
29
+ return;
30
+ }
31
+ {%- endif %}
32
+ {% endmacro %}
33
+
34
+ {{ env.wgsl.resourceDeclarations }}
35
+
36
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
37
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
38
+ {{ flat_index_2d(guardInline=true) }}
39
+ y[i] = select(else_value[i], then_value[i], cond[0] != 0u);
40
+ }
build/webgpu/manifest.json ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "domain": "ai.onnx",
3
+ "name": "If",
4
+ "conformance": "internal-lowering",
5
+ "sinceVersion": 25,
6
+ "description": "Support status: the standard ONNX `If` control-flow operator is not implemented because standalone kernel packages cannot carry or execute its `then_branch` and `else_branch` graph attributes. This internal lowering only selects elementwise between two pre-evaluated, equal-sized tensors from a scalar condition and must not be treated as ONNX `If`.",
7
+ "inputs": [
8
+ {
9
+ "role": "cond",
10
+ "dtype": "B",
11
+ "description": "Scalar boolean condition that selects which value tensor to output."
12
+ },
13
+ { "role": "then_value", "dtype": "T", "description": "Values to output when `cond` is true." },
14
+ { "role": "else_value", "dtype": "T", "description": "Values to output when `cond` is false." }
15
+ ],
16
+ "outputs": [
17
+ {
18
+ "role": "y",
19
+ "dtype": "T",
20
+ "description": "Output tensor with the same number of elements as `then_value` and `else_value`."
21
+ }
22
+ ],
23
+ "typeConstraints": { "T": ["float32"], "B": ["uint32", "bool"] },
24
+ "args": {
25
+ "cond": { "kind": "tensor", "semantic": "cond", "role": "input" },
26
+ "then_value": { "kind": "tensor", "semantic": "then_value", "role": "input" },
27
+ "else_value": { "kind": "tensor", "semantic": "else_value", "role": "input" },
28
+ "y": { "kind": "tensor", "semantic": "y", "role": "output" }
29
+ },
30
+ "tunables": { "WORKGROUP_SIZE": 256 },
31
+ "variants": [
32
+ {
33
+ "id": "lowered_select",
34
+ "when": ["ranks.cond <= 1", "numel(shapes.cond) == 1", "numel(shapes.then_value) == numel(shapes.y)", "numel(shapes.else_value) == numel(shapes.y)"],
35
+ "passes": [
36
+ {
37
+ "id": "main",
38
+ "name": "If",
39
+ "shader": "if-select.wgsl.jinja",
40
+ "bindings": [
41
+ {
42
+ "name": "cond",
43
+ "arg": "cond",
44
+ "semantic": "cond",
45
+ "buffer": { "type": "read-only-storage" },
46
+ "elementType": "u32",
47
+ "length": 1
48
+ },
49
+ {
50
+ "name": "then_value",
51
+ "arg": "then_value",
52
+ "semantic": "then_value",
53
+ "buffer": { "type": "read-only-storage" },
54
+ "elementType": "f32"
55
+ },
56
+ {
57
+ "name": "else_value",
58
+ "arg": "else_value",
59
+ "semantic": "else_value",
60
+ "buffer": { "type": "read-only-storage" },
61
+ "elementType": "f32"
62
+ },
63
+ { "name": "y", "arg": "y", "semantic": "y", "buffer": { "type": "storage" }, "elementType": "f32" },
64
+ {
65
+ "name": "params",
66
+ "semantic": "kernel.params",
67
+ "buffer": { "type": "uniform" },
68
+ "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.y)" }] }
69
+ }
70
+ ],
71
+ "dispatch": { "threads": "numel(shapes.y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
72
+ }
73
+ ]
74
+ }
75
+ ]
76
+ }
build/webgpu/metadata.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ai.onnx.If",
3
+ "id": "_ai_onnx_if_webgpu_2b93a6b",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "backend": { "type": "webgpu" },
7
+ "digest": {
8
+ "algorithm": "sha256",
9
+ "files": {
10
+ "bench.json": "aVzy6O2BXjbtp7QD6jSgMGQnCFr9rv3ErzC9HuwA6gE=",
11
+ "if-select.wgsl.jinja": "SOCO3HJ0GVfXYEOn7wNTEDBq94rDoQ5sGuijBo/4u6Y=",
12
+ "manifest.json": "qnXbI/F6Tz6YY42S8aJWiA5scMh+fR/ZkPTGfwzYYcc=",
13
+ "test.json": "wPMNj7icFakVJ6lHXUZxozdTSnpyTakK1is0VuwCvzE="
14
+ }
15
+ },
16
+ "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
17
+ "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.If" }
18
+ }
build/webgpu/test.json ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.If",
3
+ "cases": [
4
+ {
5
+ "name": "lowered_dispatch_cliff_select_then",
6
+ "inputs": {
7
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
8
+ "then_value": { "dtype": "float32", "shape": [16777216], "data": { "kind": "constant", "value": 1.5 } },
9
+ "else_value": { "dtype": "float32", "shape": [16777216], "data": { "kind": "constant", "value": -2.5 } }
10
+ },
11
+ "outputs": { "y": { "dtype": "float32", "shape": [16777216], "tolerance": 0 } }
12
+ },
13
+ {
14
+ "name": "lowered_select_then",
15
+ "inputs": {
16
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
17
+ "then_value": {
18
+ "dtype": "float32",
19
+ "shape": [2, 2],
20
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] }
21
+ },
22
+ "else_value": {
23
+ "dtype": "float32",
24
+ "shape": [2, 2],
25
+ "data": { "kind": "values", "values": [-1.0, -2.0, -3.0, -4.0] }
26
+ }
27
+ },
28
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2] } }
29
+ },
30
+ {
31
+ "name": "lowered_select_else",
32
+ "inputs": {
33
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } },
34
+ "then_value": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [10.0, 20.0, 30.0] } },
35
+ "else_value": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [4.0, 5.0, 6.0] } }
36
+ },
37
+ "outputs": { "y": { "dtype": "float32", "shape": [3] } }
38
+ },
39
+ {
40
+ "name": "lowered_ort_projection_outer_scope_add_then",
41
+ "provenance": {
42
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
43
+ "test": "If.ShapeInMainGraph_NoShapeInSubgraph_True",
44
+ "notes": "Projection onto the framework's lowered select variant: ORT's then branch computes split_out_0 + if_graph_input_0 = 2."
45
+ },
46
+ "inputs": {
47
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
48
+ "then_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } },
49
+ "else_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [11.0] } }
50
+ },
51
+ "outputs": { "y": { "dtype": "float32", "shape": [1], "tolerance": 0 } }
52
+ },
53
+ {
54
+ "name": "lowered_ort_projection_outer_scope_add_else",
55
+ "provenance": {
56
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
57
+ "test": "If.ShapeInMainGraph_NoShapeInSubgraph_False",
58
+ "notes": "Projection onto the framework's lowered select variant: ORT's else branch computes split_out_1 + if_graph_input_0 = 11."
59
+ },
60
+ "inputs": {
61
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } },
62
+ "then_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [2.0] } },
63
+ "else_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [11.0] } }
64
+ },
65
+ "outputs": { "y": { "dtype": "float32", "shape": [1], "tolerance": 0 } }
66
+ },
67
+ {
68
+ "name": "lowered_ort_projection_constant_then_branch",
69
+ "provenance": {
70
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
71
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ThenBranchExecution",
72
+ "notes": "Projection onto the framework's lowered select variant: branch subgraphs are represented by precomputed branch tensors."
73
+ },
74
+ "inputs": {
75
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
76
+ "then_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [10.0] } },
77
+ "else_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1000.0] } }
78
+ },
79
+ "outputs": { "y": { "dtype": "float32", "shape": [1] } }
80
+ },
81
+ {
82
+ "name": "lowered_ort_projection_constant_else_branch",
83
+ "provenance": {
84
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
85
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ElseBranchExecution",
86
+ "notes": "Projection onto the framework's lowered select variant: branch subgraphs are represented by precomputed branch tensors."
87
+ },
88
+ "inputs": {
89
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } },
90
+ "then_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [10.0] } },
91
+ "else_value": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [1000.0] } }
92
+ },
93
+ "outputs": { "y": { "dtype": "float32", "shape": [1] } }
94
+ },
95
+ {
96
+ "name": "lowered_ort_projection_different_branch_shapes_then",
97
+ "provenance": {
98
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
99
+ "test": "If.Opset11ThenAndElseBranchesProduceDifferentOutputShapes",
100
+ "notes": "Projection onto the framework's lowered select variant: branch tensors use different ranks with equal storage size, and the selected then branch fixes the output shape."
101
+ },
102
+ "inputs": {
103
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
104
+ "then_value": {
105
+ "dtype": "float32",
106
+ "shape": [2, 2],
107
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] }
108
+ },
109
+ "else_value": {
110
+ "dtype": "float32",
111
+ "shape": [4],
112
+ "data": { "kind": "values", "values": [-1.0, -2.0, -3.0, -4.0] }
113
+ }
114
+ },
115
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2] } }
116
+ },
117
+ {
118
+ "name": "lowered_ort_projection_different_branch_shapes_else",
119
+ "provenance": {
120
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
121
+ "test": "If.Opset11ThenAndElseBranchesProduceDifferentOutputShapes",
122
+ "notes": "Projection onto the framework's lowered select variant: branch tensors use different ranks with equal storage size, and the selected else branch fixes the output shape."
123
+ },
124
+ "inputs": {
125
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } },
126
+ "then_value": {
127
+ "dtype": "float32",
128
+ "shape": [2, 2],
129
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] }
130
+ },
131
+ "else_value": {
132
+ "dtype": "float32",
133
+ "shape": [4],
134
+ "data": { "kind": "values", "values": [-1.0, -2.0, -3.0, -4.0] }
135
+ }
136
+ },
137
+ "outputs": { "y": { "dtype": "float32", "shape": [4] } }
138
+ },
139
+ {
140
+ "name": "lowered_select_then_scalar",
141
+ "inputs": {
142
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
143
+ "then_value": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [42.0] } },
144
+ "else_value": { "dtype": "float32", "shape": [], "data": { "kind": "values", "values": [-42.0] } }
145
+ },
146
+ "outputs": { "y": { "dtype": "float32", "shape": [] } }
147
+ },
148
+ {
149
+ "name": "lowered_scalar_cond_then",
150
+ "provenance": {
151
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
152
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ThenBranchExecution",
153
+ "notes": "ONNX If condition is a scalar bool. The project-lowered select form should accept scalar logical uint32 conditions as well as [1] conditions."
154
+ },
155
+ "inputs": {
156
+ "cond": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [1] } },
157
+ "then_value": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [9.0, -3.0] } },
158
+ "else_value": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [4.0, 5.0] } }
159
+ },
160
+ "outputs": { "y": { "dtype": "float32", "shape": [2], "tolerance": 0 } }
161
+ },
162
+ {
163
+ "name": "lowered_scalar_cond_else",
164
+ "provenance": {
165
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
166
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ElseBranchExecution",
167
+ "notes": "ONNX If condition is a scalar bool. This exercises the false branch with scalar logical uint32 condition storage."
168
+ },
169
+ "inputs": {
170
+ "cond": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [0] } },
171
+ "then_value": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [9.0, -3.0] } },
172
+ "else_value": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [4.0, 5.0] } }
173
+ },
174
+ "outputs": { "y": { "dtype": "float32", "shape": [2], "tolerance": 0 } }
175
+ },
176
+ {
177
+ "name": "lowered_bool_scalar_cond_then",
178
+ "provenance": {
179
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
180
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ThenBranchExecution",
181
+ "notes": "ONNX If conditions are bool tensors. This lowered projection verifies scalar logical bool storage selects the then branch."
182
+ },
183
+ "inputs": {
184
+ "cond": { "dtype": "bool", "shape": [], "data": { "kind": "values", "values": [1] } },
185
+ "then_value": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [1.25, -2.5, 3.75] } },
186
+ "else_value": {
187
+ "dtype": "float32",
188
+ "shape": [3],
189
+ "data": { "kind": "values", "values": [-10.0, -20.0, -30.0] }
190
+ }
191
+ },
192
+ "outputs": { "y": { "dtype": "float32", "shape": [3], "tolerance": 0 } }
193
+ },
194
+ {
195
+ "name": "lowered_bool_len1_cond_else",
196
+ "provenance": {
197
+ "source": "onnxruntime/test/providers/cpu/controlflow/if_test.cc",
198
+ "test": "If.ConditionalBranchesOnlyContainConstantNodes_ElseBranchExecution",
199
+ "notes": "Length-1 logical bool condition companion for the lowered select form; false must select the else tensor exactly."
200
+ },
201
+ "inputs": {
202
+ "cond": { "dtype": "bool", "shape": [1], "data": { "kind": "values", "values": [0] } },
203
+ "then_value": {
204
+ "dtype": "float32",
205
+ "shape": [2, 2],
206
+ "data": { "kind": "values", "values": [9.0, 8.0, 7.0, 6.0] }
207
+ },
208
+ "else_value": {
209
+ "dtype": "float32",
210
+ "shape": [2, 2],
211
+ "data": { "kind": "values", "values": [-1.0, -2.0, -3.0, -4.0] }
212
+ }
213
+ },
214
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2], "tolerance": 0 } }
215
+ },
216
+ {
217
+ "name": "lowered_select_else_zero_sized",
218
+ "inputs": {
219
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [0] } },
220
+ "then_value": { "dtype": "float32", "shape": [0], "data": { "kind": "values", "values": [] } },
221
+ "else_value": { "dtype": "float32", "shape": [0], "data": { "kind": "values", "values": [] } }
222
+ },
223
+ "outputs": { "y": { "dtype": "float32", "shape": [0] } }
224
+ },
225
+ {
226
+ "name": "lowered_noncanonical_cond_uint32_42_selects_then",
227
+ "inputs": {
228
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [42] } },
229
+ "then_value": {
230
+ "dtype": "float32",
231
+ "shape": [4],
232
+ "data": { "kind": "values", "values": [3.0, 1.5, -2.5, 0.25] }
233
+ },
234
+ "else_value": {
235
+ "dtype": "float32",
236
+ "shape": [4],
237
+ "data": { "kind": "values", "values": [-9.0, 7.0, 4.25, -1.0] }
238
+ }
239
+ },
240
+ "outputs": { "y": { "dtype": "float32", "shape": [4], "tolerance": 0 } }
241
+ },
242
+ {
243
+ "name": "lowered_noncanonical_cond_uint32_max_selects_then",
244
+ "inputs": {
245
+ "cond": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4294967295] } },
246
+ "then_value": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [10.0, -5.0, 0.5] } },
247
+ "else_value": { "dtype": "float32", "shape": [3], "data": { "kind": "values", "values": [0.0, 0.0, 0.0] } }
248
+ },
249
+ "outputs": { "y": { "dtype": "float32", "shape": [3], "tolerance": 0 } }
250
+ }
251
+ ]
252
+ }