1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16 #include <unordered_set>
17
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20
21 namespace spvtools {
22 namespace opt {
23 namespace {
24
25 using Workaround1209Test = PassTest<::testing::Test>;
26
TEST_F(Workaround1209Test,RemoveOpUnreachableInLoop)27 TEST_F(Workaround1209Test, RemoveOpUnreachableInLoop) {
28 const std::string text = R"(
29 OpCapability Shader
30 %1 = OpExtInstImport "GLSL.std.450"
31 OpMemoryModel Logical GLSL450
32 OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_
33 OpSource GLSL 400
34 OpSourceExtension "GL_ARB_separate_shader_objects"
35 OpSourceExtension "GL_ARB_shading_language_420pack"
36 OpName %main "main"
37 OpName %texcoord "texcoord"
38 OpName %buf "buf"
39 OpMemberName %buf 0 "MVP"
40 OpMemberName %buf 1 "position"
41 OpMemberName %buf 2 "attr"
42 OpName %ubuf "ubuf"
43 OpName %gl_VertexIndex "gl_VertexIndex"
44 OpName %gl_PerVertex "gl_PerVertex"
45 OpMemberName %gl_PerVertex 0 "gl_Position"
46 OpName %_ ""
47 OpDecorate %texcoord Location 0
48 OpDecorate %_arr_v4float_uint_72 ArrayStride 16
49 OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16
50 OpMemberDecorate %buf 0 ColMajor
51 OpMemberDecorate %buf 0 Offset 0
52 OpMemberDecorate %buf 0 MatrixStride 16
53 OpMemberDecorate %buf 1 Offset 64
54 OpMemberDecorate %buf 2 Offset 1216
55 OpDecorate %buf Block
56 OpDecorate %ubuf DescriptorSet 0
57 OpDecorate %ubuf Binding 0
58 OpDecorate %gl_VertexIndex BuiltIn VertexIndex
59 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
60 OpDecorate %gl_PerVertex Block
61 %void = OpTypeVoid
62 %12 = OpTypeFunction %void
63 %float = OpTypeFloat 32
64 %v4float = OpTypeVector %float 4
65 %_ptr_Output_v4float = OpTypePointer Output %v4float
66 %texcoord = OpVariable %_ptr_Output_v4float Output
67 %mat4v4float = OpTypeMatrix %v4float 4
68 %uint = OpTypeInt 32 0
69 %uint_72 = OpConstant %uint 72
70 %_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72
71 %_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72
72 %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0
73 %_ptr_Uniform_buf = OpTypePointer Uniform %buf
74 %ubuf = OpVariable %_ptr_Uniform_buf Uniform
75 %int = OpTypeInt 32 1
76 %int_2 = OpConstant %int 2
77 %_ptr_Input_int = OpTypePointer Input %int
78 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
79 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
80 %gl_PerVertex = OpTypeStruct %v4float
81 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
82 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
83 %int_0 = OpConstant %int 0
84 %int_1 = OpConstant %int 1
85 %float_1 = OpConstant %float 1
86 %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
87 %main = OpFunction %void None %12
88 %29 = OpLabel
89 OpBranch %30
90 %30 = OpLabel
91 ; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]]
92 OpLoopMerge %31 %32 None
93 OpBranch %33
94 %33 = OpLabel
95 ; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]]
96 OpSelectionMerge %34 None
97 OpSwitch %int_1 %35
98 %35 = OpLabel
99 %36 = OpLoad %int %gl_VertexIndex
100 %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36
101 %38 = OpLoad %v4float %37
102 OpStore %texcoord %38
103 %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0
104 OpStore %39 %28
105 OpBranch %31
106 ; CHECK: [[sel_merge]] = OpLabel
107 %34 = OpLabel
108 ; CHECK-NEXT: OpBranch [[merge]]
109 OpUnreachable
110 %32 = OpLabel
111 OpBranch %30
112 %31 = OpLabel
113 OpReturn
114 OpFunctionEnd)";
115
116 SinglePassRunAndMatch<Workaround1209>(text, false);
117 }
118
TEST_F(Workaround1209Test,RemoveOpUnreachableInNestedLoop)119 TEST_F(Workaround1209Test, RemoveOpUnreachableInNestedLoop) {
120 const std::string text = R"(
121 OpCapability Shader
122 %1 = OpExtInstImport "GLSL.std.450"
123 OpMemoryModel Logical GLSL450
124 OpEntryPoint Vertex %2 "main" %3 %4 %5
125 OpSource GLSL 400
126 OpSourceExtension "GL_ARB_separate_shader_objects"
127 OpSourceExtension "GL_ARB_shading_language_420pack"
128 OpName %2 "main"
129 OpName %3 "texcoord"
130 OpName %6 "buf"
131 OpMemberName %6 0 "MVP"
132 OpMemberName %6 1 "position"
133 OpMemberName %6 2 "attr"
134 OpName %7 "ubuf"
135 OpName %4 "gl_VertexIndex"
136 OpName %8 "gl_PerVertex"
137 OpMemberName %8 0 "gl_Position"
138 OpName %5 ""
139 OpDecorate %3 Location 0
140 OpDecorate %9 ArrayStride 16
141 OpDecorate %10 ArrayStride 16
142 OpMemberDecorate %6 0 ColMajor
143 OpMemberDecorate %6 0 Offset 0
144 OpMemberDecorate %6 0 MatrixStride 16
145 OpMemberDecorate %6 1 Offset 64
146 OpMemberDecorate %6 2 Offset 1216
147 OpDecorate %6 Block
148 OpDecorate %7 DescriptorSet 0
149 OpDecorate %7 Binding 0
150 OpDecorate %4 BuiltIn VertexIndex
151 OpMemberDecorate %8 0 BuiltIn Position
152 OpDecorate %8 Block
153 %11 = OpTypeVoid
154 %12 = OpTypeFunction %11
155 %13 = OpTypeFloat 32
156 %14 = OpTypeVector %13 4
157 %15 = OpTypePointer Output %14
158 %3 = OpVariable %15 Output
159 %16 = OpTypeMatrix %14 4
160 %17 = OpTypeInt 32 0
161 %18 = OpConstant %17 72
162 %9 = OpTypeArray %14 %18
163 %10 = OpTypeArray %14 %18
164 %6 = OpTypeStruct %16 %9 %10
165 %19 = OpTypePointer Uniform %6
166 %7 = OpVariable %19 Uniform
167 %20 = OpTypeInt 32 1
168 %21 = OpConstant %20 2
169 %22 = OpTypePointer Input %20
170 %4 = OpVariable %22 Input
171 %23 = OpTypePointer Uniform %14
172 %8 = OpTypeStruct %14
173 %24 = OpTypePointer Output %8
174 %5 = OpVariable %24 Output
175 %25 = OpConstant %20 0
176 %26 = OpConstant %20 1
177 %27 = OpConstant %13 1
178 %28 = OpConstantComposite %14 %27 %27 %27 %27
179 %2 = OpFunction %11 None %12
180 %29 = OpLabel
181 OpBranch %31
182 %31 = OpLabel
183 ; CHECK: OpLoopMerge
184 OpLoopMerge %32 %33 None
185 OpBranch %30
186 %30 = OpLabel
187 ; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]]
188 OpLoopMerge %34 %35 None
189 OpBranch %36
190 %36 = OpLabel
191 ; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]]
192 OpSelectionMerge %37 None
193 OpSwitch %26 %38
194 %38 = OpLabel
195 %39 = OpLoad %20 %4
196 %40 = OpAccessChain %23 %7 %21 %39
197 %41 = OpLoad %14 %40
198 OpStore %3 %41
199 %42 = OpAccessChain %15 %5 %25
200 OpStore %42 %28
201 OpBranch %34
202 ; CHECK: [[sel_merge]] = OpLabel
203 %37 = OpLabel
204 ; CHECK-NEXT: OpBranch [[merge]]
205 OpUnreachable
206 %35 = OpLabel
207 OpBranch %30
208 %34 = OpLabel
209 OpBranch %32
210 %33 = OpLabel
211 OpBranch %31
212 %32 = OpLabel
213 OpReturn
214 OpFunctionEnd)";
215
216 SinglePassRunAndMatch<Workaround1209>(text, false);
217 }
218
TEST_F(Workaround1209Test,RemoveOpUnreachableInAdjacentLoops)219 TEST_F(Workaround1209Test, RemoveOpUnreachableInAdjacentLoops) {
220 const std::string text = R"(
221 OpCapability Shader
222 %1 = OpExtInstImport "GLSL.std.450"
223 OpMemoryModel Logical GLSL450
224 OpEntryPoint Vertex %2 "main" %3 %4 %5
225 OpSource GLSL 400
226 OpSourceExtension "GL_ARB_separate_shader_objects"
227 OpSourceExtension "GL_ARB_shading_language_420pack"
228 OpName %2 "main"
229 OpName %3 "texcoord"
230 OpName %6 "buf"
231 OpMemberName %6 0 "MVP"
232 OpMemberName %6 1 "position"
233 OpMemberName %6 2 "attr"
234 OpName %7 "ubuf"
235 OpName %4 "gl_VertexIndex"
236 OpName %8 "gl_PerVertex"
237 OpMemberName %8 0 "gl_Position"
238 OpName %5 ""
239 OpDecorate %3 Location 0
240 OpDecorate %9 ArrayStride 16
241 OpDecorate %10 ArrayStride 16
242 OpMemberDecorate %6 0 ColMajor
243 OpMemberDecorate %6 0 Offset 0
244 OpMemberDecorate %6 0 MatrixStride 16
245 OpMemberDecorate %6 1 Offset 64
246 OpMemberDecorate %6 2 Offset 1216
247 OpDecorate %6 Block
248 OpDecorate %7 DescriptorSet 0
249 OpDecorate %7 Binding 0
250 OpDecorate %4 BuiltIn VertexIndex
251 OpMemberDecorate %8 0 BuiltIn Position
252 OpDecorate %8 Block
253 %11 = OpTypeVoid
254 %12 = OpTypeFunction %11
255 %13 = OpTypeFloat 32
256 %14 = OpTypeVector %13 4
257 %15 = OpTypePointer Output %14
258 %3 = OpVariable %15 Output
259 %16 = OpTypeMatrix %14 4
260 %17 = OpTypeInt 32 0
261 %18 = OpConstant %17 72
262 %9 = OpTypeArray %14 %18
263 %10 = OpTypeArray %14 %18
264 %6 = OpTypeStruct %16 %9 %10
265 %19 = OpTypePointer Uniform %6
266 %7 = OpVariable %19 Uniform
267 %20 = OpTypeInt 32 1
268 %21 = OpConstant %20 2
269 %22 = OpTypePointer Input %20
270 %4 = OpVariable %22 Input
271 %23 = OpTypePointer Uniform %14
272 %8 = OpTypeStruct %14
273 %24 = OpTypePointer Output %8
274 %5 = OpVariable %24 Output
275 %25 = OpConstant %20 0
276 %26 = OpConstant %20 1
277 %27 = OpConstant %13 1
278 %28 = OpConstantComposite %14 %27 %27 %27 %27
279 %2 = OpFunction %11 None %12
280 %29 = OpLabel
281 OpBranch %30
282 %30 = OpLabel
283 ; CHECK: OpLoopMerge [[merge1:%[a-zA-Z_\d]+]]
284 OpLoopMerge %31 %32 None
285 OpBranch %33
286 %33 = OpLabel
287 ; CHECK: OpSelectionMerge [[sel_merge1:%[a-zA-Z_\d]+]]
288 OpSelectionMerge %34 None
289 OpSwitch %26 %35
290 %35 = OpLabel
291 %36 = OpLoad %20 %4
292 %37 = OpAccessChain %23 %7 %21 %36
293 %38 = OpLoad %14 %37
294 OpStore %3 %38
295 %39 = OpAccessChain %15 %5 %25
296 OpStore %39 %28
297 OpBranch %31
298 ; CHECK: [[sel_merge1]] = OpLabel
299 %34 = OpLabel
300 ; CHECK-NEXT: OpBranch [[merge1]]
301 OpUnreachable
302 %32 = OpLabel
303 OpBranch %30
304 %31 = OpLabel
305 ; CHECK: OpLoopMerge [[merge2:%[a-zA-Z_\d]+]]
306 OpLoopMerge %40 %41 None
307 OpBranch %42
308 %42 = OpLabel
309 ; CHECK: OpSelectionMerge [[sel_merge2:%[a-zA-Z_\d]+]]
310 OpSelectionMerge %43 None
311 OpSwitch %26 %44
312 %44 = OpLabel
313 %45 = OpLoad %20 %4
314 %46 = OpAccessChain %23 %7 %21 %45
315 %47 = OpLoad %14 %46
316 OpStore %3 %47
317 %48 = OpAccessChain %15 %5 %25
318 OpStore %48 %28
319 OpBranch %40
320 ; CHECK: [[sel_merge2]] = OpLabel
321 %43 = OpLabel
322 ; CHECK-NEXT: OpBranch [[merge2]]
323 OpUnreachable
324 %41 = OpLabel
325 OpBranch %31
326 %40 = OpLabel
327 OpReturn
328 OpFunctionEnd)";
329
330 SinglePassRunAndMatch<Workaround1209>(text, false);
331 }
332
TEST_F(Workaround1209Test,LeaveUnreachableNotInLoop)333 TEST_F(Workaround1209Test, LeaveUnreachableNotInLoop) {
334 const std::string text = R"(
335 OpCapability Shader
336 %1 = OpExtInstImport "GLSL.std.450"
337 OpMemoryModel Logical GLSL450
338 OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_
339 OpSource GLSL 400
340 OpSourceExtension "GL_ARB_separate_shader_objects"
341 OpSourceExtension "GL_ARB_shading_language_420pack"
342 OpName %main "main"
343 OpName %texcoord "texcoord"
344 OpName %buf "buf"
345 OpMemberName %buf 0 "MVP"
346 OpMemberName %buf 1 "position"
347 OpMemberName %buf 2 "attr"
348 OpName %ubuf "ubuf"
349 OpName %gl_VertexIndex "gl_VertexIndex"
350 OpName %gl_PerVertex "gl_PerVertex"
351 OpMemberName %gl_PerVertex 0 "gl_Position"
352 OpName %_ ""
353 OpDecorate %texcoord Location 0
354 OpDecorate %_arr_v4float_uint_72 ArrayStride 16
355 OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16
356 OpMemberDecorate %buf 0 ColMajor
357 OpMemberDecorate %buf 0 Offset 0
358 OpMemberDecorate %buf 0 MatrixStride 16
359 OpMemberDecorate %buf 1 Offset 64
360 OpMemberDecorate %buf 2 Offset 1216
361 OpDecorate %buf Block
362 OpDecorate %ubuf DescriptorSet 0
363 OpDecorate %ubuf Binding 0
364 OpDecorate %gl_VertexIndex BuiltIn VertexIndex
365 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
366 OpDecorate %gl_PerVertex Block
367 %void = OpTypeVoid
368 %12 = OpTypeFunction %void
369 %float = OpTypeFloat 32
370 %v4float = OpTypeVector %float 4
371 %_ptr_Output_v4float = OpTypePointer Output %v4float
372 %texcoord = OpVariable %_ptr_Output_v4float Output
373 %mat4v4float = OpTypeMatrix %v4float 4
374 %uint = OpTypeInt 32 0
375 %uint_72 = OpConstant %uint 72
376 %_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72
377 %_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72
378 %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0
379 %_ptr_Uniform_buf = OpTypePointer Uniform %buf
380 %ubuf = OpVariable %_ptr_Uniform_buf Uniform
381 %int = OpTypeInt 32 1
382 %int_2 = OpConstant %int 2
383 %_ptr_Input_int = OpTypePointer Input %int
384 %gl_VertexIndex = OpVariable %_ptr_Input_int Input
385 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
386 %gl_PerVertex = OpTypeStruct %v4float
387 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
388 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
389 %int_0 = OpConstant %int 0
390 %int_1 = OpConstant %int 1
391 %float_1 = OpConstant %float 1
392 %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
393 %main = OpFunction %void None %12
394 %29 = OpLabel
395 OpBranch %30
396 %30 = OpLabel
397 OpSelectionMerge %34 None
398 OpSwitch %int_1 %35
399 %35 = OpLabel
400 %36 = OpLoad %int %gl_VertexIndex
401 %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36
402 %38 = OpLoad %v4float %37
403 OpStore %texcoord %38
404 %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0
405 OpStore %39 %28
406 OpReturn
407 %34 = OpLabel
408 ; CHECK: OpUnreachable
409 OpUnreachable
410 OpFunctionEnd)";
411
412 SinglePassRunAndMatch<Workaround1209>(text, false);
413 }
414
415 } // namespace
416 } // namespace opt
417 } // namespace spvtools
418