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