1 /*
2 * Copyright © 2023 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <gtest/gtest.h>
25
26 #include "helpers.h"
27
28 class ControlFlow : public spirv_test {};
29
TEST_F(ControlFlow,Basic)30 TEST_F(ControlFlow, Basic)
31 {
32 /*
33 ; Extra arguments for spirv-as --target-env spv1.3
34
35 OpCapability Shader
36 %1 = OpExtInstImport "GLSL.std.450"
37 OpMemoryModel Logical GLSL450
38 OpEntryPoint GLCompute %4 "main"
39 OpExecutionMode %4 LocalSize 1 1 1
40 OpMemberDecorate %_struct_7 0 Offset 0
41 OpDecorate %_struct_7 BufferBlock
42 OpDecorate %9 DescriptorSet 0
43 OpDecorate %9 Binding 0
44 %void = OpTypeVoid
45 %3 = OpTypeFunction %void
46 %uint = OpTypeInt 32 0
47 %_struct_7 = OpTypeStruct %uint
48 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
49 %9 = OpVariable %_ptr_Uniform__struct_7 Uniform
50 %int = OpTypeInt 32 1
51 %int_0 = OpConstant %int 0
52 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
53 %4 = OpFunction %void None %3
54 %5 = OpLabel
55 %13 = OpAccessChain %_ptr_Uniform_uint %9 %int_0
56 %14 = OpLoad %uint %13 Volatile
57 OpStore %13 %14
58 OpReturn
59 OpFunctionEnd
60 */
61 static const uint32_t words[] = {
62 0x07230203, 0x00010300, 0x00070000, 0x0000000f, 0x00000000, 0x00020011,
63 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
64 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005,
65 0x00000002, 0x6e69616d, 0x00000000, 0x00060010, 0x00000002, 0x00000011,
66 0x00000001, 0x00000001, 0x00000001, 0x00050048, 0x00000003, 0x00000000,
67 0x00000023, 0x00000000, 0x00030047, 0x00000003, 0x00000003, 0x00040047,
68 0x00000004, 0x00000022, 0x00000000, 0x00040047, 0x00000004, 0x00000021,
69 0x00000000, 0x00020013, 0x00000005, 0x00030021, 0x00000006, 0x00000005,
70 0x00040015, 0x00000007, 0x00000020, 0x00000000, 0x0003001e, 0x00000003,
71 0x00000007, 0x00040020, 0x00000008, 0x00000002, 0x00000003, 0x0004003b,
72 0x00000008, 0x00000004, 0x00000002, 0x00040015, 0x00000009, 0x00000020,
73 0x00000001, 0x0004002b, 0x00000009, 0x0000000a, 0x00000000, 0x00040020,
74 0x0000000b, 0x00000002, 0x00000007, 0x00050036, 0x00000005, 0x00000002,
75 0x00000000, 0x00000006, 0x000200f8, 0x0000000c, 0x00050041, 0x0000000b,
76 0x0000000d, 0x00000004, 0x0000000a, 0x0005003d, 0x00000007, 0x0000000e,
77 0x0000000d, 0x00000001, 0x0003003e, 0x0000000d, 0x0000000e, 0x000100fd,
78 0x00010038,
79 };
80 get_nir(sizeof(words) / sizeof(words[0]), words);
81 ASSERT_TRUE(shader);
82 }
83
TEST_F(ControlFlow,BreakIfConditionWithLoop)84 TEST_F(ControlFlow, BreakIfConditionWithLoop)
85 {
86 // From https://gitlab.khronos.org/spirv/SPIR-V/-/issues/659.
87
88 /*
89 ; Extra arguments for spirv-as --target-env spv1.5
90
91 OpCapability Shader
92 OpMemoryModel Logical Simple
93 OpEntryPoint GLCompute %100 "main"
94 OpExecutionMode %100 LocalSize 1 1 1
95 %void = OpTypeVoid
96 %8 = OpTypeFunction %void
97 %bool = OpTypeBool
98 %cond = OpConstantNull %bool ; a boring "false".
99
100 %100 = OpFunction %void None %8
101 %10 = OpLabel
102 OpBranch %20
103
104 %20 = OpLabel
105 OpLoopMerge %90 %80 None
106 OpBranch %30
107
108 %30 = OpLabel
109 OpSelectionMerge %50 None
110 OpBranchConditional %cond %90 %50
111
112 %50 = OpLabel
113 OpBranch %80
114
115 %80 = OpLabel ; continue target for loop
116 OpBranch %20
117
118 %90 = OpLabel ; merge for loop
119 OpReturn
120 OpFunctionEnd
121 */
122 static const uint32_t words[] = {
123 0x07230203, 0x00010500, 0x00070000, 0x0000000c, 0x00000000, 0x00020011,
124 0x00000001, 0x0003000e, 0x00000000, 0x00000000, 0x0005000f, 0x00000005,
125 0x00000001, 0x6e69616d, 0x00000000, 0x00060010, 0x00000001, 0x00000011,
126 0x00000001, 0x00000001, 0x00000001, 0x00020013, 0x00000002, 0x00030021,
127 0x00000003, 0x00000002, 0x00020014, 0x00000004, 0x0003002e, 0x00000004,
128 0x00000005, 0x00050036, 0x00000002, 0x00000001, 0x00000000, 0x00000003,
129 0x000200f8, 0x00000006, 0x000200f9, 0x00000007, 0x000200f8, 0x00000007,
130 0x000400f6, 0x00000008, 0x00000009, 0x00000000, 0x000200f9, 0x0000000a,
131 0x000200f8, 0x0000000a, 0x000300f7, 0x0000000b, 0x00000000, 0x000400fa,
132 0x00000005, 0x00000008, 0x0000000b, 0x000200f8, 0x0000000b, 0x000200f9,
133 0x00000009, 0x000200f8, 0x00000009, 0x000200f9, 0x00000007, 0x000200f8,
134 0x00000008, 0x000100fd, 0x00010038,
135 };
136 get_nir(sizeof(words) / sizeof(words[0]), words);
137 ASSERT_TRUE(shader);
138 }
139
TEST_F(ControlFlow,EarlyMerge)140 TEST_F(ControlFlow, EarlyMerge)
141 {
142 // From https://gitlab.khronos.org/spirv/SPIR-V/-/issues/640.
143
144 /*
145 ; Extra arguments for spirv-as --target-env spv1.0
146
147 OpCapability Shader
148 %1 = OpExtInstImport "GLSL.std.450"
149 OpMemoryModel Logical GLSL450
150 OpEntryPoint Fragment %main "main" %colour
151 OpExecutionMode %main OriginUpperLeft
152 OpSource GLSL 460
153 OpName %main "main"
154 OpName %colour "colour"
155 OpDecorate %colour Location 0
156 %void = OpTypeVoid
157 %3 = OpTypeFunction %void
158 %bool = OpTypeBool
159 %false = OpConstantFalse %bool
160 %true = OpConstantTrue %bool
161 %float = OpTypeFloat 32
162 %vec4 = OpTypeVector %float 4
163 %pvec4 = OpTypePointer Output %vec4
164 %colour = OpVariable %pvec4 Output
165 %f0 = OpConstant %float 0.0
166 %f1 = OpConstant %float 1.0
167 %13 = OpConstantComposite %vec4 %f0 %f1 %f0 %f1
168 %main = OpFunction %void None %3
169 %B5 = OpLabel
170 OpSelectionMerge %B8 None
171 OpBranchConditional %true %B6 %B7
172 %B6 = OpLabel
173 OpBranch %B7
174 %B7 = OpLabel
175 OpBranch %B8
176 %B8 = OpLabel
177 OpStore %colour %13
178 OpReturn
179 OpFunctionEnd
180 */
181 static const uint32_t words[] = {
182 0x07230203, 0x00010000, 0x00070000, 0x00000013, 0x00000000, 0x00020011,
183 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
184 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0006000f, 0x00000004,
185 0x00000002, 0x6e69616d, 0x00000000, 0x00000003, 0x00030010, 0x00000002,
186 0x00000007, 0x00030003, 0x00000002, 0x000001cc, 0x00040005, 0x00000002,
187 0x6e69616d, 0x00000000, 0x00040005, 0x00000003, 0x6f6c6f63, 0x00007275,
188 0x00040047, 0x00000003, 0x0000001e, 0x00000000, 0x00020013, 0x00000004,
189 0x00030021, 0x00000005, 0x00000004, 0x00020014, 0x00000006, 0x0003002a,
190 0x00000006, 0x00000007, 0x00030029, 0x00000006, 0x00000008, 0x00030016,
191 0x00000009, 0x00000020, 0x00040017, 0x0000000a, 0x00000009, 0x00000004,
192 0x00040020, 0x0000000b, 0x00000003, 0x0000000a, 0x0004003b, 0x0000000b,
193 0x00000003, 0x00000003, 0x0004002b, 0x00000009, 0x0000000c, 0x00000000,
194 0x0004002b, 0x00000009, 0x0000000d, 0x3f800000, 0x0007002c, 0x0000000a,
195 0x0000000e, 0x0000000c, 0x0000000d, 0x0000000c, 0x0000000d, 0x00050036,
196 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x000200f8, 0x0000000f,
197 0x000300f7, 0x00000010, 0x00000000, 0x000400fa, 0x00000008, 0x00000011,
198 0x00000012, 0x000200f8, 0x00000011, 0x000200f9, 0x00000012, 0x000200f8,
199 0x00000012, 0x000200f9, 0x00000010, 0x000200f8, 0x00000010, 0x0003003e,
200 0x00000003, 0x0000000e, 0x000100fd, 0x00010038,
201 };
202 get_nir(sizeof(words) / sizeof(words[0]), words, MESA_SHADER_FRAGMENT);
203 ASSERT_TRUE(shader);
204 }
205
TEST_F(ControlFlow,SingleBlockLoop)206 TEST_F(ControlFlow, SingleBlockLoop)
207 {
208 /*
209 OpCapability Shader
210 OpMemoryModel Logical Simple
211 OpEntryPoint GLCompute %100 "main"
212 OpExecutionMode %100 LocalSize 1 1 1
213 %void = OpTypeVoid
214 %8 = OpTypeFunction %void
215 %bool = OpTypeBool
216 %cond = OpConstantNull %bool
217
218 %100 = OpFunction %void None %8
219 %10 = OpLabel
220 OpBranch %20
221
222 %20 = OpLabel
223 OpLoopMerge %30 %20 None
224 OpBranchConditional %cond %20 %30
225
226 %30 = OpLabel
227 OpReturn
228 OpFunctionEnd
229 */
230 static const uint32_t words[] = {
231 0x07230203, 0x00010600, 0x00070000, 0x00000009, 0x00000000, 0x00020011,
232 0x00000001, 0x0003000e, 0x00000000, 0x00000000, 0x0005000f, 0x00000005,
233 0x00000001, 0x6e69616d, 0x00000000, 0x00060010, 0x00000001, 0x00000011,
234 0x00000001, 0x00000001, 0x00000001, 0x00020013, 0x00000002, 0x00030021,
235 0x00000003, 0x00000002, 0x00020014, 0x00000004, 0x0003002e, 0x00000004,
236 0x00000005, 0x00050036, 0x00000002, 0x00000001, 0x00000000, 0x00000003,
237 0x000200f8, 0x00000006, 0x000200f9, 0x00000007, 0x000200f8, 0x00000007,
238 0x000400f6, 0x00000008, 0x00000007, 0x00000000, 0x000400fa, 0x00000005,
239 0x00000007, 0x00000008, 0x000200f8, 0x00000008, 0x000100fd, 0x00010038,
240 };
241 get_nir(ARRAY_SIZE(words), words, MESA_SHADER_COMPUTE);
242 ASSERT_TRUE(shader);
243 }