1 // Copyright (c) 2017 Valve Corporation
2 // Copyright (c) 2017 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include <string>
17 #include <vector>
18
19 #include "test/opt/assembly_builder.h"
20 #include "test/opt/pass_fixture.h"
21 #include "test/opt/pass_utils.h"
22
23 namespace spvtools {
24 namespace opt {
25 namespace {
26
27 using AggressiveDCETest = PassTest<::testing::Test>;
28
TEST_F(AggressiveDCETest,EliminateExtendedInst)29 TEST_F(AggressiveDCETest, EliminateExtendedInst) {
30 // #version 140
31 //
32 // in vec4 BaseColor;
33 // in vec4 Dead;
34 //
35 // void main()
36 // {
37 // vec4 v = BaseColor;
38 // vec4 dv = sqrt(Dead);
39 // gl_FragColor = v;
40 // }
41 const std::string spirv = R"(
42 OpCapability Shader
43 %1 = OpExtInstImport "GLSL.std.450"
44 OpMemoryModel Logical GLSL450
45 ; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
46 OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor
47 OpExecutionMode %main OriginUpperLeft
48 OpSource GLSL 140
49 OpName %main "main"
50 OpName %v "v"
51 OpName %BaseColor "BaseColor"
52 ; CHECK-NOT: OpName %dv "dv"
53 OpName %dv "dv"
54 ; CHECK-NOT: OpName %Dead "Dead"
55 OpName %Dead "Dead"
56 OpName %gl_FragColor "gl_FragColor"
57 %void = OpTypeVoid
58 %9 = OpTypeFunction %void
59 %float = OpTypeFloat 32
60 %v4float = OpTypeVector %float 4
61 %_ptr_Function_v4float = OpTypePointer Function %v4float
62 %_ptr_Input_v4float = OpTypePointer Input %v4float
63 %BaseColor = OpVariable %_ptr_Input_v4float Input
64 ; CHECK-NOT: %Dead = OpVariable
65 %Dead = OpVariable %_ptr_Input_v4float Input
66 %_ptr_Output_v4float = OpTypePointer Output %v4float
67 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
68 %main = OpFunction %void None %9
69 %15 = OpLabel
70 %v = OpVariable %_ptr_Function_v4float Function
71 ; CHECK-NOT: %dv = OpVariable
72 %dv = OpVariable %_ptr_Function_v4float Function
73 %16 = OpLoad %v4float %BaseColor
74 OpStore %v %16
75 ; CHECK-NOT: OpLoad %v4float %Dead
76 %17 = OpLoad %v4float %Dead
77 ; CHECK-NOT: OpExtInst %v4float %1 Sqrt
78 %18 = OpExtInst %v4float %1 Sqrt %17
79 ; CHECK-NOT: OpStore %dv
80 OpStore %dv %18
81 %19 = OpLoad %v4float %v
82 OpStore %gl_FragColor %19
83 OpReturn
84 OpFunctionEnd
85 )";
86
87 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
88 }
89
TEST_F(AggressiveDCETest,NoEliminateFrexp)90 TEST_F(AggressiveDCETest, NoEliminateFrexp) {
91 // Note: SPIR-V hand-edited to utilize Frexp
92 //
93 // #version 450
94 //
95 // in vec4 BaseColor;
96 // in vec4 Dead;
97 // out vec4 Color;
98 // out ivec4 iv2;
99 //
100 // void main()
101 // {
102 // vec4 v = BaseColor;
103 // vec4 dv = frexp(Dead, iv2);
104 // Color = v;
105 // }
106
107 const std::string predefs1 =
108 R"(OpCapability Shader
109 %1 = OpExtInstImport "GLSL.std.450"
110 OpMemoryModel Logical GLSL450
111 OpEntryPoint Fragment %main "main" %BaseColor %Dead %iv2 %Color
112 OpExecutionMode %main OriginUpperLeft
113 OpSource GLSL 450
114 )";
115
116 const std::string names_before =
117 R"(OpName %main "main"
118 OpName %v "v"
119 OpName %BaseColor "BaseColor"
120 OpName %dv "dv"
121 OpName %Dead "Dead"
122 OpName %iv2 "iv2"
123 OpName %ResType "ResType"
124 OpName %Color "Color"
125 )";
126
127 const std::string names_after =
128 R"(OpName %main "main"
129 OpName %v "v"
130 OpName %BaseColor "BaseColor"
131 OpName %Dead "Dead"
132 OpName %iv2 "iv2"
133 OpName %Color "Color"
134 )";
135
136 const std::string predefs2_before =
137 R"(%void = OpTypeVoid
138 %11 = OpTypeFunction %void
139 %float = OpTypeFloat 32
140 %v4float = OpTypeVector %float 4
141 %_ptr_Function_v4float = OpTypePointer Function %v4float
142 %_ptr_Input_v4float = OpTypePointer Input %v4float
143 %BaseColor = OpVariable %_ptr_Input_v4float Input
144 %Dead = OpVariable %_ptr_Input_v4float Input
145 %int = OpTypeInt 32 1
146 %v4int = OpTypeVector %int 4
147 %_ptr_Output_v4int = OpTypePointer Output %v4int
148 %iv2 = OpVariable %_ptr_Output_v4int Output
149 %ResType = OpTypeStruct %v4float %v4int
150 %_ptr_Output_v4float = OpTypePointer Output %v4float
151 %Color = OpVariable %_ptr_Output_v4float Output
152 )";
153
154 const std::string predefs2_after =
155 R"(%void = OpTypeVoid
156 %11 = OpTypeFunction %void
157 %float = OpTypeFloat 32
158 %v4float = OpTypeVector %float 4
159 %_ptr_Function_v4float = OpTypePointer Function %v4float
160 %_ptr_Input_v4float = OpTypePointer Input %v4float
161 %BaseColor = OpVariable %_ptr_Input_v4float Input
162 %Dead = OpVariable %_ptr_Input_v4float Input
163 %int = OpTypeInt 32 1
164 %v4int = OpTypeVector %int 4
165 %_ptr_Output_v4int = OpTypePointer Output %v4int
166 %iv2 = OpVariable %_ptr_Output_v4int Output
167 %_ptr_Output_v4float = OpTypePointer Output %v4float
168 %Color = OpVariable %_ptr_Output_v4float Output
169 )";
170
171 const std::string func_before =
172 R"(%main = OpFunction %void None %11
173 %20 = OpLabel
174 %v = OpVariable %_ptr_Function_v4float Function
175 %dv = OpVariable %_ptr_Function_v4float Function
176 %21 = OpLoad %v4float %BaseColor
177 OpStore %v %21
178 %22 = OpLoad %v4float %Dead
179 %23 = OpExtInst %v4float %1 Frexp %22 %iv2
180 OpStore %dv %23
181 %24 = OpLoad %v4float %v
182 OpStore %Color %24
183 OpReturn
184 OpFunctionEnd
185 )";
186
187 const std::string func_after =
188 R"(%main = OpFunction %void None %11
189 %20 = OpLabel
190 %v = OpVariable %_ptr_Function_v4float Function
191 %21 = OpLoad %v4float %BaseColor
192 OpStore %v %21
193 %22 = OpLoad %v4float %Dead
194 %23 = OpExtInst %v4float %1 Frexp %22 %iv2
195 %24 = OpLoad %v4float %v
196 OpStore %Color %24
197 OpReturn
198 OpFunctionEnd
199 )";
200
201 SinglePassRunAndCheck<AggressiveDCEPass>(
202 predefs1 + names_before + predefs2_before + func_before,
203 predefs1 + names_after + predefs2_after + func_after, true, true);
204 }
205
TEST_F(AggressiveDCETest,EliminateDecorate)206 TEST_F(AggressiveDCETest, EliminateDecorate) {
207 // Note: The SPIR-V was hand-edited to add the OpDecorate
208 //
209 // #version 140
210 //
211 // in vec4 BaseColor;
212 // in vec4 Dead;
213 //
214 // void main()
215 // {
216 // vec4 v = BaseColor;
217 // vec4 dv = Dead * 0.5;
218 // gl_FragColor = v;
219 // }
220
221 const std::string spirv =
222 R"(
223 OpCapability Shader
224 %1 = OpExtInstImport "GLSL.std.450"
225 OpMemoryModel Logical GLSL450
226 OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor
227 OpExecutionMode %main OriginUpperLeft
228 OpSource GLSL 140
229 OpName %main "main"
230 OpName %v "v"
231 OpName %BaseColor "BaseColor"
232 OpName %dv "dv"
233 OpName %Dead "Dead"
234 OpName %gl_FragColor "gl_FragColor"
235 ; CHECK-NOT: OpDecorate
236 OpDecorate %8 RelaxedPrecision
237 %void = OpTypeVoid
238 %10 = OpTypeFunction %void
239 %float = OpTypeFloat 32
240 %v4float = OpTypeVector %float 4
241 %_ptr_Function_v4float = OpTypePointer Function %v4float
242 %_ptr_Input_v4float = OpTypePointer Input %v4float
243 %BaseColor = OpVariable %_ptr_Input_v4float Input
244 %Dead = OpVariable %_ptr_Input_v4float Input
245 %float_0_5 = OpConstant %float 0.5
246 %_ptr_Output_v4float = OpTypePointer Output %v4float
247 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
248 %main = OpFunction %void None %10
249 %17 = OpLabel
250 %v = OpVariable %_ptr_Function_v4float Function
251 %dv = OpVariable %_ptr_Function_v4float Function
252 %18 = OpLoad %v4float %BaseColor
253 OpStore %v %18
254 %19 = OpLoad %v4float %Dead
255 ; CHECK-NOT: OpVectorTimesScalar
256 %8 = OpVectorTimesScalar %v4float %19 %float_0_5
257 OpStore %dv %8
258 %20 = OpLoad %v4float %v
259 OpStore %gl_FragColor %20
260 OpReturn
261 OpFunctionEnd
262 )";
263
264 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
265 }
266
TEST_F(AggressiveDCETest,Simple)267 TEST_F(AggressiveDCETest, Simple) {
268 // #version 140
269 //
270 // in vec4 BaseColor;
271 // in vec4 Dead;
272 //
273 // void main()
274 // {
275 // vec4 v = BaseColor;
276 // vec4 dv = Dead;
277 // gl_FragColor = v;
278 // }
279
280 const std::string spirv =
281 R"(
282 OpCapability Shader
283 %1 = OpExtInstImport "GLSL.std.450"
284 OpMemoryModel Logical GLSL450
285 ; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
286 OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor
287 OpExecutionMode %main OriginUpperLeft
288 OpSource GLSL 140
289 OpName %main "main"
290 OpName %v "v"
291 OpName %BaseColor "BaseColor"
292 ; CHECK-NOT: OpName %dv "dv"
293 OpName %dv "dv"
294 ; CHECK-NOT: OpName %Dead "Dead"
295 OpName %Dead "Dead"
296 OpName %gl_FragColor "gl_FragColor"
297 %void = OpTypeVoid
298 %9 = OpTypeFunction %void
299 %float = OpTypeFloat 32
300 %v4float = OpTypeVector %float 4
301 %_ptr_Function_v4float = OpTypePointer Function %v4float
302 %_ptr_Input_v4float = OpTypePointer Input %v4float
303 %BaseColor = OpVariable %_ptr_Input_v4float Input
304 ; CHECK-NOT: %Dead = OpVariable
305 %Dead = OpVariable %_ptr_Input_v4float Input
306 %_ptr_Output_v4float = OpTypePointer Output %v4float
307 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
308 %main = OpFunction %void None %9
309 %15 = OpLabel
310 %v = OpVariable %_ptr_Function_v4float Function
311 ; CHECK-NOT: %dv = OpVariable
312 %dv = OpVariable %_ptr_Function_v4float Function
313 %16 = OpLoad %v4float %BaseColor
314 OpStore %v %16
315 ; CHECK-NOT: OpLoad %v4float %Dead
316 %17 = OpLoad %v4float %Dead
317 ; CHECK-NOT: OpStore %dv
318 OpStore %dv %17
319 %18 = OpLoad %v4float %v
320 OpStore %gl_FragColor %18
321 OpReturn
322 OpFunctionEnd
323 )";
324
325 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
326 }
327
TEST_F(AggressiveDCETest,OptAllowListExtension)328 TEST_F(AggressiveDCETest, OptAllowListExtension) {
329 // #version 140
330 //
331 // in vec4 BaseColor;
332 // in vec4 Dead;
333 //
334 // void main()
335 // {
336 // vec4 v = BaseColor;
337 // vec4 dv = Dead;
338 // gl_FragColor = v;
339 // }
340
341 const std::string spirv =
342 R"(OpCapability Shader
343 OpExtension "SPV_AMD_gpu_shader_int16"
344 %1 = OpExtInstImport "GLSL.std.450"
345 OpMemoryModel Logical GLSL450
346 ; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
347 OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor
348 OpExecutionMode %main OriginUpperLeft
349 OpSource GLSL 140
350 OpName %main "main"
351 OpName %v "v"
352 OpName %BaseColor "BaseColor"
353 OpName %dv "dv"
354 OpName %Dead "Dead"
355 OpName %gl_FragColor "gl_FragColor"
356 %void = OpTypeVoid
357 %9 = OpTypeFunction %void
358 %float = OpTypeFloat 32
359 %v4float = OpTypeVector %float 4
360 %_ptr_Function_v4float = OpTypePointer Function %v4float
361 %_ptr_Input_v4float = OpTypePointer Input %v4float
362 %BaseColor = OpVariable %_ptr_Input_v4float Input
363 %Dead = OpVariable %_ptr_Input_v4float Input
364 %_ptr_Output_v4float = OpTypePointer Output %v4float
365 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
366 %main = OpFunction %void None %9
367 %15 = OpLabel
368 %v = OpVariable %_ptr_Function_v4float Function
369 %dv = OpVariable %_ptr_Function_v4float Function
370 %16 = OpLoad %v4float %BaseColor
371 OpStore %v %16
372 %17 = OpLoad %v4float %Dead
373 OpStore %dv %17
374 %18 = OpLoad %v4float %v
375 OpStore %gl_FragColor %18
376 OpReturn
377 OpFunctionEnd
378 )";
379
380 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
381 }
382
TEST_F(AggressiveDCETest,NoOptDenyListExtension)383 TEST_F(AggressiveDCETest, NoOptDenyListExtension) {
384 // #version 140
385 //
386 // in vec4 BaseColor;
387 // in vec4 Dead;
388 //
389 // void main()
390 // {
391 // vec4 v = BaseColor;
392 // vec4 dv = Dead;
393 // gl_FragColor = v;
394 // }
395
396 const std::string assembly =
397 R"(OpCapability Shader
398 OpExtension "SPV_KHR_variable_pointers"
399 %1 = OpExtInstImport "GLSL.std.450"
400 OpMemoryModel Logical GLSL450
401 OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor
402 OpExecutionMode %main OriginUpperLeft
403 OpSource GLSL 140
404 OpName %main "main"
405 OpName %v "v"
406 OpName %BaseColor "BaseColor"
407 OpName %dv "dv"
408 OpName %Dead "Dead"
409 OpName %gl_FragColor "gl_FragColor"
410 %void = OpTypeVoid
411 %9 = OpTypeFunction %void
412 %float = OpTypeFloat 32
413 %v4float = OpTypeVector %float 4
414 %_ptr_Function_v4float = OpTypePointer Function %v4float
415 %_ptr_Input_v4float = OpTypePointer Input %v4float
416 %BaseColor = OpVariable %_ptr_Input_v4float Input
417 %Dead = OpVariable %_ptr_Input_v4float Input
418 %_ptr_Output_v4float = OpTypePointer Output %v4float
419 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
420 %main = OpFunction %void None %9
421 %15 = OpLabel
422 %v = OpVariable %_ptr_Function_v4float Function
423 %dv = OpVariable %_ptr_Function_v4float Function
424 %16 = OpLoad %v4float %BaseColor
425 OpStore %v %16
426 %17 = OpLoad %v4float %Dead
427 OpStore %dv %17
428 %18 = OpLoad %v4float %v
429 OpStore %gl_FragColor %18
430 OpReturn
431 OpFunctionEnd
432 )";
433
434 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
435 }
436
TEST_F(AggressiveDCETest,ElimWithCall)437 TEST_F(AggressiveDCETest, ElimWithCall) {
438 // This demonstrates that "dead" function calls are not eliminated.
439 // Also demonstrates that DCE will happen in presence of function call.
440 // #version 140
441 // in vec4 i1;
442 // in vec4 i2;
443 //
444 // void nothing(vec4 v)
445 // {
446 // }
447 //
448 // void main()
449 // {
450 // vec4 v1 = i1;
451 // vec4 v2 = i2;
452 // nothing(v1);
453 // gl_FragColor = vec4(0.0);
454 // }
455
456 const std::string text =
457 R"( OpCapability Shader
458 %1 = OpExtInstImport "GLSL.std.450"
459 OpMemoryModel Logical GLSL450
460 OpEntryPoint Fragment %main "main" %i1 %i2 %gl_FragColor
461 OpExecutionMode %main OriginUpperLeft
462 OpSource GLSL 140
463 OpName %main "main"
464 OpName %nothing_vf4_ "nothing(vf4;"
465 OpName %v "v"
466 OpName %v1 "v1"
467 OpName %i1 "i1"
468 OpName %v2 "v2"
469 OpName %i2 "i2"
470 OpName %param "param"
471 OpName %gl_FragColor "gl_FragColor"
472 %void = OpTypeVoid
473 %12 = OpTypeFunction %void
474 %float = OpTypeFloat 32
475 %v4float = OpTypeVector %float 4
476 %_ptr_Function_v4float = OpTypePointer Function %v4float
477 %16 = OpTypeFunction %void %_ptr_Function_v4float
478 %_ptr_Input_v4float = OpTypePointer Input %v4float
479 %i1 = OpVariable %_ptr_Input_v4float Input
480 %i2 = OpVariable %_ptr_Input_v4float Input
481 %_ptr_Output_v4float = OpTypePointer Output %v4float
482 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
483 %float_0 = OpConstant %float 0
484 %20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
485 %main = OpFunction %void None %12
486 %21 = OpLabel
487 %v1 = OpVariable %_ptr_Function_v4float Function
488 %v2 = OpVariable %_ptr_Function_v4float Function
489 %param = OpVariable %_ptr_Function_v4float Function
490 %22 = OpLoad %v4float %i1
491 OpStore %v1 %22
492 ; CHECK-NOT: OpLoad %v4float %i2
493 %23 = OpLoad %v4float %i2
494 ; CHECK-NOT: OpStore %v2
495 OpStore %v2 %23
496 %24 = OpLoad %v4float %v1
497 OpStore %param %24
498 ; CHECK: OpFunctionCall %void %nothing_vf4_
499 %25 = OpFunctionCall %void %nothing_vf4_ %param
500 OpStore %gl_FragColor %20
501 OpReturn
502 OpFunctionEnd
503 ; CHECK: %nothing_vf4_ = OpFunction
504 %nothing_vf4_ = OpFunction %void None %16
505 %v = OpFunctionParameter %_ptr_Function_v4float
506 %26 = OpLabel
507 OpReturn
508 OpFunctionEnd
509 )";
510
511 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
512 }
513
TEST_F(AggressiveDCETest,NoParamElim)514 TEST_F(AggressiveDCETest, NoParamElim) {
515 // This demonstrates that unused parameters are not eliminated, but
516 // dead uses of them are.
517 // #version 140
518 //
519 // in vec4 BaseColor;
520 //
521 // vec4 foo(vec4 v1, vec4 v2)
522 // {
523 // vec4 t = -v1;
524 // return v2;
525 // }
526 //
527 // void main()
528 // {
529 // vec4 dead;
530 // gl_FragColor = foo(dead, BaseColor);
531 // }
532
533 const std::string defs_before =
534 R"(OpCapability Shader
535 %1 = OpExtInstImport "GLSL.std.450"
536 OpMemoryModel Logical GLSL450
537 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
538 OpExecutionMode %main OriginUpperLeft
539 OpSource GLSL 140
540 OpName %main "main"
541 OpName %foo_vf4_vf4_ "foo(vf4;vf4;"
542 OpName %v1 "v1"
543 OpName %v2 "v2"
544 OpName %t "t"
545 OpName %gl_FragColor "gl_FragColor"
546 OpName %dead "dead"
547 OpName %BaseColor "BaseColor"
548 OpName %param "param"
549 OpName %param_0 "param"
550 %void = OpTypeVoid
551 %13 = OpTypeFunction %void
552 %float = OpTypeFloat 32
553 %v4float = OpTypeVector %float 4
554 %_ptr_Function_v4float = OpTypePointer Function %v4float
555 %17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float
556 %_ptr_Output_v4float = OpTypePointer Output %v4float
557 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
558 %_ptr_Input_v4float = OpTypePointer Input %v4float
559 %BaseColor = OpVariable %_ptr_Input_v4float Input
560 %main = OpFunction %void None %13
561 %20 = OpLabel
562 %dead = OpVariable %_ptr_Function_v4float Function
563 %param = OpVariable %_ptr_Function_v4float Function
564 %param_0 = OpVariable %_ptr_Function_v4float Function
565 %21 = OpLoad %v4float %dead
566 OpStore %param %21
567 %22 = OpLoad %v4float %BaseColor
568 OpStore %param_0 %22
569 %23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0
570 OpStore %gl_FragColor %23
571 OpReturn
572 OpFunctionEnd
573 )";
574
575 const std::string defs_after =
576 R"(OpCapability Shader
577 %1 = OpExtInstImport "GLSL.std.450"
578 OpMemoryModel Logical GLSL450
579 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
580 OpExecutionMode %main OriginUpperLeft
581 OpSource GLSL 140
582 OpName %main "main"
583 OpName %foo_vf4_vf4_ "foo(vf4;vf4;"
584 OpName %v1 "v1"
585 OpName %v2 "v2"
586 OpName %gl_FragColor "gl_FragColor"
587 OpName %dead "dead"
588 OpName %BaseColor "BaseColor"
589 OpName %param "param"
590 OpName %param_0 "param"
591 %void = OpTypeVoid
592 %13 = OpTypeFunction %void
593 %float = OpTypeFloat 32
594 %v4float = OpTypeVector %float 4
595 %_ptr_Function_v4float = OpTypePointer Function %v4float
596 %17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float
597 %_ptr_Output_v4float = OpTypePointer Output %v4float
598 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
599 %_ptr_Input_v4float = OpTypePointer Input %v4float
600 %BaseColor = OpVariable %_ptr_Input_v4float Input
601 %main = OpFunction %void None %13
602 %20 = OpLabel
603 %dead = OpVariable %_ptr_Function_v4float Function
604 %param = OpVariable %_ptr_Function_v4float Function
605 %param_0 = OpVariable %_ptr_Function_v4float Function
606 %21 = OpLoad %v4float %dead
607 OpStore %param %21
608 %22 = OpLoad %v4float %BaseColor
609 OpStore %param_0 %22
610 %23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0
611 OpStore %gl_FragColor %23
612 OpReturn
613 OpFunctionEnd
614 )";
615
616 const std::string func_before =
617 R"(%foo_vf4_vf4_ = OpFunction %v4float None %17
618 %v1 = OpFunctionParameter %_ptr_Function_v4float
619 %v2 = OpFunctionParameter %_ptr_Function_v4float
620 %24 = OpLabel
621 %t = OpVariable %_ptr_Function_v4float Function
622 %25 = OpLoad %v4float %v1
623 %26 = OpFNegate %v4float %25
624 OpStore %t %26
625 %27 = OpLoad %v4float %v2
626 OpReturnValue %27
627 OpFunctionEnd
628 )";
629
630 const std::string func_after =
631 R"(%foo_vf4_vf4_ = OpFunction %v4float None %17
632 %v1 = OpFunctionParameter %_ptr_Function_v4float
633 %v2 = OpFunctionParameter %_ptr_Function_v4float
634 %24 = OpLabel
635 %27 = OpLoad %v4float %v2
636 OpReturnValue %27
637 OpFunctionEnd
638 )";
639
640 SinglePassRunAndCheck<AggressiveDCEPass>(defs_before + func_before,
641 defs_after + func_after, true, true);
642 }
643
TEST_F(AggressiveDCETest,ElimOpaque)644 TEST_F(AggressiveDCETest, ElimOpaque) {
645 // SPIR-V not representable from GLSL; not generatable from HLSL
646 // for the moment.
647
648 const std::string defs_before =
649 R"(OpCapability Shader
650 %1 = OpExtInstImport "GLSL.std.450"
651 OpMemoryModel Logical GLSL450
652 OpEntryPoint Fragment %main "main" %outColor %texCoords
653 OpExecutionMode %main OriginUpperLeft
654 OpSource GLSL 140
655 OpName %main "main"
656 OpName %S_t "S_t"
657 OpMemberName %S_t 0 "v0"
658 OpMemberName %S_t 1 "v1"
659 OpMemberName %S_t 2 "smp"
660 OpName %outColor "outColor"
661 OpName %sampler15 "sampler15"
662 OpName %s0 "s0"
663 OpName %texCoords "texCoords"
664 OpDecorate %sampler15 DescriptorSet 0
665 %void = OpTypeVoid
666 %9 = OpTypeFunction %void
667 %float = OpTypeFloat 32
668 %v2float = OpTypeVector %float 2
669 %v4float = OpTypeVector %float 4
670 %_ptr_Output_v4float = OpTypePointer Output %v4float
671 %outColor = OpVariable %_ptr_Output_v4float Output
672 %14 = OpTypeImage %float 2D 0 0 0 1 Unknown
673 %15 = OpTypeSampledImage %14
674 %S_t = OpTypeStruct %v2float %v2float %15
675 %_ptr_Function_S_t = OpTypePointer Function %S_t
676 %17 = OpTypeFunction %void %_ptr_Function_S_t
677 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
678 %_ptr_Function_15 = OpTypePointer Function %15
679 %sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant
680 %int = OpTypeInt 32 1
681 %int_0 = OpConstant %int 0
682 %int_2 = OpConstant %int 2
683 %_ptr_Function_v2float = OpTypePointer Function %v2float
684 %_ptr_Input_v2float = OpTypePointer Input %v2float
685 %texCoords = OpVariable %_ptr_Input_v2float Input
686 )";
687
688 const std::string defs_after =
689 R"(OpCapability Shader
690 %1 = OpExtInstImport "GLSL.std.450"
691 OpMemoryModel Logical GLSL450
692 OpEntryPoint Fragment %main "main" %outColor %texCoords
693 OpExecutionMode %main OriginUpperLeft
694 OpSource GLSL 140
695 OpName %main "main"
696 OpName %outColor "outColor"
697 OpName %sampler15 "sampler15"
698 OpName %texCoords "texCoords"
699 OpDecorate %sampler15 DescriptorSet 0
700 %void = OpTypeVoid
701 %9 = OpTypeFunction %void
702 %float = OpTypeFloat 32
703 %v2float = OpTypeVector %float 2
704 %v4float = OpTypeVector %float 4
705 %_ptr_Output_v4float = OpTypePointer Output %v4float
706 %outColor = OpVariable %_ptr_Output_v4float Output
707 %14 = OpTypeImage %float 2D 0 0 0 1 Unknown
708 %15 = OpTypeSampledImage %14
709 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
710 %sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant
711 %_ptr_Input_v2float = OpTypePointer Input %v2float
712 %texCoords = OpVariable %_ptr_Input_v2float Input
713 )";
714
715 const std::string func_before =
716 R"(%main = OpFunction %void None %9
717 %25 = OpLabel
718 %s0 = OpVariable %_ptr_Function_S_t Function
719 %26 = OpLoad %v2float %texCoords
720 %27 = OpLoad %S_t %s0
721 %28 = OpCompositeInsert %S_t %26 %27 0
722 %29 = OpLoad %15 %sampler15
723 %30 = OpCompositeInsert %S_t %29 %28 2
724 OpStore %s0 %30
725 %31 = OpImageSampleImplicitLod %v4float %29 %26
726 OpStore %outColor %31
727 OpReturn
728 OpFunctionEnd
729 )";
730
731 const std::string func_after =
732 R"(%main = OpFunction %void None %9
733 %25 = OpLabel
734 %26 = OpLoad %v2float %texCoords
735 %29 = OpLoad %15 %sampler15
736 %31 = OpImageSampleImplicitLod %v4float %29 %26
737 OpStore %outColor %31
738 OpReturn
739 OpFunctionEnd
740 )";
741
742 SinglePassRunAndCheck<AggressiveDCEPass>(defs_before + func_before,
743 defs_after + func_after, true, true);
744 }
745
TEST_F(AggressiveDCETest,NoParamStoreElim)746 TEST_F(AggressiveDCETest, NoParamStoreElim) {
747 // Should not eliminate stores to params
748 //
749 // #version 450
750 //
751 // layout(location = 0) in vec4 BaseColor;
752 // layout(location = 0) out vec4 OutColor;
753 //
754 // void foo(in vec4 v1, out vec4 v2)
755 // {
756 // v2 = -v1;
757 // }
758 //
759 // void main()
760 // {
761 // foo(BaseColor, OutColor);
762 // }
763
764 const std::string assembly =
765 R"(OpCapability Shader
766 %1 = OpExtInstImport "GLSL.std.450"
767 OpMemoryModel Logical GLSL450
768 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
769 OpExecutionMode %main OriginUpperLeft
770 OpSource GLSL 450
771 OpName %main "main"
772 OpName %foo_vf4_vf4_ "foo(vf4;vf4;"
773 OpName %v1 "v1"
774 OpName %v2 "v2"
775 OpName %BaseColor "BaseColor"
776 OpName %OutColor "OutColor"
777 OpName %param "param"
778 OpName %param_0 "param"
779 OpDecorate %BaseColor Location 0
780 OpDecorate %OutColor Location 0
781 %void = OpTypeVoid
782 %11 = OpTypeFunction %void
783 %float = OpTypeFloat 32
784 %v4float = OpTypeVector %float 4
785 %_ptr_Function_v4float = OpTypePointer Function %v4float
786 %15 = OpTypeFunction %void %_ptr_Function_v4float %_ptr_Function_v4float
787 %_ptr_Input_v4float = OpTypePointer Input %v4float
788 %BaseColor = OpVariable %_ptr_Input_v4float Input
789 %_ptr_Output_v4float = OpTypePointer Output %v4float
790 %OutColor = OpVariable %_ptr_Output_v4float Output
791 %main = OpFunction %void None %11
792 %18 = OpLabel
793 %param = OpVariable %_ptr_Function_v4float Function
794 %param_0 = OpVariable %_ptr_Function_v4float Function
795 %19 = OpLoad %v4float %BaseColor
796 OpStore %param %19
797 %20 = OpFunctionCall %void %foo_vf4_vf4_ %param %param_0
798 %21 = OpLoad %v4float %param_0
799 OpStore %OutColor %21
800 OpReturn
801 OpFunctionEnd
802 %foo_vf4_vf4_ = OpFunction %void None %15
803 %v1 = OpFunctionParameter %_ptr_Function_v4float
804 %v2 = OpFunctionParameter %_ptr_Function_v4float
805 %22 = OpLabel
806 %23 = OpLoad %v4float %v1
807 %24 = OpFNegate %v4float %23
808 OpStore %v2 %24
809 OpReturn
810 OpFunctionEnd
811 )";
812
813 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
814 }
815
TEST_F(AggressiveDCETest,PrivateStoreElimInEntryNoCalls)816 TEST_F(AggressiveDCETest, PrivateStoreElimInEntryNoCalls) {
817 // Eliminate stores to private in entry point with no calls
818 // Note: Not legal GLSL
819 //
820 // layout(location = 0) in vec4 BaseColor;
821 // layout(location = 1) in vec4 Dead;
822 // layout(location = 0) out vec4 OutColor;
823 //
824 // private vec4 dv;
825 //
826 // void main()
827 // {
828 // vec4 v = BaseColor;
829 // dv = Dead;
830 // OutColor = v;
831 // }
832
833 const std::string spirv =
834 R"(OpCapability Shader
835 %1 = OpExtInstImport "GLSL.std.450"
836 OpMemoryModel Logical GLSL450
837 OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor
838 OpExecutionMode %main OriginUpperLeft
839 OpSource GLSL 450
840 OpName %main "main"
841 OpName %v "v"
842 OpName %BaseColor "BaseColor"
843 ; CHECK-NOT: OpName %dv "dv"
844 OpName %dv "dv"
845 OpName %Dead "Dead"
846 OpName %OutColor "OutColor"
847 OpDecorate %BaseColor Location 0
848 OpDecorate %Dead Location 1
849 OpDecorate %OutColor Location 0
850 %void = OpTypeVoid
851 %9 = OpTypeFunction %void
852 %float = OpTypeFloat 32
853 %v4float = OpTypeVector %float 4
854 %_ptr_Function_v4float = OpTypePointer Function %v4float
855 ; CHECK-NOT: OpTypePointer Private
856 %_ptr_Private_v4float = OpTypePointer Private %v4float
857 %_ptr_Input_v4float = OpTypePointer Input %v4float
858 %BaseColor = OpVariable %_ptr_Input_v4float Input
859 %Dead = OpVariable %_ptr_Input_v4float Input
860 %_ptr_Output_v4float = OpTypePointer Output %v4float
861 ; CHECK-NOT: %dv = OpVariable
862 %dv = OpVariable %_ptr_Private_v4float Private
863 %OutColor = OpVariable %_ptr_Output_v4float Output
864 %main = OpFunction %void None %9
865 %16 = OpLabel
866 %v = OpVariable %_ptr_Function_v4float Function
867 %17 = OpLoad %v4float %BaseColor
868 OpStore %v %17
869 %18 = OpLoad %v4float %Dead
870 ; CHECK-NOT: OpStore %dv
871 OpStore %dv %18
872 %19 = OpLoad %v4float %v
873 %20 = OpFNegate %v4float %19
874 OpStore %OutColor %20
875 OpReturn
876 OpFunctionEnd
877 )";
878
879 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
880 }
881
TEST_F(AggressiveDCETest,NoPrivateStoreElimIfLoad)882 TEST_F(AggressiveDCETest, NoPrivateStoreElimIfLoad) {
883 // Should not eliminate stores to private when there is a load
884 // Note: Not legal GLSL
885 //
886 // #version 450
887 //
888 // layout(location = 0) in vec4 BaseColor;
889 // layout(location = 0) out vec4 OutColor;
890 //
891 // private vec4 pv;
892 //
893 // void main()
894 // {
895 // pv = BaseColor;
896 // OutColor = pv;
897 // }
898
899 const std::string assembly =
900 R"(OpCapability Shader
901 %1 = OpExtInstImport "GLSL.std.450"
902 OpMemoryModel Logical GLSL450
903 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
904 OpExecutionMode %main OriginUpperLeft
905 OpSource GLSL 450
906 OpName %main "main"
907 OpName %pv "pv"
908 OpName %BaseColor "BaseColor"
909 OpName %OutColor "OutColor"
910 OpDecorate %BaseColor Location 0
911 OpDecorate %OutColor Location 0
912 %void = OpTypeVoid
913 %7 = OpTypeFunction %void
914 %float = OpTypeFloat 32
915 %v4float = OpTypeVector %float 4
916 %_ptr_Private_v4float = OpTypePointer Private %v4float
917 %_ptr_Input_v4float = OpTypePointer Input %v4float
918 %BaseColor = OpVariable %_ptr_Input_v4float Input
919 %_ptr_Output_v4float = OpTypePointer Output %v4float
920 %OutColor = OpVariable %_ptr_Output_v4float Output
921 %pv = OpVariable %_ptr_Private_v4float Private
922 %main = OpFunction %void None %7
923 %13 = OpLabel
924 %14 = OpLoad %v4float %BaseColor
925 OpStore %pv %14
926 %15 = OpLoad %v4float %pv
927 %16 = OpFNegate %v4float %15
928 OpStore %OutColor %16
929 OpReturn
930 OpFunctionEnd
931 )";
932
933 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
934 }
935
TEST_F(AggressiveDCETest,NoPrivateStoreElimWithCall)936 TEST_F(AggressiveDCETest, NoPrivateStoreElimWithCall) {
937 // Should not eliminate stores to private when function contains call
938 // Note: Not legal GLSL
939 //
940 // #version 450
941 //
942 // layout(location = 0) in vec4 BaseColor;
943 // layout(location = 0) out vec4 OutColor;
944 //
945 // private vec4 v1;
946 //
947 // void foo()
948 // {
949 // OutColor = -v1;
950 // }
951 //
952 // void main()
953 // {
954 // v1 = BaseColor;
955 // foo();
956 // }
957
958 const std::string assembly =
959 R"(OpCapability Shader
960 %1 = OpExtInstImport "GLSL.std.450"
961 OpMemoryModel Logical GLSL450
962 OpEntryPoint Fragment %main "main" %OutColor %BaseColor
963 OpExecutionMode %main OriginUpperLeft
964 OpSource GLSL 450
965 OpName %main "main"
966 OpName %foo_ "foo("
967 OpName %OutColor "OutColor"
968 OpName %v1 "v1"
969 OpName %BaseColor "BaseColor"
970 OpDecorate %OutColor Location 0
971 OpDecorate %BaseColor Location 0
972 %void = OpTypeVoid
973 %8 = OpTypeFunction %void
974 %float = OpTypeFloat 32
975 %v4float = OpTypeVector %float 4
976 %_ptr_Output_v4float = OpTypePointer Output %v4float
977 %OutColor = OpVariable %_ptr_Output_v4float Output
978 %_ptr_Private_v4float = OpTypePointer Private %v4float
979 %_ptr_Input_v4float = OpTypePointer Input %v4float
980 %v1 = OpVariable %_ptr_Private_v4float Private
981 %BaseColor = OpVariable %_ptr_Input_v4float Input
982 %main = OpFunction %void None %8
983 %14 = OpLabel
984 %15 = OpLoad %v4float %BaseColor
985 OpStore %v1 %15
986 %16 = OpFunctionCall %void %foo_
987 OpReturn
988 OpFunctionEnd
989 %foo_ = OpFunction %void None %8
990 %17 = OpLabel
991 %18 = OpLoad %v4float %v1
992 %19 = OpFNegate %v4float %18
993 OpStore %OutColor %19
994 OpReturn
995 OpFunctionEnd
996 )";
997
998 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
999 }
1000
TEST_F(AggressiveDCETest,NoPrivateStoreElimInNonEntry)1001 TEST_F(AggressiveDCETest, NoPrivateStoreElimInNonEntry) {
1002 // Should not eliminate stores to private when function is not entry point
1003 // Note: Not legal GLSL
1004 //
1005 // #version 450
1006 //
1007 // layout(location = 0) in vec4 BaseColor;
1008 // layout(location = 0) out vec4 OutColor;
1009 //
1010 // private vec4 v1;
1011 //
1012 // void foo()
1013 // {
1014 // v1 = BaseColor;
1015 // }
1016 //
1017 // void main()
1018 // {
1019 // foo();
1020 // OutColor = -v1;
1021 // }
1022
1023 const std::string assembly =
1024 R"(OpCapability Shader
1025 %1 = OpExtInstImport "GLSL.std.450"
1026 OpMemoryModel Logical GLSL450
1027 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1028 OpExecutionMode %main OriginUpperLeft
1029 OpSource GLSL 450
1030 OpName %main "main"
1031 OpName %foo_ "foo("
1032 OpName %v1 "v1"
1033 OpName %BaseColor "BaseColor"
1034 OpName %OutColor "OutColor"
1035 OpDecorate %BaseColor Location 0
1036 OpDecorate %OutColor Location 0
1037 %void = OpTypeVoid
1038 %8 = OpTypeFunction %void
1039 %float = OpTypeFloat 32
1040 %v4float = OpTypeVector %float 4
1041 %_ptr_Private_v4float = OpTypePointer Private %v4float
1042 %_ptr_Input_v4float = OpTypePointer Input %v4float
1043 %BaseColor = OpVariable %_ptr_Input_v4float Input
1044 %_ptr_Output_v4float = OpTypePointer Output %v4float
1045 %v1 = OpVariable %_ptr_Private_v4float Private
1046 %OutColor = OpVariable %_ptr_Output_v4float Output
1047 %main = OpFunction %void None %8
1048 %14 = OpLabel
1049 %15 = OpFunctionCall %void %foo_
1050 %16 = OpLoad %v4float %v1
1051 %17 = OpFNegate %v4float %16
1052 OpStore %OutColor %17
1053 OpReturn
1054 OpFunctionEnd
1055 %foo_ = OpFunction %void None %8
1056 %18 = OpLabel
1057 %19 = OpLoad %v4float %BaseColor
1058 OpStore %v1 %19
1059 OpReturn
1060 OpFunctionEnd
1061 )";
1062
1063 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1064 }
1065
TEST_F(AggressiveDCETest,WorkgroupStoreElimInEntryNoCalls)1066 TEST_F(AggressiveDCETest, WorkgroupStoreElimInEntryNoCalls) {
1067 // Eliminate stores to private in entry point with no calls
1068 // Note: Not legal GLSL
1069 //
1070 // layout(location = 0) in vec4 BaseColor;
1071 // layout(location = 1) in vec4 Dead;
1072 // layout(location = 0) out vec4 OutColor;
1073 //
1074 // workgroup vec4 dv;
1075 //
1076 // void main()
1077 // {
1078 // vec4 v = BaseColor;
1079 // dv = Dead;
1080 // OutColor = v;
1081 // }
1082
1083 const std::string spirv =
1084 R"(OpCapability Shader
1085 %1 = OpExtInstImport "GLSL.std.450"
1086 OpMemoryModel Logical GLSL450
1087 OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor
1088 OpExecutionMode %main OriginUpperLeft
1089 OpSource GLSL 450
1090 OpName %main "main"
1091 OpName %v "v"
1092 OpName %BaseColor "BaseColor"
1093 ; CHECK-NOT: OpName %dv "dv"
1094 OpName %dv "dv"
1095 OpName %Dead "Dead"
1096 OpName %OutColor "OutColor"
1097 OpDecorate %BaseColor Location 0
1098 OpDecorate %Dead Location 1
1099 OpDecorate %OutColor Location 0
1100 %void = OpTypeVoid
1101 %9 = OpTypeFunction %void
1102 %float = OpTypeFloat 32
1103 %v4float = OpTypeVector %float 4
1104 %_ptr_Function_v4float = OpTypePointer Function %v4float
1105 ; CHECK-NOT: OpTypePointer Workgroup
1106 %_ptr_Workgroup_v4float = OpTypePointer Workgroup %v4float
1107 %_ptr_Input_v4float = OpTypePointer Input %v4float
1108 %BaseColor = OpVariable %_ptr_Input_v4float Input
1109 %Dead = OpVariable %_ptr_Input_v4float Input
1110 %_ptr_Output_v4float = OpTypePointer Output %v4float
1111 ; CHECK-NOT: %dv = OpVariable
1112 %dv = OpVariable %_ptr_Workgroup_v4float Workgroup
1113 %OutColor = OpVariable %_ptr_Output_v4float Output
1114 %main = OpFunction %void None %9
1115 %16 = OpLabel
1116 %v = OpVariable %_ptr_Function_v4float Function
1117 %17 = OpLoad %v4float %BaseColor
1118 OpStore %v %17
1119 %18 = OpLoad %v4float %Dead
1120 ; CHECK-NOT: OpStore %dv
1121 OpStore %dv %18
1122 %19 = OpLoad %v4float %v
1123 %20 = OpFNegate %v4float %19
1124 OpStore %OutColor %20
1125 OpReturn
1126 OpFunctionEnd
1127 )";
1128
1129 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
1130 }
1131
TEST_F(AggressiveDCETest,EliminateDeadIfThenElse)1132 TEST_F(AggressiveDCETest, EliminateDeadIfThenElse) {
1133 // #version 450
1134 //
1135 // layout(location = 0) in vec4 BaseColor;
1136 // layout(location = 0) out vec4 OutColor;
1137 //
1138 // void main()
1139 // {
1140 // float d;
1141 // if (BaseColor.x == 0)
1142 // d = BaseColor.y;
1143 // else
1144 // d = BaseColor.z;
1145 // OutColor = vec4(1.0,1.0,1.0,1.0);
1146 // }
1147
1148 const std::string spirv =
1149 R"(OpCapability Shader
1150 %1 = OpExtInstImport "GLSL.std.450"
1151 OpMemoryModel Logical GLSL450
1152 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1153 OpExecutionMode %main OriginUpperLeft
1154 OpSource GLSL 450
1155 OpName %main "main"
1156 OpName %BaseColor "BaseColor"
1157 OpName %d "d"
1158 OpName %OutColor "OutColor"
1159 OpDecorate %BaseColor Location 0
1160 OpDecorate %OutColor Location 0
1161 %void = OpTypeVoid
1162 %7 = OpTypeFunction %void
1163 %float = OpTypeFloat 32
1164 %v4float = OpTypeVector %float 4
1165 %_ptr_Input_v4float = OpTypePointer Input %v4float
1166 %BaseColor = OpVariable %_ptr_Input_v4float Input
1167 %uint = OpTypeInt 32 0
1168 %uint_0 = OpConstant %uint 0
1169 %_ptr_Input_float = OpTypePointer Input %float
1170 %float_0 = OpConstant %float 0
1171 %bool = OpTypeBool
1172 %_ptr_Function_float = OpTypePointer Function %float
1173 %uint_1 = OpConstant %uint 1
1174 %uint_2 = OpConstant %uint 2
1175 %_ptr_Output_v4float = OpTypePointer Output %v4float
1176 %OutColor = OpVariable %_ptr_Output_v4float Output
1177 %float_1 = OpConstant %float 1
1178 %21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1179 ; CHECK: = OpFunction %void
1180 ; CHECK-NEXT: %22 = OpLabel
1181 ; CHECK-NEXT: OpBranch %26
1182 ; CHECK-NEXT: %26 = OpLabel
1183 %main = OpFunction %void None %7
1184 %22 = OpLabel
1185 %d = OpVariable %_ptr_Function_float Function
1186 %23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1187 %24 = OpLoad %float %23
1188 %25 = OpFOrdEqual %bool %24 %float_0
1189 OpSelectionMerge %26 None
1190 OpBranchConditional %25 %27 %28
1191 %27 = OpLabel
1192 %29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1193 %30 = OpLoad %float %29
1194 OpStore %d %30
1195 OpBranch %26
1196 %28 = OpLabel
1197 %31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2
1198 %32 = OpLoad %float %31
1199 OpStore %d %32
1200 OpBranch %26
1201 %26 = OpLabel
1202 OpStore %OutColor %21
1203 OpReturn
1204 OpFunctionEnd
1205 )";
1206
1207 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
1208 }
1209
TEST_F(AggressiveDCETest,EliminateDeadIfThen)1210 TEST_F(AggressiveDCETest, EliminateDeadIfThen) {
1211 // #version 450
1212 //
1213 // layout(location = 0) in vec4 BaseColor;
1214 // layout(location = 0) out vec4 OutColor;
1215 //
1216 // void main()
1217 // {
1218 // float d;
1219 // if (BaseColor.x == 0)
1220 // d = BaseColor.y;
1221 // OutColor = vec4(1.0,1.0,1.0,1.0);
1222 // }
1223
1224 const std::string spirv =
1225 R"(OpCapability Shader
1226 %1 = OpExtInstImport "GLSL.std.450"
1227 OpMemoryModel Logical GLSL450
1228 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1229 OpExecutionMode %main OriginUpperLeft
1230 OpSource GLSL 450
1231 OpName %main "main"
1232 OpName %BaseColor "BaseColor"
1233 OpName %d "d"
1234 OpName %OutColor "OutColor"
1235 OpDecorate %BaseColor Location 0
1236 OpDecorate %OutColor Location 0
1237 %void = OpTypeVoid
1238 %7 = OpTypeFunction %void
1239 %float = OpTypeFloat 32
1240 %v4float = OpTypeVector %float 4
1241 %_ptr_Input_v4float = OpTypePointer Input %v4float
1242 %BaseColor = OpVariable %_ptr_Input_v4float Input
1243 %uint = OpTypeInt 32 0
1244 %uint_0 = OpConstant %uint 0
1245 %_ptr_Input_float = OpTypePointer Input %float
1246 %float_0 = OpConstant %float 0
1247 %bool = OpTypeBool
1248 %_ptr_Function_float = OpTypePointer Function %float
1249 %uint_1 = OpConstant %uint 1
1250 %_ptr_Output_v4float = OpTypePointer Output %v4float
1251 %OutColor = OpVariable %_ptr_Output_v4float Output
1252 %float_1 = OpConstant %float 1
1253 %20 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1254 ; CHECK: = OpFunction
1255 ; CHECK-NEXT: %21 = OpLabel
1256 ; CHECK-NEXT: OpBranch [[target:%\w+]]
1257 ; CHECK-NEXT: [[target]] = OpLabel
1258 %main = OpFunction %void None %7
1259 %21 = OpLabel
1260 %d = OpVariable %_ptr_Function_float Function
1261 %22 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1262 %23 = OpLoad %float %22
1263 %24 = OpFOrdEqual %bool %23 %float_0
1264 OpSelectionMerge %25 None
1265 OpBranchConditional %24 %26 %25
1266 %26 = OpLabel
1267 %27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1268 %28 = OpLoad %float %27
1269 OpStore %d %28
1270 OpBranch %25
1271 %25 = OpLabel
1272 OpStore %OutColor %20
1273 OpReturn
1274 OpFunctionEnd
1275 )";
1276
1277 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
1278 }
1279
TEST_F(AggressiveDCETest,EliminateDeadSwitch)1280 TEST_F(AggressiveDCETest, EliminateDeadSwitch) {
1281 // #version 450
1282 //
1283 // layout(location = 0) in vec4 BaseColor;
1284 // layout(location = 1) in flat int x;
1285 // layout(location = 0) out vec4 OutColor;
1286 //
1287 // void main()
1288 // {
1289 // float d;
1290 // switch (x) {
1291 // case 0:
1292 // d = BaseColor.y;
1293 // }
1294 // OutColor = vec4(1.0,1.0,1.0,1.0);
1295 // }
1296 const std::string spirv =
1297 R"(OpCapability Shader
1298 %1 = OpExtInstImport "GLSL.std.450"
1299 OpMemoryModel Logical GLSL450
1300 OpEntryPoint Fragment %main "main" %x %BaseColor %OutColor
1301 OpExecutionMode %main OriginUpperLeft
1302 OpSource GLSL 450
1303 OpName %main "main"
1304 OpName %x "x"
1305 OpName %d "d"
1306 OpName %BaseColor "BaseColor"
1307 OpName %OutColor "OutColor"
1308 OpDecorate %x Flat
1309 OpDecorate %x Location 1
1310 OpDecorate %BaseColor Location 0
1311 OpDecorate %OutColor Location 0
1312 %void = OpTypeVoid
1313 %3 = OpTypeFunction %void
1314 %int = OpTypeInt 32 1
1315 %_ptr_Input_int = OpTypePointer Input %int
1316 %x = OpVariable %_ptr_Input_int Input
1317 %float = OpTypeFloat 32
1318 %_ptr_Function_float = OpTypePointer Function %float
1319 %v4float = OpTypeVector %float 4
1320 %_ptr_Input_v4float = OpTypePointer Input %v4float
1321 %BaseColor = OpVariable %_ptr_Input_v4float Input
1322 %uint = OpTypeInt 32 0
1323 %uint_1 = OpConstant %uint 1
1324 %_ptr_Input_float = OpTypePointer Input %float
1325 %_ptr_Output_v4float = OpTypePointer Output %v4float
1326 %OutColor = OpVariable %_ptr_Output_v4float Output
1327 %float_1 = OpConstant %float 1
1328 %27 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1329 ; CHECK: = OpFunction
1330 ; CHECK-NEXT: = OpLabel
1331 ; CHECK-NEXT: OpBranch [[target:%\w+]]
1332 ; CHECK-NEXT: [[target]] = OpLabel
1333 %main = OpFunction %void None %3
1334 %5 = OpLabel
1335 %d = OpVariable %_ptr_Function_float Function
1336 %9 = OpLoad %int %x
1337 OpSelectionMerge %11 None
1338 OpSwitch %9 %11 0 %10
1339 %10 = OpLabel
1340 %21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1341 %22 = OpLoad %float %21
1342 OpStore %d %22
1343 OpBranch %11
1344 %11 = OpLabel
1345 OpStore %OutColor %27
1346 OpReturn
1347 OpFunctionEnd)";
1348
1349 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
1350 }
1351
TEST_F(AggressiveDCETest,EliminateDeadIfThenElseNested)1352 TEST_F(AggressiveDCETest, EliminateDeadIfThenElseNested) {
1353 // #version 450
1354 //
1355 // layout(location = 0) in vec4 BaseColor;
1356 // layout(location = 0) out vec4 OutColor;
1357 //
1358 // void main()
1359 // {
1360 // float d;
1361 // if (BaseColor.x == 0)
1362 // if (BaseColor.y == 0)
1363 // d = 0.0;
1364 // else
1365 // d = 0.25;
1366 // else
1367 // if (BaseColor.y == 0)
1368 // d = 0.5;
1369 // else
1370 // d = 0.75;
1371 // OutColor = vec4(1.0,1.0,1.0,1.0);
1372 // }
1373
1374 const std::string spirv =
1375 R"(OpCapability Shader
1376 %1 = OpExtInstImport "GLSL.std.450"
1377 OpMemoryModel Logical GLSL450
1378 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1379 OpExecutionMode %main OriginUpperLeft
1380 OpSource GLSL 450
1381 OpName %main "main"
1382 OpName %BaseColor "BaseColor"
1383 OpName %d "d"
1384 OpName %OutColor "OutColor"
1385 OpDecorate %BaseColor Location 0
1386 OpDecorate %OutColor Location 0
1387 %void = OpTypeVoid
1388 %7 = OpTypeFunction %void
1389 %float = OpTypeFloat 32
1390 %v4float = OpTypeVector %float 4
1391 %_ptr_Input_v4float = OpTypePointer Input %v4float
1392 %BaseColor = OpVariable %_ptr_Input_v4float Input
1393 %uint = OpTypeInt 32 0
1394 %uint_0 = OpConstant %uint 0
1395 %_ptr_Input_float = OpTypePointer Input %float
1396 %float_0 = OpConstant %float 0
1397 %bool = OpTypeBool
1398 %uint_1 = OpConstant %uint 1
1399 %_ptr_Function_float = OpTypePointer Function %float
1400 %float_0_25 = OpConstant %float 0.25
1401 %float_0_5 = OpConstant %float 0.5
1402 %float_0_75 = OpConstant %float 0.75
1403 %_ptr_Output_v4float = OpTypePointer Output %v4float
1404 %OutColor = OpVariable %_ptr_Output_v4float Output
1405 %float_1 = OpConstant %float 1
1406 %23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
1407
1408 ; CHECK: = OpFunction
1409 ; CHECK-NEXT: = OpLabel
1410 ; CHECK-NEXT: OpBranch [[target:%\w+]]
1411 ; CHECK-NEXT: [[target]] = OpLabel
1412 ; CHECK-NOT: OpLabel
1413
1414 %main = OpFunction %void None %7
1415 %24 = OpLabel
1416 %d = OpVariable %_ptr_Function_float Function
1417 %25 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1418 %26 = OpLoad %float %25
1419 %27 = OpFOrdEqual %bool %26 %float_0
1420 OpSelectionMerge %28 None
1421 OpBranchConditional %27 %29 %30
1422 %29 = OpLabel
1423 %31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1424 %32 = OpLoad %float %31
1425 %33 = OpFOrdEqual %bool %32 %float_0
1426 OpSelectionMerge %34 None
1427 OpBranchConditional %33 %35 %36
1428 %35 = OpLabel
1429 OpStore %d %float_0
1430 OpBranch %34
1431 %36 = OpLabel
1432 OpStore %d %float_0_25
1433 OpBranch %34
1434 %34 = OpLabel
1435 OpBranch %28
1436 %30 = OpLabel
1437 %37 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1438 %38 = OpLoad %float %37
1439 %39 = OpFOrdEqual %bool %38 %float_0
1440 OpSelectionMerge %40 None
1441 OpBranchConditional %39 %41 %42
1442 %41 = OpLabel
1443 OpStore %d %float_0_5
1444 OpBranch %40
1445 %42 = OpLabel
1446 OpStore %d %float_0_75
1447 OpBranch %40
1448 %40 = OpLabel
1449 OpBranch %28
1450 %28 = OpLabel
1451 OpStore %OutColor %23
1452 OpReturn
1453 OpFunctionEnd
1454 )";
1455
1456 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
1457 }
1458
TEST_F(AggressiveDCETest,NoEliminateLiveIfThenElse)1459 TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElse) {
1460 // #version 450
1461 //
1462 // layout(location = 0) in vec4 BaseColor;
1463 // layout(location = 0) out vec4 OutColor;
1464 //
1465 // void main()
1466 // {
1467 // float t;
1468 // if (BaseColor.x == 0)
1469 // t = BaseColor.y;
1470 // else
1471 // t = BaseColor.z;
1472 // OutColor = vec4(t);
1473 // }
1474
1475 const std::string assembly =
1476 R"(OpCapability Shader
1477 %1 = OpExtInstImport "GLSL.std.450"
1478 OpMemoryModel Logical GLSL450
1479 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1480 OpExecutionMode %main OriginUpperLeft
1481 OpSource GLSL 450
1482 OpName %main "main"
1483 OpName %BaseColor "BaseColor"
1484 OpName %t "t"
1485 OpName %OutColor "OutColor"
1486 OpDecorate %BaseColor Location 0
1487 OpDecorate %OutColor Location 0
1488 %void = OpTypeVoid
1489 %7 = OpTypeFunction %void
1490 %float = OpTypeFloat 32
1491 %v4float = OpTypeVector %float 4
1492 %_ptr_Input_v4float = OpTypePointer Input %v4float
1493 %BaseColor = OpVariable %_ptr_Input_v4float Input
1494 %uint = OpTypeInt 32 0
1495 %uint_0 = OpConstant %uint 0
1496 %_ptr_Input_float = OpTypePointer Input %float
1497 %float_0 = OpConstant %float 0
1498 %bool = OpTypeBool
1499 %_ptr_Function_float = OpTypePointer Function %float
1500 %uint_1 = OpConstant %uint 1
1501 %uint_2 = OpConstant %uint 2
1502 %_ptr_Output_v4float = OpTypePointer Output %v4float
1503 %OutColor = OpVariable %_ptr_Output_v4float Output
1504 %main = OpFunction %void None %7
1505 %20 = OpLabel
1506 %t = OpVariable %_ptr_Function_float Function
1507 %21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1508 %22 = OpLoad %float %21
1509 %23 = OpFOrdEqual %bool %22 %float_0
1510 OpSelectionMerge %24 None
1511 OpBranchConditional %23 %25 %26
1512 %25 = OpLabel
1513 %27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1514 %28 = OpLoad %float %27
1515 OpStore %t %28
1516 OpBranch %24
1517 %26 = OpLabel
1518 %29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2
1519 %30 = OpLoad %float %29
1520 OpStore %t %30
1521 OpBranch %24
1522 %24 = OpLabel
1523 %31 = OpLoad %float %t
1524 %32 = OpCompositeConstruct %v4float %31 %31 %31 %31
1525 OpStore %OutColor %32
1526 OpReturn
1527 OpFunctionEnd
1528 )";
1529
1530 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1531 }
1532
TEST_F(AggressiveDCETest,NoEliminateLiveIfThenElseNested)1533 TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElseNested) {
1534 // #version 450
1535 //
1536 // layout(location = 0) in vec4 BaseColor;
1537 // layout(location = 0) out vec4 OutColor;
1538 //
1539 // void main()
1540 // {
1541 // float t;
1542 // if (BaseColor.x == 0)
1543 // if (BaseColor.y == 0)
1544 // t = 0.0;
1545 // else
1546 // t = 0.25;
1547 // else
1548 // if (BaseColor.y == 0)
1549 // t = 0.5;
1550 // else
1551 // t = 0.75;
1552 // OutColor = vec4(t);
1553 // }
1554
1555 const std::string assembly =
1556 R"(OpCapability Shader
1557 %1 = OpExtInstImport "GLSL.std.450"
1558 OpMemoryModel Logical GLSL450
1559 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1560 OpExecutionMode %main OriginUpperLeft
1561 OpSource GLSL 450
1562 OpName %main "main"
1563 OpName %BaseColor "BaseColor"
1564 OpName %t "t"
1565 OpName %OutColor "OutColor"
1566 OpDecorate %BaseColor Location 0
1567 OpDecorate %OutColor Location 0
1568 %void = OpTypeVoid
1569 %7 = OpTypeFunction %void
1570 %float = OpTypeFloat 32
1571 %v4float = OpTypeVector %float 4
1572 %_ptr_Input_v4float = OpTypePointer Input %v4float
1573 %BaseColor = OpVariable %_ptr_Input_v4float Input
1574 %uint = OpTypeInt 32 0
1575 %uint_0 = OpConstant %uint 0
1576 %_ptr_Input_float = OpTypePointer Input %float
1577 %float_0 = OpConstant %float 0
1578 %bool = OpTypeBool
1579 %uint_1 = OpConstant %uint 1
1580 %_ptr_Function_float = OpTypePointer Function %float
1581 %float_0_25 = OpConstant %float 0.25
1582 %float_0_5 = OpConstant %float 0.5
1583 %float_0_75 = OpConstant %float 0.75
1584 %_ptr_Output_v4float = OpTypePointer Output %v4float
1585 %OutColor = OpVariable %_ptr_Output_v4float Output
1586 %main = OpFunction %void None %7
1587 %22 = OpLabel
1588 %t = OpVariable %_ptr_Function_float Function
1589 %23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1590 %24 = OpLoad %float %23
1591 %25 = OpFOrdEqual %bool %24 %float_0
1592 OpSelectionMerge %26 None
1593 OpBranchConditional %25 %27 %28
1594 %27 = OpLabel
1595 %29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1596 %30 = OpLoad %float %29
1597 %31 = OpFOrdEqual %bool %30 %float_0
1598 OpSelectionMerge %32 None
1599 OpBranchConditional %31 %33 %34
1600 %33 = OpLabel
1601 OpStore %t %float_0
1602 OpBranch %32
1603 %34 = OpLabel
1604 OpStore %t %float_0_25
1605 OpBranch %32
1606 %32 = OpLabel
1607 OpBranch %26
1608 %28 = OpLabel
1609 %35 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
1610 %36 = OpLoad %float %35
1611 %37 = OpFOrdEqual %bool %36 %float_0
1612 OpSelectionMerge %38 None
1613 OpBranchConditional %37 %39 %40
1614 %39 = OpLabel
1615 OpStore %t %float_0_5
1616 OpBranch %38
1617 %40 = OpLabel
1618 OpStore %t %float_0_75
1619 OpBranch %38
1620 %38 = OpLabel
1621 OpBranch %26
1622 %26 = OpLabel
1623 %41 = OpLoad %float %t
1624 %42 = OpCompositeConstruct %v4float %41 %41 %41 %41
1625 OpStore %OutColor %42
1626 OpReturn
1627 OpFunctionEnd
1628 )";
1629
1630 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1631 }
1632
TEST_F(AggressiveDCETest,NoEliminateIfWithPhi)1633 TEST_F(AggressiveDCETest, NoEliminateIfWithPhi) {
1634 // Note: Assembly hand-optimized from GLSL
1635 //
1636 // #version 450
1637 //
1638 // layout(location = 0) in vec4 BaseColor;
1639 // layout(location = 0) out vec4 OutColor;
1640 //
1641 // void main()
1642 // {
1643 // float t;
1644 // if (BaseColor.x == 0)
1645 // t = 0.0;
1646 // else
1647 // t = 1.0;
1648 // OutColor = vec4(t);
1649 // }
1650
1651 const std::string assembly =
1652 R"(OpCapability Shader
1653 %1 = OpExtInstImport "GLSL.std.450"
1654 OpMemoryModel Logical GLSL450
1655 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
1656 OpExecutionMode %main OriginUpperLeft
1657 OpSource GLSL 450
1658 OpName %main "main"
1659 OpName %BaseColor "BaseColor"
1660 OpName %OutColor "OutColor"
1661 OpDecorate %BaseColor Location 0
1662 OpDecorate %OutColor Location 0
1663 %void = OpTypeVoid
1664 %6 = OpTypeFunction %void
1665 %float = OpTypeFloat 32
1666 %v4float = OpTypeVector %float 4
1667 %_ptr_Input_v4float = OpTypePointer Input %v4float
1668 %BaseColor = OpVariable %_ptr_Input_v4float Input
1669 %uint = OpTypeInt 32 0
1670 %uint_0 = OpConstant %uint 0
1671 %_ptr_Input_float = OpTypePointer Input %float
1672 %float_0 = OpConstant %float 0
1673 %bool = OpTypeBool
1674 %float_1 = OpConstant %float 1
1675 %_ptr_Output_v4float = OpTypePointer Output %v4float
1676 %OutColor = OpVariable %_ptr_Output_v4float Output
1677 %main = OpFunction %void None %6
1678 %17 = OpLabel
1679 %18 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
1680 %19 = OpLoad %float %18
1681 %20 = OpFOrdEqual %bool %19 %float_0
1682 OpSelectionMerge %21 None
1683 OpBranchConditional %20 %22 %23
1684 %22 = OpLabel
1685 OpBranch %21
1686 %23 = OpLabel
1687 OpBranch %21
1688 %21 = OpLabel
1689 %24 = OpPhi %float %float_0 %22 %float_1 %23
1690 %25 = OpCompositeConstruct %v4float %24 %24 %24 %24
1691 OpStore %OutColor %25
1692 OpReturn
1693 OpFunctionEnd
1694 )";
1695
1696 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1697 }
1698
TEST_F(AggressiveDCETest,NoEliminateIfBreak)1699 TEST_F(AggressiveDCETest, NoEliminateIfBreak) {
1700 // Note: Assembly optimized from GLSL
1701 //
1702 // #version 450
1703 //
1704 // layout(location=0) in vec4 InColor;
1705 // layout(location=0) out vec4 OutColor;
1706 //
1707 // void main()
1708 // {
1709 // float f = 0.0;
1710 // for (;;) {
1711 // f += 2.0;
1712 // if (f > 20.0)
1713 // break;
1714 // }
1715 //
1716 // OutColor = InColor / f;
1717 // }
1718
1719 const std::string assembly =
1720 R"(OpCapability Shader
1721 %1 = OpExtInstImport "GLSL.std.450"
1722 OpMemoryModel Logical GLSL450
1723 OpEntryPoint Fragment %main "main" %OutColor %InColor
1724 OpExecutionMode %main OriginUpperLeft
1725 OpSource GLSL 450
1726 OpName %main "main"
1727 OpName %f "f"
1728 OpName %OutColor "OutColor"
1729 OpName %InColor "InColor"
1730 OpDecorate %OutColor Location 0
1731 OpDecorate %InColor Location 0
1732 %void = OpTypeVoid
1733 %7 = OpTypeFunction %void
1734 %float = OpTypeFloat 32
1735 %_ptr_Function_float = OpTypePointer Function %float
1736 %float_0 = OpConstant %float 0
1737 %float_2 = OpConstant %float 2
1738 %float_20 = OpConstant %float 20
1739 %bool = OpTypeBool
1740 %v4float = OpTypeVector %float 4
1741 %_ptr_Output_v4float = OpTypePointer Output %v4float
1742 %OutColor = OpVariable %_ptr_Output_v4float Output
1743 %_ptr_Input_v4float = OpTypePointer Input %v4float
1744 %InColor = OpVariable %_ptr_Input_v4float Input
1745 %main = OpFunction %void None %7
1746 %17 = OpLabel
1747 %f = OpVariable %_ptr_Function_float Function
1748 OpStore %f %float_0
1749 OpBranch %18
1750 %18 = OpLabel
1751 OpLoopMerge %19 %20 None
1752 OpBranch %21
1753 %21 = OpLabel
1754 %22 = OpLoad %float %f
1755 %23 = OpFAdd %float %22 %float_2
1756 OpStore %f %23
1757 %24 = OpLoad %float %f
1758 %25 = OpFOrdGreaterThan %bool %24 %float_20
1759 OpSelectionMerge %26 None
1760 OpBranchConditional %25 %27 %26
1761 %27 = OpLabel
1762 OpBranch %19
1763 %26 = OpLabel
1764 OpBranch %20
1765 %20 = OpLabel
1766 OpBranch %18
1767 %19 = OpLabel
1768 %28 = OpLoad %v4float %InColor
1769 %29 = OpLoad %float %f
1770 %30 = OpCompositeConstruct %v4float %29 %29 %29 %29
1771 %31 = OpFDiv %v4float %28 %30
1772 OpStore %OutColor %31
1773 OpReturn
1774 OpFunctionEnd
1775 )";
1776
1777 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1778 }
1779
TEST_F(AggressiveDCETest,NoEliminateIfBreak2)1780 TEST_F(AggressiveDCETest, NoEliminateIfBreak2) {
1781 // Do not eliminate break as conditional branch with merge instruction
1782 // Note: SPIR-V edited to add merge instruction before break.
1783 //
1784 // #version 430
1785 //
1786 // layout(std430) buffer U_t
1787 // {
1788 // float g_F[10];
1789 // };
1790 //
1791 // layout(location = 0)out float o;
1792 //
1793 // void main(void)
1794 // {
1795 // float s = 0.0;
1796 // for (int i=0; i<10; i++)
1797 // s += g_F[i];
1798 // o = s;
1799 // }
1800
1801 const std::string assembly =
1802 R"(OpCapability Shader
1803 %1 = OpExtInstImport "GLSL.std.450"
1804 OpMemoryModel Logical GLSL450
1805 OpEntryPoint Fragment %main "main" %o
1806 OpExecutionMode %main OriginUpperLeft
1807 OpSource GLSL 430
1808 OpName %main "main"
1809 OpName %s "s"
1810 OpName %i "i"
1811 OpName %U_t "U_t"
1812 OpMemberName %U_t 0 "g_F"
1813 OpName %_ ""
1814 OpName %o "o"
1815 OpDecorate %_arr_float_uint_10 ArrayStride 4
1816 OpMemberDecorate %U_t 0 Offset 0
1817 OpDecorate %U_t BufferBlock
1818 OpDecorate %_ DescriptorSet 0
1819 OpDecorate %o Location 0
1820 %void = OpTypeVoid
1821 %10 = OpTypeFunction %void
1822 %float = OpTypeFloat 32
1823 %_ptr_Function_float = OpTypePointer Function %float
1824 %float_0 = OpConstant %float 0
1825 %int = OpTypeInt 32 1
1826 %_ptr_Function_int = OpTypePointer Function %int
1827 %int_0 = OpConstant %int 0
1828 %int_10 = OpConstant %int 10
1829 %bool = OpTypeBool
1830 %uint = OpTypeInt 32 0
1831 %uint_10 = OpConstant %uint 10
1832 %_arr_float_uint_10 = OpTypeArray %float %uint_10
1833 %U_t = OpTypeStruct %_arr_float_uint_10
1834 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
1835 %_ = OpVariable %_ptr_Uniform_U_t Uniform
1836 %_ptr_Uniform_float = OpTypePointer Uniform %float
1837 %int_1 = OpConstant %int 1
1838 %_ptr_Output_float = OpTypePointer Output %float
1839 %o = OpVariable %_ptr_Output_float Output
1840 %main = OpFunction %void None %10
1841 %25 = OpLabel
1842 %s = OpVariable %_ptr_Function_float Function
1843 %i = OpVariable %_ptr_Function_int Function
1844 OpStore %s %float_0
1845 OpStore %i %int_0
1846 OpBranch %26
1847 %26 = OpLabel
1848 OpLoopMerge %27 %28 None
1849 OpBranch %29
1850 %29 = OpLabel
1851 %30 = OpLoad %int %i
1852 %31 = OpSLessThan %bool %30 %int_10
1853 OpSelectionMerge %32 None
1854 OpBranchConditional %31 %32 %27
1855 %32 = OpLabel
1856 %33 = OpLoad %int %i
1857 %34 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %33
1858 %35 = OpLoad %float %34
1859 %36 = OpLoad %float %s
1860 %37 = OpFAdd %float %36 %35
1861 OpStore %s %37
1862 OpBranch %28
1863 %28 = OpLabel
1864 %38 = OpLoad %int %i
1865 %39 = OpIAdd %int %38 %int_1
1866 OpStore %i %39
1867 OpBranch %26
1868 %27 = OpLabel
1869 %40 = OpLoad %float %s
1870 OpStore %o %40
1871 OpReturn
1872 OpFunctionEnd
1873 )";
1874
1875 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
1876 }
1877
TEST_F(AggressiveDCETest,EliminateEntireUselessLoop)1878 TEST_F(AggressiveDCETest, EliminateEntireUselessLoop) {
1879 // #version 140
1880 // in vec4 BaseColor;
1881 //
1882 // layout(std140) uniform U_t
1883 // {
1884 // int g_I ;
1885 // } ;
1886 //
1887 // void main()
1888 // {
1889 // vec4 v = BaseColor;
1890 // float df = 0.0;
1891 // int i = 0;
1892 // while (i < g_I) {
1893 // df = df * 0.5;
1894 // i = i + 1;
1895 // }
1896 // gl_FragColor = v;
1897 // }
1898
1899 const std::string predefs1 =
1900 R"(OpCapability Shader
1901 %1 = OpExtInstImport "GLSL.std.450"
1902 OpMemoryModel Logical GLSL450
1903 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
1904 OpExecutionMode %main OriginUpperLeft
1905 OpSource GLSL 140
1906 )";
1907
1908 const std::string names_before =
1909 R"(OpName %main "main"
1910 OpName %v "v"
1911 OpName %BaseColor "BaseColor"
1912 OpName %df "df"
1913 OpName %i "i"
1914 OpName %U_t "U_t"
1915 OpMemberName %U_t 0 "g_I"
1916 OpName %_ ""
1917 OpName %gl_FragColor "gl_FragColor"
1918 )";
1919
1920 const std::string names_after =
1921 R"(OpName %main "main"
1922 OpName %v "v"
1923 OpName %BaseColor "BaseColor"
1924 OpName %gl_FragColor "gl_FragColor"
1925 )";
1926
1927 const std::string predefs2_before =
1928 R"(OpMemberDecorate %U_t 0 Offset 0
1929 OpDecorate %U_t Block
1930 OpDecorate %_ DescriptorSet 0
1931 %void = OpTypeVoid
1932 %11 = OpTypeFunction %void
1933 %float = OpTypeFloat 32
1934 %v4float = OpTypeVector %float 4
1935 %_ptr_Function_v4float = OpTypePointer Function %v4float
1936 %_ptr_Input_v4float = OpTypePointer Input %v4float
1937 %BaseColor = OpVariable %_ptr_Input_v4float Input
1938 %_ptr_Function_float = OpTypePointer Function %float
1939 %float_0 = OpConstant %float 0
1940 %int = OpTypeInt 32 1
1941 %_ptr_Function_int = OpTypePointer Function %int
1942 %int_0 = OpConstant %int 0
1943 %U_t = OpTypeStruct %int
1944 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
1945 %_ = OpVariable %_ptr_Uniform_U_t Uniform
1946 %_ptr_Uniform_int = OpTypePointer Uniform %int
1947 %bool = OpTypeBool
1948 %float_0_5 = OpConstant %float 0.5
1949 %int_1 = OpConstant %int 1
1950 %_ptr_Output_v4float = OpTypePointer Output %v4float
1951 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
1952 )";
1953
1954 const std::string predefs2_after =
1955 R"(%void = OpTypeVoid
1956 %11 = OpTypeFunction %void
1957 %float = OpTypeFloat 32
1958 %v4float = OpTypeVector %float 4
1959 %_ptr_Function_v4float = OpTypePointer Function %v4float
1960 %_ptr_Input_v4float = OpTypePointer Input %v4float
1961 %BaseColor = OpVariable %_ptr_Input_v4float Input
1962 %_ptr_Output_v4float = OpTypePointer Output %v4float
1963 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
1964 )";
1965
1966 const std::string func_before =
1967 R"(%main = OpFunction %void None %11
1968 %27 = OpLabel
1969 %v = OpVariable %_ptr_Function_v4float Function
1970 %df = OpVariable %_ptr_Function_float Function
1971 %i = OpVariable %_ptr_Function_int Function
1972 %28 = OpLoad %v4float %BaseColor
1973 OpStore %v %28
1974 OpStore %df %float_0
1975 OpStore %i %int_0
1976 OpBranch %29
1977 %29 = OpLabel
1978 OpLoopMerge %30 %31 None
1979 OpBranch %32
1980 %32 = OpLabel
1981 %33 = OpLoad %int %i
1982 %34 = OpAccessChain %_ptr_Uniform_int %_ %int_0
1983 %35 = OpLoad %int %34
1984 %36 = OpSLessThan %bool %33 %35
1985 OpBranchConditional %36 %37 %30
1986 %37 = OpLabel
1987 %38 = OpLoad %float %df
1988 %39 = OpFMul %float %38 %float_0_5
1989 OpStore %df %39
1990 %40 = OpLoad %int %i
1991 %41 = OpIAdd %int %40 %int_1
1992 OpStore %i %41
1993 OpBranch %31
1994 %31 = OpLabel
1995 OpBranch %29
1996 %30 = OpLabel
1997 %42 = OpLoad %v4float %v
1998 OpStore %gl_FragColor %42
1999 OpReturn
2000 OpFunctionEnd
2001 )";
2002
2003 const std::string func_after =
2004 R"(%main = OpFunction %void None %11
2005 %27 = OpLabel
2006 %v = OpVariable %_ptr_Function_v4float Function
2007 %28 = OpLoad %v4float %BaseColor
2008 OpStore %v %28
2009 OpBranch %29
2010 %29 = OpLabel
2011 OpBranch %30
2012 %30 = OpLabel
2013 %42 = OpLoad %v4float %v
2014 OpStore %gl_FragColor %42
2015 OpReturn
2016 OpFunctionEnd
2017 )";
2018
2019 SinglePassRunAndCheck<AggressiveDCEPass>(
2020 predefs1 + names_before + predefs2_before + func_before,
2021 predefs1 + names_after + predefs2_after + func_after, true, true);
2022 }
2023
TEST_F(AggressiveDCETest,NoEliminateBusyLoop)2024 TEST_F(AggressiveDCETest, NoEliminateBusyLoop) {
2025 // Note: SPIR-V edited to replace AtomicAdd(i,0) with AtomicLoad(i)
2026 //
2027 // #version 450
2028 //
2029 // layout(std430) buffer I_t
2030 // {
2031 // int g_I;
2032 // int g_I2;
2033 // };
2034 //
2035 // layout(location = 0) out int o;
2036 //
2037 // void main(void)
2038 // {
2039 // while (atomicAdd(g_I, 0) == 0) {}
2040 // o = g_I2;
2041 // }
2042
2043 const std::string assembly =
2044 R"(OpCapability Shader
2045 %1 = OpExtInstImport "GLSL.std.450"
2046 OpMemoryModel Logical GLSL450
2047 OpEntryPoint Fragment %main "main" %o
2048 OpExecutionMode %main OriginUpperLeft
2049 OpSource GLSL 450
2050 OpName %main "main"
2051 OpName %I_t "I_t"
2052 OpMemberName %I_t 0 "g_I"
2053 OpMemberName %I_t 1 "g_I2"
2054 OpName %_ ""
2055 OpName %o "o"
2056 OpMemberDecorate %I_t 0 Offset 0
2057 OpMemberDecorate %I_t 1 Offset 4
2058 OpDecorate %I_t BufferBlock
2059 OpDecorate %_ DescriptorSet 0
2060 OpDecorate %o Location 0
2061 %void = OpTypeVoid
2062 %7 = OpTypeFunction %void
2063 %int = OpTypeInt 32 1
2064 %I_t = OpTypeStruct %int %int
2065 %_ptr_Uniform_I_t = OpTypePointer Uniform %I_t
2066 %_ = OpVariable %_ptr_Uniform_I_t Uniform
2067 %int_0 = OpConstant %int 0
2068 %int_1 = OpConstant %int 1
2069 %_ptr_Uniform_int = OpTypePointer Uniform %int
2070 %uint = OpTypeInt 32 0
2071 %uint_1 = OpConstant %uint 1
2072 %uint_0 = OpConstant %uint 0
2073 %bool = OpTypeBool
2074 %_ptr_Output_int = OpTypePointer Output %int
2075 %o = OpVariable %_ptr_Output_int Output
2076 %main = OpFunction %void None %7
2077 %18 = OpLabel
2078 OpBranch %19
2079 %19 = OpLabel
2080 OpLoopMerge %20 %21 None
2081 OpBranch %22
2082 %22 = OpLabel
2083 %23 = OpAccessChain %_ptr_Uniform_int %_ %int_0
2084 %24 = OpAtomicLoad %int %23 %uint_1 %uint_0
2085 %25 = OpIEqual %bool %24 %int_0
2086 OpBranchConditional %25 %26 %20
2087 %26 = OpLabel
2088 OpBranch %21
2089 %21 = OpLabel
2090 OpBranch %19
2091 %20 = OpLabel
2092 %27 = OpAccessChain %_ptr_Uniform_int %_ %int_1
2093 %28 = OpLoad %int %27
2094 OpStore %o %28
2095 OpReturn
2096 OpFunctionEnd
2097 )";
2098
2099 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
2100 }
2101
TEST_F(AggressiveDCETest,NoEliminateLiveLoop)2102 TEST_F(AggressiveDCETest, NoEliminateLiveLoop) {
2103 // Note: SPIR-V optimized
2104 //
2105 // #version 430
2106 //
2107 // layout(std430) buffer U_t
2108 // {
2109 // float g_F[10];
2110 // };
2111 //
2112 // layout(location = 0)out float o;
2113 //
2114 // void main(void)
2115 // {
2116 // float s = 0.0;
2117 // for (int i=0; i<10; i++)
2118 // s += g_F[i];
2119 // o = s;
2120 // }
2121
2122 const std::string assembly =
2123 R"(OpCapability Shader
2124 %1 = OpExtInstImport "GLSL.std.450"
2125 OpMemoryModel Logical GLSL450
2126 OpEntryPoint Fragment %main "main" %o
2127 OpExecutionMode %main OriginUpperLeft
2128 OpSource GLSL 430
2129 OpName %main "main"
2130 OpName %U_t "U_t"
2131 OpMemberName %U_t 0 "g_F"
2132 OpName %_ ""
2133 OpName %o "o"
2134 OpDecorate %_arr_float_uint_10 ArrayStride 4
2135 OpMemberDecorate %U_t 0 Offset 0
2136 OpDecorate %U_t BufferBlock
2137 OpDecorate %_ DescriptorSet 0
2138 OpDecorate %o Location 0
2139 %void = OpTypeVoid
2140 %8 = OpTypeFunction %void
2141 %float = OpTypeFloat 32
2142 %float_0 = OpConstant %float 0
2143 %int = OpTypeInt 32 1
2144 %int_0 = OpConstant %int 0
2145 %int_10 = OpConstant %int 10
2146 %bool = OpTypeBool
2147 %uint = OpTypeInt 32 0
2148 %uint_10 = OpConstant %uint 10
2149 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2150 %U_t = OpTypeStruct %_arr_float_uint_10
2151 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2152 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2153 %_ptr_Uniform_float = OpTypePointer Uniform %float
2154 %int_1 = OpConstant %int 1
2155 %_ptr_Output_float = OpTypePointer Output %float
2156 %o = OpVariable %_ptr_Output_float Output
2157 %main = OpFunction %void None %8
2158 %21 = OpLabel
2159 OpBranch %22
2160 %22 = OpLabel
2161 %23 = OpPhi %float %float_0 %21 %24 %25
2162 %26 = OpPhi %int %int_0 %21 %27 %25
2163 OpLoopMerge %28 %25 None
2164 OpBranch %29
2165 %29 = OpLabel
2166 %30 = OpSLessThan %bool %26 %int_10
2167 OpBranchConditional %30 %31 %28
2168 %31 = OpLabel
2169 %32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %26
2170 %33 = OpLoad %float %32
2171 %24 = OpFAdd %float %23 %33
2172 OpBranch %25
2173 %25 = OpLabel
2174 %27 = OpIAdd %int %26 %int_1
2175 OpBranch %22
2176 %28 = OpLabel
2177 OpStore %o %23
2178 OpReturn
2179 OpFunctionEnd
2180 )";
2181
2182 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
2183 }
2184
TEST_F(AggressiveDCETest,EliminateEntireFunctionBody)2185 TEST_F(AggressiveDCETest, EliminateEntireFunctionBody) {
2186 // #version 450
2187 //
2188 // layout(location = 0) in vec4 BaseColor;
2189 // layout(location = 0) out vec4 OutColor;
2190 //
2191 // void main()
2192 // {
2193 // float d;
2194 // if (BaseColor.x == 0)
2195 // d = BaseColor.y;
2196 // else
2197 // d = BaseColor.z;
2198 // }
2199
2200 const std::string spirv =
2201 R"(OpCapability Shader
2202 %1 = OpExtInstImport "GLSL.std.450"
2203 OpMemoryModel Logical GLSL450
2204 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
2205 OpExecutionMode %main OriginUpperLeft
2206 OpSource GLSL 450
2207 OpName %main "main"
2208 OpName %BaseColor "BaseColor"
2209 OpName %d "d"
2210 OpName %OutColor "OutColor"
2211 OpDecorate %BaseColor Location 0
2212 OpDecorate %OutColor Location 0
2213 %void = OpTypeVoid
2214 %7 = OpTypeFunction %void
2215 %float = OpTypeFloat 32
2216 %v4float = OpTypeVector %float 4
2217 %_ptr_Input_v4float = OpTypePointer Input %v4float
2218 %BaseColor = OpVariable %_ptr_Input_v4float Input
2219 %uint = OpTypeInt 32 0
2220 %uint_0 = OpConstant %uint 0
2221 %_ptr_Input_float = OpTypePointer Input %float
2222 %float_0 = OpConstant %float 0
2223 %bool = OpTypeBool
2224 %_ptr_Function_float = OpTypePointer Function %float
2225 %uint_1 = OpConstant %uint 1
2226 %uint_2 = OpConstant %uint 2
2227 %_ptr_Output_v4float = OpTypePointer Output %v4float
2228 %OutColor = OpVariable %_ptr_Output_v4float Output
2229
2230 ; CHECK: = OpFunction
2231 ; CHECK-NEXT: = OpLabel
2232 ; CHECK-NEXT: OpBranch [[target:%\w+]]
2233 ; CHECK-NEXT: [[target]] = OpLabel
2234 ; CHECK-NEXT: OpReturn
2235 ; CHECK-NEXT: OpFunctionEnd
2236
2237 %main = OpFunction %void None %7
2238 %20 = OpLabel
2239 %d = OpVariable %_ptr_Function_float Function
2240 %21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0
2241 %22 = OpLoad %float %21
2242 %23 = OpFOrdEqual %bool %22 %float_0
2243 OpSelectionMerge %24 None
2244 OpBranchConditional %23 %25 %26
2245 %25 = OpLabel
2246 %27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1
2247 %28 = OpLoad %float %27
2248 OpStore %d %28
2249 OpBranch %24
2250 %26 = OpLabel
2251 %29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2
2252 %30 = OpLoad %float %29
2253 OpStore %d %30
2254 OpBranch %24
2255 %24 = OpLabel
2256 OpReturn
2257 OpFunctionEnd
2258 )";
2259
2260 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
2261 }
2262
TEST_F(AggressiveDCETest,EliminateUselessInnerLoop)2263 TEST_F(AggressiveDCETest, EliminateUselessInnerLoop) {
2264 // #version 430
2265 //
2266 // layout(std430) buffer U_t
2267 // {
2268 // float g_F[10];
2269 // };
2270 //
2271 // layout(location = 0)out float o;
2272 //
2273 // void main(void)
2274 // {
2275 // float s = 0.0;
2276 // for (int i=0; i<10; i++) {
2277 // for (int j=0; j<10; j++) {
2278 // }
2279 // s += g_F[i];
2280 // }
2281 // o = s;
2282 // }
2283
2284 const std::string predefs_before =
2285 R"(OpCapability Shader
2286 %1 = OpExtInstImport "GLSL.std.450"
2287 OpMemoryModel Logical GLSL450
2288 OpEntryPoint Fragment %main "main" %o
2289 OpExecutionMode %main OriginUpperLeft
2290 OpSource GLSL 430
2291 OpName %main "main"
2292 OpName %s "s"
2293 OpName %i "i"
2294 OpName %j "j"
2295 OpName %U_t "U_t"
2296 OpMemberName %U_t 0 "g_F"
2297 OpName %_ ""
2298 OpName %o "o"
2299 OpDecorate %_arr_float_uint_10 ArrayStride 4
2300 OpMemberDecorate %U_t 0 Offset 0
2301 OpDecorate %U_t BufferBlock
2302 OpDecorate %_ DescriptorSet 0
2303 OpDecorate %o Location 0
2304 %void = OpTypeVoid
2305 %11 = OpTypeFunction %void
2306 %float = OpTypeFloat 32
2307 %_ptr_Function_float = OpTypePointer Function %float
2308 %float_0 = OpConstant %float 0
2309 %int = OpTypeInt 32 1
2310 %_ptr_Function_int = OpTypePointer Function %int
2311 %int_0 = OpConstant %int 0
2312 %int_10 = OpConstant %int 10
2313 %bool = OpTypeBool
2314 %int_1 = OpConstant %int 1
2315 %uint = OpTypeInt 32 0
2316 %uint_10 = OpConstant %uint 10
2317 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2318 %U_t = OpTypeStruct %_arr_float_uint_10
2319 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2320 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2321 %_ptr_Uniform_float = OpTypePointer Uniform %float
2322 %_ptr_Output_float = OpTypePointer Output %float
2323 %o = OpVariable %_ptr_Output_float Output
2324 )";
2325
2326 const std::string predefs_after =
2327 R"(OpCapability Shader
2328 %1 = OpExtInstImport "GLSL.std.450"
2329 OpMemoryModel Logical GLSL450
2330 OpEntryPoint Fragment %main "main" %o
2331 OpExecutionMode %main OriginUpperLeft
2332 OpSource GLSL 430
2333 OpName %main "main"
2334 OpName %s "s"
2335 OpName %i "i"
2336 OpName %U_t "U_t"
2337 OpMemberName %U_t 0 "g_F"
2338 OpName %_ ""
2339 OpName %o "o"
2340 OpDecorate %_arr_float_uint_10 ArrayStride 4
2341 OpMemberDecorate %U_t 0 Offset 0
2342 OpDecorate %U_t BufferBlock
2343 OpDecorate %_ DescriptorSet 0
2344 OpDecorate %o Location 0
2345 %void = OpTypeVoid
2346 %11 = OpTypeFunction %void
2347 %float = OpTypeFloat 32
2348 %_ptr_Function_float = OpTypePointer Function %float
2349 %float_0 = OpConstant %float 0
2350 %int = OpTypeInt 32 1
2351 %_ptr_Function_int = OpTypePointer Function %int
2352 %int_0 = OpConstant %int 0
2353 %int_10 = OpConstant %int 10
2354 %bool = OpTypeBool
2355 %int_1 = OpConstant %int 1
2356 %uint = OpTypeInt 32 0
2357 %uint_10 = OpConstant %uint 10
2358 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2359 %U_t = OpTypeStruct %_arr_float_uint_10
2360 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2361 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2362 %_ptr_Uniform_float = OpTypePointer Uniform %float
2363 %_ptr_Output_float = OpTypePointer Output %float
2364 %o = OpVariable %_ptr_Output_float Output
2365 )";
2366
2367 const std::string func_before =
2368 R"(%main = OpFunction %void None %11
2369 %26 = OpLabel
2370 %s = OpVariable %_ptr_Function_float Function
2371 %i = OpVariable %_ptr_Function_int Function
2372 %j = OpVariable %_ptr_Function_int Function
2373 OpStore %s %float_0
2374 OpStore %i %int_0
2375 OpBranch %27
2376 %27 = OpLabel
2377 OpLoopMerge %28 %29 None
2378 OpBranch %30
2379 %30 = OpLabel
2380 %31 = OpLoad %int %i
2381 %32 = OpSLessThan %bool %31 %int_10
2382 OpBranchConditional %32 %33 %28
2383 %33 = OpLabel
2384 OpStore %j %int_0
2385 OpBranch %34
2386 %34 = OpLabel
2387 OpLoopMerge %35 %36 None
2388 OpBranch %37
2389 %37 = OpLabel
2390 %38 = OpLoad %int %j
2391 %39 = OpSLessThan %bool %38 %int_10
2392 OpBranchConditional %39 %40 %35
2393 %40 = OpLabel
2394 OpBranch %36
2395 %36 = OpLabel
2396 %41 = OpLoad %int %j
2397 %42 = OpIAdd %int %41 %int_1
2398 OpStore %j %42
2399 OpBranch %34
2400 %35 = OpLabel
2401 %43 = OpLoad %int %i
2402 %44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43
2403 %45 = OpLoad %float %44
2404 %46 = OpLoad %float %s
2405 %47 = OpFAdd %float %46 %45
2406 OpStore %s %47
2407 OpBranch %29
2408 %29 = OpLabel
2409 %48 = OpLoad %int %i
2410 %49 = OpIAdd %int %48 %int_1
2411 OpStore %i %49
2412 OpBranch %27
2413 %28 = OpLabel
2414 %50 = OpLoad %float %s
2415 OpStore %o %50
2416 OpReturn
2417 OpFunctionEnd
2418 )";
2419
2420 const std::string func_after =
2421 R"(%main = OpFunction %void None %11
2422 %26 = OpLabel
2423 %s = OpVariable %_ptr_Function_float Function
2424 %i = OpVariable %_ptr_Function_int Function
2425 OpStore %s %float_0
2426 OpStore %i %int_0
2427 OpBranch %27
2428 %27 = OpLabel
2429 OpLoopMerge %28 %29 None
2430 OpBranch %30
2431 %30 = OpLabel
2432 %31 = OpLoad %int %i
2433 %32 = OpSLessThan %bool %31 %int_10
2434 OpBranchConditional %32 %33 %28
2435 %33 = OpLabel
2436 OpBranch %34
2437 %34 = OpLabel
2438 OpBranch %35
2439 %35 = OpLabel
2440 %43 = OpLoad %int %i
2441 %44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43
2442 %45 = OpLoad %float %44
2443 %46 = OpLoad %float %s
2444 %47 = OpFAdd %float %46 %45
2445 OpStore %s %47
2446 OpBranch %29
2447 %29 = OpLabel
2448 %48 = OpLoad %int %i
2449 %49 = OpIAdd %int %48 %int_1
2450 OpStore %i %49
2451 OpBranch %27
2452 %28 = OpLabel
2453 %50 = OpLoad %float %s
2454 OpStore %o %50
2455 OpReturn
2456 OpFunctionEnd
2457 )";
2458
2459 SinglePassRunAndCheck<AggressiveDCEPass>(
2460 predefs_before + func_before, predefs_after + func_after, true, true);
2461 }
2462
TEST_F(AggressiveDCETest,EliminateUselessNestedLoopWithIf)2463 TEST_F(AggressiveDCETest, EliminateUselessNestedLoopWithIf) {
2464 // #version 430
2465 //
2466 // layout(std430) buffer U_t
2467 // {
2468 // float g_F[10][10];
2469 // };
2470 //
2471 // layout(location = 0)out float o;
2472 //
2473 // void main(void)
2474 // {
2475 // float s = 0.0;
2476 // for (int i=0; i<10; i++) {
2477 // for (int j=0; j<10; j++) {
2478 // float t = g_F[i][j];
2479 // if (t > 0.0)
2480 // s += t;
2481 // }
2482 // }
2483 // o = 0.0;
2484 // }
2485
2486 const std::string predefs_before =
2487 R"(OpCapability Shader
2488 %1 = OpExtInstImport "GLSL.std.450"
2489 OpMemoryModel Logical GLSL450
2490 OpEntryPoint Fragment %main "main" %o
2491 OpExecutionMode %main OriginUpperLeft
2492 OpSource GLSL 430
2493 OpName %main "main"
2494 OpName %s "s"
2495 OpName %i "i"
2496 OpName %j "j"
2497 OpName %U_t "U_t"
2498 OpMemberName %U_t 0 "g_F"
2499 OpName %_ ""
2500 OpName %o "o"
2501 OpDecorate %_arr_float_uint_10 ArrayStride 4
2502 OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40
2503 OpMemberDecorate %U_t 0 Offset 0
2504 OpDecorate %U_t BufferBlock
2505 OpDecorate %_ DescriptorSet 0
2506 OpDecorate %o Location 0
2507 %void = OpTypeVoid
2508 %12 = OpTypeFunction %void
2509 %float = OpTypeFloat 32
2510 %_ptr_Function_float = OpTypePointer Function %float
2511 %float_0 = OpConstant %float 0
2512 %int = OpTypeInt 32 1
2513 %_ptr_Function_int = OpTypePointer Function %int
2514 %int_0 = OpConstant %int 0
2515 %int_10 = OpConstant %int 10
2516 %bool = OpTypeBool
2517 %uint = OpTypeInt 32 0
2518 %uint_10 = OpConstant %uint 10
2519 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2520 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
2521 %U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10
2522 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2523 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2524 %_ptr_Uniform_float = OpTypePointer Uniform %float
2525 %int_1 = OpConstant %int 1
2526 %_ptr_Output_float = OpTypePointer Output %float
2527 %o = OpVariable %_ptr_Output_float Output
2528 )";
2529
2530 const std::string predefs_after =
2531 R"(OpCapability Shader
2532 %1 = OpExtInstImport "GLSL.std.450"
2533 OpMemoryModel Logical GLSL450
2534 OpEntryPoint Fragment %main "main" %o
2535 OpExecutionMode %main OriginUpperLeft
2536 OpSource GLSL 430
2537 OpName %main "main"
2538 OpName %o "o"
2539 OpDecorate %o Location 0
2540 %void = OpTypeVoid
2541 %12 = OpTypeFunction %void
2542 %float = OpTypeFloat 32
2543 %float_0 = OpConstant %float 0
2544 %_ptr_Output_float = OpTypePointer Output %float
2545 %o = OpVariable %_ptr_Output_float Output
2546 )";
2547
2548 const std::string func_before =
2549 R"(%main = OpFunction %void None %12
2550 %27 = OpLabel
2551 %s = OpVariable %_ptr_Function_float Function
2552 %i = OpVariable %_ptr_Function_int Function
2553 %j = OpVariable %_ptr_Function_int Function
2554 OpStore %s %float_0
2555 OpStore %i %int_0
2556 OpBranch %28
2557 %28 = OpLabel
2558 OpLoopMerge %29 %30 None
2559 OpBranch %31
2560 %31 = OpLabel
2561 %32 = OpLoad %int %i
2562 %33 = OpSLessThan %bool %32 %int_10
2563 OpBranchConditional %33 %34 %29
2564 %34 = OpLabel
2565 OpStore %j %int_0
2566 OpBranch %35
2567 %35 = OpLabel
2568 OpLoopMerge %36 %37 None
2569 OpBranch %38
2570 %38 = OpLabel
2571 %39 = OpLoad %int %j
2572 %40 = OpSLessThan %bool %39 %int_10
2573 OpBranchConditional %40 %41 %36
2574 %41 = OpLabel
2575 %42 = OpLoad %int %i
2576 %43 = OpLoad %int %j
2577 %44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43
2578 %45 = OpLoad %float %44
2579 %46 = OpFOrdGreaterThan %bool %45 %float_0
2580 OpSelectionMerge %47 None
2581 OpBranchConditional %46 %48 %47
2582 %48 = OpLabel
2583 %49 = OpLoad %float %s
2584 %50 = OpFAdd %float %49 %45
2585 OpStore %s %50
2586 OpBranch %47
2587 %47 = OpLabel
2588 OpBranch %37
2589 %37 = OpLabel
2590 %51 = OpLoad %int %j
2591 %52 = OpIAdd %int %51 %int_1
2592 OpStore %j %52
2593 OpBranch %35
2594 %36 = OpLabel
2595 OpBranch %30
2596 %30 = OpLabel
2597 %53 = OpLoad %int %i
2598 %54 = OpIAdd %int %53 %int_1
2599 OpStore %i %54
2600 OpBranch %28
2601 %29 = OpLabel
2602 OpStore %o %float_0
2603 OpReturn
2604 OpFunctionEnd
2605 )";
2606
2607 const std::string func_after =
2608 R"(%main = OpFunction %void None %12
2609 %27 = OpLabel
2610 OpBranch %28
2611 %28 = OpLabel
2612 OpBranch %29
2613 %29 = OpLabel
2614 OpStore %o %float_0
2615 OpReturn
2616 OpFunctionEnd
2617 )";
2618
2619 SinglePassRunAndCheck<AggressiveDCEPass>(
2620 predefs_before + func_before, predefs_after + func_after, true, true);
2621 }
2622
TEST_F(AggressiveDCETest,EliminateEmptyIfBeforeContinue)2623 TEST_F(AggressiveDCETest, EliminateEmptyIfBeforeContinue) {
2624 // #version 430
2625 //
2626 // layout(location = 0)out float o;
2627 //
2628 // void main(void)
2629 // {
2630 // float s = 0.0;
2631 // for (int i=0; i<10; i++) {
2632 // s += 1.0;
2633 // if (i > s) {}
2634 // }
2635 // o = s;
2636 // }
2637
2638 const std::string predefs_before =
2639 R"(OpCapability Shader
2640 %1 = OpExtInstImport "GLSL.std.450"
2641 OpMemoryModel Logical GLSL450
2642 OpEntryPoint Fragment %main "main" %3
2643 OpExecutionMode %main OriginUpperLeft
2644 OpSource GLSL 430
2645 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
2646 OpSourceExtension "GL_GOOGLE_include_directive"
2647 OpName %main "main"
2648 OpDecorate %3 Location 0
2649 %void = OpTypeVoid
2650 %5 = OpTypeFunction %void
2651 %float = OpTypeFloat 32
2652 %float_0 = OpConstant %float 0
2653 %int = OpTypeInt 32 1
2654 %_ptr_Function_int = OpTypePointer Function %int
2655 %int_0 = OpConstant %int 0
2656 %int_10 = OpConstant %int 10
2657 %bool = OpTypeBool
2658 %float_1 = OpConstant %float 1
2659 %int_1 = OpConstant %int 1
2660 %_ptr_Output_float = OpTypePointer Output %float
2661 %3 = OpVariable %_ptr_Output_float Output
2662 )";
2663
2664 const std::string predefs_after =
2665 R"(OpCapability Shader
2666 %1 = OpExtInstImport "GLSL.std.450"
2667 OpMemoryModel Logical GLSL450
2668 OpEntryPoint Fragment %main "main" %3
2669 OpExecutionMode %main OriginUpperLeft
2670 OpSource GLSL 430
2671 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
2672 OpSourceExtension "GL_GOOGLE_include_directive"
2673 OpName %main "main"
2674 OpDecorate %3 Location 0
2675 %void = OpTypeVoid
2676 %5 = OpTypeFunction %void
2677 %float = OpTypeFloat 32
2678 %float_0 = OpConstant %float 0
2679 %int = OpTypeInt 32 1
2680 %int_0 = OpConstant %int 0
2681 %int_10 = OpConstant %int 10
2682 %bool = OpTypeBool
2683 %float_1 = OpConstant %float 1
2684 %int_1 = OpConstant %int 1
2685 %_ptr_Output_float = OpTypePointer Output %float
2686 %3 = OpVariable %_ptr_Output_float Output
2687 )";
2688
2689 const std::string func_before =
2690 R"(%main = OpFunction %void None %5
2691 %16 = OpLabel
2692 OpBranch %17
2693 %17 = OpLabel
2694 %18 = OpPhi %float %float_0 %16 %19 %20
2695 %21 = OpPhi %int %int_0 %16 %22 %20
2696 OpLoopMerge %23 %20 None
2697 OpBranch %24
2698 %24 = OpLabel
2699 %25 = OpSLessThan %bool %21 %int_10
2700 OpBranchConditional %25 %26 %23
2701 %26 = OpLabel
2702 %19 = OpFAdd %float %18 %float_1
2703 %27 = OpConvertFToS %int %19
2704 %28 = OpSGreaterThan %bool %21 %27
2705 OpSelectionMerge %20 None
2706 OpBranchConditional %28 %29 %20
2707 %29 = OpLabel
2708 OpBranch %20
2709 %20 = OpLabel
2710 %22 = OpIAdd %int %21 %int_1
2711 OpBranch %17
2712 %23 = OpLabel
2713 OpStore %3 %18
2714 OpReturn
2715 OpFunctionEnd
2716 )";
2717
2718 const std::string func_after =
2719 R"(%main = OpFunction %void None %5
2720 %16 = OpLabel
2721 OpBranch %17
2722 %17 = OpLabel
2723 %18 = OpPhi %float %float_0 %16 %19 %20
2724 %21 = OpPhi %int %int_0 %16 %22 %20
2725 OpLoopMerge %23 %20 None
2726 OpBranch %24
2727 %24 = OpLabel
2728 %25 = OpSLessThan %bool %21 %int_10
2729 OpBranchConditional %25 %26 %23
2730 %26 = OpLabel
2731 %19 = OpFAdd %float %18 %float_1
2732 OpBranch %20
2733 %20 = OpLabel
2734 %22 = OpIAdd %int %21 %int_1
2735 OpBranch %17
2736 %23 = OpLabel
2737 OpStore %3 %18
2738 OpReturn
2739 OpFunctionEnd
2740 )";
2741
2742 SinglePassRunAndCheck<AggressiveDCEPass>(
2743 predefs_before + func_before, predefs_after + func_after, true, true);
2744 }
2745
TEST_F(AggressiveDCETest,NoEliminateLiveNestedLoopWithIf)2746 TEST_F(AggressiveDCETest, NoEliminateLiveNestedLoopWithIf) {
2747 // Note: SPIR-V optimized
2748 //
2749 // #version 430
2750 //
2751 // layout(std430) buffer U_t
2752 // {
2753 // float g_F[10][10];
2754 // };
2755 //
2756 // layout(location = 0)out float o;
2757 //
2758 // void main(void)
2759 // {
2760 // float s = 0.0;
2761 // for (int i=0; i<10; i++) {
2762 // for (int j=0; j<10; j++) {
2763 // float t = g_F[i][j];
2764 // if (t > 0.0)
2765 // s += t;
2766 // }
2767 // }
2768 // o = s;
2769 // }
2770
2771 const std::string assembly =
2772 R"(OpCapability Shader
2773 %1 = OpExtInstImport "GLSL.std.450"
2774 OpMemoryModel Logical GLSL450
2775 OpEntryPoint Fragment %main "main" %o
2776 OpExecutionMode %main OriginUpperLeft
2777 OpSource GLSL 430
2778 OpName %main "main"
2779 OpName %s "s"
2780 OpName %i "i"
2781 OpName %j "j"
2782 OpName %U_t "U_t"
2783 OpMemberName %U_t 0 "g_F"
2784 OpName %_ ""
2785 OpName %o "o"
2786 OpDecorate %_arr_float_uint_10 ArrayStride 4
2787 OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40
2788 OpMemberDecorate %U_t 0 Offset 0
2789 OpDecorate %U_t BufferBlock
2790 OpDecorate %_ DescriptorSet 0
2791 OpDecorate %o Location 0
2792 %void = OpTypeVoid
2793 %12 = OpTypeFunction %void
2794 %float = OpTypeFloat 32
2795 %_ptr_Function_float = OpTypePointer Function %float
2796 %float_0 = OpConstant %float 0
2797 %int = OpTypeInt 32 1
2798 %_ptr_Function_int = OpTypePointer Function %int
2799 %int_0 = OpConstant %int 0
2800 %int_10 = OpConstant %int 10
2801 %bool = OpTypeBool
2802 %uint = OpTypeInt 32 0
2803 %uint_10 = OpConstant %uint 10
2804 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2805 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
2806 %U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10
2807 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2808 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2809 %_ptr_Uniform_float = OpTypePointer Uniform %float
2810 %int_1 = OpConstant %int 1
2811 %_ptr_Output_float = OpTypePointer Output %float
2812 %o = OpVariable %_ptr_Output_float Output
2813 %main = OpFunction %void None %12
2814 %27 = OpLabel
2815 %s = OpVariable %_ptr_Function_float Function
2816 %i = OpVariable %_ptr_Function_int Function
2817 %j = OpVariable %_ptr_Function_int Function
2818 OpStore %s %float_0
2819 OpStore %i %int_0
2820 OpBranch %28
2821 %28 = OpLabel
2822 OpLoopMerge %29 %30 None
2823 OpBranch %31
2824 %31 = OpLabel
2825 %32 = OpLoad %int %i
2826 %33 = OpSLessThan %bool %32 %int_10
2827 OpBranchConditional %33 %34 %29
2828 %34 = OpLabel
2829 OpStore %j %int_0
2830 OpBranch %35
2831 %35 = OpLabel
2832 OpLoopMerge %36 %37 None
2833 OpBranch %38
2834 %38 = OpLabel
2835 %39 = OpLoad %int %j
2836 %40 = OpSLessThan %bool %39 %int_10
2837 OpBranchConditional %40 %41 %36
2838 %41 = OpLabel
2839 %42 = OpLoad %int %i
2840 %43 = OpLoad %int %j
2841 %44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43
2842 %45 = OpLoad %float %44
2843 %46 = OpFOrdGreaterThan %bool %45 %float_0
2844 OpSelectionMerge %47 None
2845 OpBranchConditional %46 %48 %47
2846 %48 = OpLabel
2847 %49 = OpLoad %float %s
2848 %50 = OpFAdd %float %49 %45
2849 OpStore %s %50
2850 OpBranch %47
2851 %47 = OpLabel
2852 OpBranch %37
2853 %37 = OpLabel
2854 %51 = OpLoad %int %j
2855 %52 = OpIAdd %int %51 %int_1
2856 OpStore %j %52
2857 OpBranch %35
2858 %36 = OpLabel
2859 OpBranch %30
2860 %30 = OpLabel
2861 %53 = OpLoad %int %i
2862 %54 = OpIAdd %int %53 %int_1
2863 OpStore %i %54
2864 OpBranch %28
2865 %29 = OpLabel
2866 %55 = OpLoad %float %s
2867 OpStore %o %55
2868 OpReturn
2869 OpFunctionEnd
2870 )";
2871
2872 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
2873 }
2874
TEST_F(AggressiveDCETest,NoEliminateIfContinue)2875 TEST_F(AggressiveDCETest, NoEliminateIfContinue) {
2876 // Do not eliminate continue embedded in if construct
2877 //
2878 // #version 430
2879 //
2880 // layout(std430) buffer U_t
2881 // {
2882 // float g_F[10];
2883 // };
2884 //
2885 // layout(location = 0)out float o;
2886 //
2887 // void main(void)
2888 // {
2889 // float s = 0.0;
2890 // for (int i=0; i<10; i++) {
2891 // if (i % 2 == 0) continue;
2892 // s += g_F[i];
2893 // }
2894 // o = s;
2895 // }
2896
2897 const std::string assembly =
2898 R"(OpCapability Shader
2899 %1 = OpExtInstImport "GLSL.std.450"
2900 OpMemoryModel Logical GLSL450
2901 OpEntryPoint Fragment %main "main" %o
2902 OpExecutionMode %main OriginUpperLeft
2903 OpSource GLSL 430
2904 OpName %main "main"
2905 OpName %s "s"
2906 OpName %i "i"
2907 OpName %U_t "U_t"
2908 OpMemberName %U_t 0 "g_F"
2909 OpName %_ ""
2910 OpName %o "o"
2911 OpDecorate %_arr_float_uint_10 ArrayStride 4
2912 OpMemberDecorate %U_t 0 Offset 0
2913 OpDecorate %U_t BufferBlock
2914 OpDecorate %_ DescriptorSet 0
2915 OpDecorate %o Location 0
2916 %void = OpTypeVoid
2917 %10 = OpTypeFunction %void
2918 %float = OpTypeFloat 32
2919 %_ptr_Function_float = OpTypePointer Function %float
2920 %float_0 = OpConstant %float 0
2921 %int = OpTypeInt 32 1
2922 %_ptr_Function_int = OpTypePointer Function %int
2923 %int_0 = OpConstant %int 0
2924 %int_10 = OpConstant %int 10
2925 %bool = OpTypeBool
2926 %int_2 = OpConstant %int 2
2927 %uint = OpTypeInt 32 0
2928 %uint_10 = OpConstant %uint 10
2929 %_arr_float_uint_10 = OpTypeArray %float %uint_10
2930 %U_t = OpTypeStruct %_arr_float_uint_10
2931 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
2932 %_ = OpVariable %_ptr_Uniform_U_t Uniform
2933 %_ptr_Uniform_float = OpTypePointer Uniform %float
2934 %int_1 = OpConstant %int 1
2935 %_ptr_Output_float = OpTypePointer Output %float
2936 %o = OpVariable %_ptr_Output_float Output
2937 %main = OpFunction %void None %10
2938 %26 = OpLabel
2939 %s = OpVariable %_ptr_Function_float Function
2940 %i = OpVariable %_ptr_Function_int Function
2941 OpStore %s %float_0
2942 OpStore %i %int_0
2943 OpBranch %27
2944 %27 = OpLabel
2945 OpLoopMerge %28 %29 None
2946 OpBranch %30
2947 %30 = OpLabel
2948 %31 = OpLoad %int %i
2949 %32 = OpSLessThan %bool %31 %int_10
2950 OpBranchConditional %32 %33 %28
2951 %33 = OpLabel
2952 %34 = OpLoad %int %i
2953 %35 = OpSMod %int %34 %int_2
2954 %36 = OpIEqual %bool %35 %int_0
2955 OpSelectionMerge %37 None
2956 OpBranchConditional %36 %38 %37
2957 %38 = OpLabel
2958 OpBranch %29
2959 %37 = OpLabel
2960 %39 = OpLoad %int %i
2961 %40 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %39
2962 %41 = OpLoad %float %40
2963 %42 = OpLoad %float %s
2964 %43 = OpFAdd %float %42 %41
2965 OpStore %s %43
2966 OpBranch %29
2967 %29 = OpLabel
2968 %44 = OpLoad %int %i
2969 %45 = OpIAdd %int %44 %int_1
2970 OpStore %i %45
2971 OpBranch %27
2972 %28 = OpLabel
2973 %46 = OpLoad %float %s
2974 OpStore %o %46
2975 OpReturn
2976 OpFunctionEnd
2977 )";
2978
2979 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
2980 }
2981
TEST_F(AggressiveDCETest,NoEliminateIfContinue2)2982 TEST_F(AggressiveDCETest, NoEliminateIfContinue2) {
2983 // Do not eliminate continue not embedded in if construct
2984 //
2985 // #version 430
2986 //
2987 // layout(std430) buffer U_t
2988 // {
2989 // float g_F[10];
2990 // };
2991 //
2992 // layout(location = 0)out float o;
2993 //
2994 // void main(void)
2995 // {
2996 // float s = 0.0;
2997 // for (int i=0; i<10; i++) {
2998 // if (i % 2 == 0) continue;
2999 // s += g_F[i];
3000 // }
3001 // o = s;
3002 // }
3003
3004 const std::string assembly =
3005 R"(OpCapability Shader
3006 %1 = OpExtInstImport "GLSL.std.450"
3007 OpMemoryModel Logical GLSL450
3008 OpEntryPoint Fragment %main "main" %o
3009 OpExecutionMode %main OriginUpperLeft
3010 OpSource GLSL 430
3011 OpName %main "main"
3012 OpName %s "s"
3013 OpName %i "i"
3014 OpName %U_t "U_t"
3015 OpMemberName %U_t 0 "g_F"
3016 OpName %_ ""
3017 OpName %o "o"
3018 OpDecorate %_arr_float_uint_10 ArrayStride 4
3019 OpMemberDecorate %U_t 0 Offset 0
3020 OpDecorate %U_t BufferBlock
3021 OpDecorate %_ DescriptorSet 0
3022 OpDecorate %o Location 0
3023 %void = OpTypeVoid
3024 %10 = OpTypeFunction %void
3025 %float = OpTypeFloat 32
3026 %_ptr_Function_float = OpTypePointer Function %float
3027 %float_0 = OpConstant %float 0
3028 %int = OpTypeInt 32 1
3029 %_ptr_Function_int = OpTypePointer Function %int
3030 %int_0 = OpConstant %int 0
3031 %int_10 = OpConstant %int 10
3032 %bool = OpTypeBool
3033 %int_2 = OpConstant %int 2
3034 %uint = OpTypeInt 32 0
3035 %uint_10 = OpConstant %uint 10
3036 %_arr_float_uint_10 = OpTypeArray %float %uint_10
3037 %U_t = OpTypeStruct %_arr_float_uint_10
3038 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
3039 %_ = OpVariable %_ptr_Uniform_U_t Uniform
3040 %_ptr_Uniform_float = OpTypePointer Uniform %float
3041 %int_1 = OpConstant %int 1
3042 %_ptr_Output_float = OpTypePointer Output %float
3043 %o = OpVariable %_ptr_Output_float Output
3044 %main = OpFunction %void None %10
3045 %26 = OpLabel
3046 %s = OpVariable %_ptr_Function_float Function
3047 %i = OpVariable %_ptr_Function_int Function
3048 OpStore %s %float_0
3049 OpStore %i %int_0
3050 OpBranch %27
3051 %27 = OpLabel
3052 OpLoopMerge %28 %29 None
3053 OpBranch %30
3054 %30 = OpLabel
3055 %31 = OpLoad %int %i
3056 %32 = OpSLessThan %bool %31 %int_10
3057 OpBranchConditional %32 %33 %28
3058 %33 = OpLabel
3059 %34 = OpLoad %int %i
3060 %35 = OpSMod %int %34 %int_2
3061 %36 = OpIEqual %bool %35 %int_0
3062 OpBranchConditional %36 %29 %37
3063 %37 = OpLabel
3064 %38 = OpLoad %int %i
3065 %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38
3066 %40 = OpLoad %float %39
3067 %41 = OpLoad %float %s
3068 %42 = OpFAdd %float %41 %40
3069 OpStore %s %42
3070 OpBranch %29
3071 %29 = OpLabel
3072 %43 = OpLoad %int %i
3073 %44 = OpIAdd %int %43 %int_1
3074 OpStore %i %44
3075 OpBranch %27
3076 %28 = OpLabel
3077 %45 = OpLoad %float %s
3078 OpStore %o %45
3079 OpReturn
3080 OpFunctionEnd
3081 )";
3082
3083 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
3084 }
3085
TEST_F(AggressiveDCETest,NoEliminateIfContinue3)3086 TEST_F(AggressiveDCETest, NoEliminateIfContinue3) {
3087 // Do not eliminate continue as conditional branch with merge instruction
3088 // Note: SPIR-V edited to add merge instruction before continue.
3089 //
3090 // #version 430
3091 //
3092 // layout(std430) buffer U_t
3093 // {
3094 // float g_F[10];
3095 // };
3096 //
3097 // layout(location = 0)out float o;
3098 //
3099 // void main(void)
3100 // {
3101 // float s = 0.0;
3102 // for (int i=0; i<10; i++) {
3103 // if (i % 2 == 0) continue;
3104 // s += g_F[i];
3105 // }
3106 // o = s;
3107 // }
3108
3109 const std::string assembly =
3110 R"(OpCapability Shader
3111 %1 = OpExtInstImport "GLSL.std.450"
3112 OpMemoryModel Logical GLSL450
3113 OpEntryPoint Fragment %main "main" %o
3114 OpExecutionMode %main OriginUpperLeft
3115 OpSource GLSL 430
3116 OpName %main "main"
3117 OpName %s "s"
3118 OpName %i "i"
3119 OpName %U_t "U_t"
3120 OpMemberName %U_t 0 "g_F"
3121 OpName %_ ""
3122 OpName %o "o"
3123 OpDecorate %_arr_float_uint_10 ArrayStride 4
3124 OpMemberDecorate %U_t 0 Offset 0
3125 OpDecorate %U_t BufferBlock
3126 OpDecorate %_ DescriptorSet 0
3127 OpDecorate %o Location 0
3128 %void = OpTypeVoid
3129 %10 = OpTypeFunction %void
3130 %float = OpTypeFloat 32
3131 %_ptr_Function_float = OpTypePointer Function %float
3132 %float_0 = OpConstant %float 0
3133 %int = OpTypeInt 32 1
3134 %_ptr_Function_int = OpTypePointer Function %int
3135 %int_0 = OpConstant %int 0
3136 %int_10 = OpConstant %int 10
3137 %bool = OpTypeBool
3138 %int_2 = OpConstant %int 2
3139 %uint = OpTypeInt 32 0
3140 %uint_10 = OpConstant %uint 10
3141 %_arr_float_uint_10 = OpTypeArray %float %uint_10
3142 %U_t = OpTypeStruct %_arr_float_uint_10
3143 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
3144 %_ = OpVariable %_ptr_Uniform_U_t Uniform
3145 %_ptr_Uniform_float = OpTypePointer Uniform %float
3146 %int_1 = OpConstant %int 1
3147 %_ptr_Output_float = OpTypePointer Output %float
3148 %o = OpVariable %_ptr_Output_float Output
3149 %main = OpFunction %void None %10
3150 %26 = OpLabel
3151 %s = OpVariable %_ptr_Function_float Function
3152 %i = OpVariable %_ptr_Function_int Function
3153 OpStore %s %float_0
3154 OpStore %i %int_0
3155 OpBranch %27
3156 %27 = OpLabel
3157 OpLoopMerge %28 %29 None
3158 OpBranch %30
3159 %30 = OpLabel
3160 %31 = OpLoad %int %i
3161 %32 = OpSLessThan %bool %31 %int_10
3162 OpBranchConditional %32 %33 %28
3163 %33 = OpLabel
3164 %34 = OpLoad %int %i
3165 %35 = OpSMod %int %34 %int_2
3166 %36 = OpIEqual %bool %35 %int_0
3167 OpSelectionMerge %37 None
3168 OpBranchConditional %36 %29 %37
3169 %37 = OpLabel
3170 %38 = OpLoad %int %i
3171 %39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38
3172 %40 = OpLoad %float %39
3173 %41 = OpLoad %float %s
3174 %42 = OpFAdd %float %41 %40
3175 OpStore %s %42
3176 OpBranch %29
3177 %29 = OpLabel
3178 %43 = OpLoad %int %i
3179 %44 = OpIAdd %int %43 %int_1
3180 OpStore %i %44
3181 OpBranch %27
3182 %28 = OpLabel
3183 %45 = OpLoad %float %s
3184 OpStore %o %45
3185 OpReturn
3186 OpFunctionEnd
3187 )";
3188
3189 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true);
3190 }
3191
3192 // This is not valid input and ADCE does not support variable pointers and only
3193 // supports shaders.
TEST_F(AggressiveDCETest,PointerVariable)3194 TEST_F(AggressiveDCETest, PointerVariable) {
3195 // ADCE is able to handle code that contains a load whose base address
3196 // comes from a load and not an OpVariable. I want to see an instruction
3197 // removed to be sure that ADCE is not exiting early.
3198
3199 const std::string before =
3200 R"(OpCapability Shader
3201 OpMemoryModel Logical GLSL450
3202 OpEntryPoint Fragment %1 "main" %2
3203 OpExecutionMode %1 OriginUpperLeft
3204 OpMemberDecorate %_struct_3 0 Offset 0
3205 OpDecorate %_runtimearr__struct_3 ArrayStride 16
3206 OpMemberDecorate %_struct_5 0 Offset 0
3207 OpDecorate %_struct_5 BufferBlock
3208 OpMemberDecorate %_struct_6 0 Offset 0
3209 OpDecorate %_struct_6 BufferBlock
3210 OpDecorate %2 Location 0
3211 OpDecorate %7 DescriptorSet 0
3212 OpDecorate %7 Binding 0
3213 OpDecorate %8 DescriptorSet 0
3214 OpDecorate %8 Binding 1
3215 %void = OpTypeVoid
3216 %10 = OpTypeFunction %void
3217 %int = OpTypeInt 32 1
3218 %uint = OpTypeInt 32 0
3219 %float = OpTypeFloat 32
3220 %v4float = OpTypeVector %float 4
3221 %_ptr_Output_v4float = OpTypePointer Output %v4float
3222 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
3223 %_struct_3 = OpTypeStruct %v4float
3224 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
3225 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
3226 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
3227 %_struct_6 = OpTypeStruct %int
3228 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
3229 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
3230 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
3231 %int_0 = OpConstant %int 0
3232 %uint_0 = OpConstant %uint 0
3233 %2 = OpVariable %_ptr_Output_v4float Output
3234 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
3235 %8 = OpVariable %_ptr_Uniform__struct_6 Uniform
3236 %1 = OpFunction %void None %10
3237 %23 = OpLabel
3238 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
3239 OpStore %24 %7
3240 %26 = OpLoad %_ptr_Uniform__struct_5 %24
3241 %27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0
3242 %28 = OpLoad %v4float %27
3243 %29 = OpCopyObject %v4float %28
3244 OpStore %2 %28
3245 OpReturn
3246 OpFunctionEnd
3247 )";
3248
3249 const std::string after =
3250 R"(OpCapability Shader
3251 OpMemoryModel Logical GLSL450
3252 OpEntryPoint Fragment %1 "main" %2
3253 OpExecutionMode %1 OriginUpperLeft
3254 OpMemberDecorate %_struct_3 0 Offset 0
3255 OpDecorate %_runtimearr__struct_3 ArrayStride 16
3256 OpMemberDecorate %_struct_5 0 Offset 0
3257 OpDecorate %_struct_5 BufferBlock
3258 OpDecorate %2 Location 0
3259 OpDecorate %7 DescriptorSet 0
3260 OpDecorate %7 Binding 0
3261 %void = OpTypeVoid
3262 %10 = OpTypeFunction %void
3263 %int = OpTypeInt 32 1
3264 %uint = OpTypeInt 32 0
3265 %float = OpTypeFloat 32
3266 %v4float = OpTypeVector %float 4
3267 %_ptr_Output_v4float = OpTypePointer Output %v4float
3268 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
3269 %_struct_3 = OpTypeStruct %v4float
3270 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
3271 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
3272 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
3273 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
3274 %int_0 = OpConstant %int 0
3275 %uint_0 = OpConstant %uint 0
3276 %2 = OpVariable %_ptr_Output_v4float Output
3277 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
3278 %1 = OpFunction %void None %10
3279 %23 = OpLabel
3280 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
3281 OpStore %24 %7
3282 %25 = OpLoad %_ptr_Uniform__struct_5 %24
3283 %26 = OpAccessChain %_ptr_Uniform_v4float %25 %int_0 %uint_0 %int_0
3284 %27 = OpLoad %v4float %26
3285 OpStore %2 %27
3286 OpReturn
3287 OpFunctionEnd
3288 )";
3289
3290 // The input is not valid and ADCE only supports shaders, but not variable
3291 // pointers. Workaround this by enabling relaxed logical pointers in the
3292 // validator.
3293 ValidatorOptions()->relax_logical_pointer = true;
3294 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
3295 }
3296
3297 // %dead is unused. Make sure we remove it along with its name.
TEST_F(AggressiveDCETest,RemoveUnreferenced)3298 TEST_F(AggressiveDCETest, RemoveUnreferenced) {
3299 const std::string before =
3300 R"(OpCapability Shader
3301 OpCapability Linkage
3302 %1 = OpExtInstImport "GLSL.std.450"
3303 OpMemoryModel Logical GLSL450
3304 OpEntryPoint Fragment %main "main"
3305 OpExecutionMode %main OriginUpperLeft
3306 OpSource GLSL 150
3307 OpName %main "main"
3308 OpName %dead "dead"
3309 %void = OpTypeVoid
3310 %5 = OpTypeFunction %void
3311 %float = OpTypeFloat 32
3312 %_ptr_Private_float = OpTypePointer Private %float
3313 %dead = OpVariable %_ptr_Private_float Private
3314 %main = OpFunction %void None %5
3315 %8 = OpLabel
3316 OpReturn
3317 OpFunctionEnd
3318 )";
3319
3320 const std::string after =
3321 R"(OpCapability Shader
3322 OpCapability Linkage
3323 %1 = OpExtInstImport "GLSL.std.450"
3324 OpMemoryModel Logical GLSL450
3325 OpEntryPoint Fragment %main "main"
3326 OpExecutionMode %main OriginUpperLeft
3327 OpSource GLSL 150
3328 OpName %main "main"
3329 %void = OpTypeVoid
3330 %5 = OpTypeFunction %void
3331 %main = OpFunction %void None %5
3332 %8 = OpLabel
3333 OpReturn
3334 OpFunctionEnd
3335 )";
3336
3337 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3338 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
3339 }
3340
3341 // Delete %dead because it is unreferenced. Then %initializer becomes
3342 // unreferenced, so remove it as well.
TEST_F(AggressiveDCETest,RemoveUnreferencedWithInit1)3343 TEST_F(AggressiveDCETest, RemoveUnreferencedWithInit1) {
3344 const std::string before =
3345 R"(OpCapability Shader
3346 OpCapability Linkage
3347 %1 = OpExtInstImport "GLSL.std.450"
3348 OpMemoryModel Logical GLSL450
3349 OpEntryPoint Fragment %main "main"
3350 OpExecutionMode %main OriginUpperLeft
3351 OpSource GLSL 150
3352 OpName %main "main"
3353 OpName %dead "dead"
3354 OpName %initializer "initializer"
3355 %void = OpTypeVoid
3356 %6 = OpTypeFunction %void
3357 %float = OpTypeFloat 32
3358 %_ptr_Private_float = OpTypePointer Private %float
3359 %initializer = OpVariable %_ptr_Private_float Private
3360 %dead = OpVariable %_ptr_Private_float Private %initializer
3361 %main = OpFunction %void None %6
3362 %9 = OpLabel
3363 OpReturn
3364 OpFunctionEnd
3365 )";
3366
3367 const std::string after =
3368 R"(OpCapability Shader
3369 OpCapability Linkage
3370 %1 = OpExtInstImport "GLSL.std.450"
3371 OpMemoryModel Logical GLSL450
3372 OpEntryPoint Fragment %main "main"
3373 OpExecutionMode %main OriginUpperLeft
3374 OpSource GLSL 150
3375 OpName %main "main"
3376 %void = OpTypeVoid
3377 %6 = OpTypeFunction %void
3378 %main = OpFunction %void None %6
3379 %9 = OpLabel
3380 OpReturn
3381 OpFunctionEnd
3382 )";
3383
3384 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3385 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
3386 }
3387
3388 // Keep %live because it is used, and its initializer.
TEST_F(AggressiveDCETest,KeepReferenced)3389 TEST_F(AggressiveDCETest, KeepReferenced) {
3390 const std::string before =
3391 R"(OpCapability Shader
3392 OpCapability Linkage
3393 %1 = OpExtInstImport "GLSL.std.450"
3394 OpMemoryModel Logical GLSL450
3395 OpEntryPoint Fragment %main "main" %output
3396 OpExecutionMode %main OriginUpperLeft
3397 OpSource GLSL 150
3398 OpName %main "main"
3399 OpName %live "live"
3400 OpName %initializer "initializer"
3401 OpName %output "output"
3402 %void = OpTypeVoid
3403 %6 = OpTypeFunction %void
3404 %float = OpTypeFloat 32
3405 %_ptr_Private_float = OpTypePointer Private %float
3406 %initializer = OpConstant %float 0
3407 %live = OpVariable %_ptr_Private_float Private %initializer
3408 %_ptr_Output_float = OpTypePointer Output %float
3409 %output = OpVariable %_ptr_Output_float Output
3410 %main = OpFunction %void None %6
3411 %9 = OpLabel
3412 %10 = OpLoad %float %live
3413 OpStore %output %10
3414 OpReturn
3415 OpFunctionEnd
3416 )";
3417
3418 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3419 SinglePassRunAndCheck<AggressiveDCEPass>(before, before, true, true);
3420 }
3421
3422 // This test that the decoration associated with a variable are removed when the
3423 // variable is removed.
TEST_F(AggressiveDCETest,RemoveVariableAndDecorations)3424 TEST_F(AggressiveDCETest, RemoveVariableAndDecorations) {
3425 const std::string before =
3426 R"(OpCapability Shader
3427 %1 = OpExtInstImport "GLSL.std.450"
3428 OpMemoryModel Logical GLSL450
3429 OpEntryPoint Vertex %main "main"
3430 OpSource GLSL 450
3431 OpName %main "main"
3432 OpName %B "B"
3433 OpMemberName %B 0 "a"
3434 OpName %Bdat "Bdat"
3435 OpMemberDecorate %B 0 Offset 0
3436 OpDecorate %B BufferBlock
3437 OpDecorate %Bdat DescriptorSet 0
3438 OpDecorate %Bdat Binding 0
3439 %void = OpTypeVoid
3440 %6 = OpTypeFunction %void
3441 %uint = OpTypeInt 32 0
3442 %B = OpTypeStruct %uint
3443 %_ptr_Uniform_B = OpTypePointer Uniform %B
3444 %Bdat = OpVariable %_ptr_Uniform_B Uniform
3445 %int = OpTypeInt 32 1
3446 %int_0 = OpConstant %int 0
3447 %uint_1 = OpConstant %uint 1
3448 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
3449 %main = OpFunction %void None %6
3450 %13 = OpLabel
3451 OpReturn
3452 OpFunctionEnd
3453 )";
3454
3455 const std::string after =
3456 R"(OpCapability Shader
3457 %1 = OpExtInstImport "GLSL.std.450"
3458 OpMemoryModel Logical GLSL450
3459 OpEntryPoint Vertex %main "main"
3460 OpSource GLSL 450
3461 OpName %main "main"
3462 %void = OpTypeVoid
3463 %6 = OpTypeFunction %void
3464 %main = OpFunction %void None %6
3465 %13 = OpLabel
3466 OpReturn
3467 OpFunctionEnd
3468 )";
3469
3470 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3471 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
3472 }
3473
TEST_F(AggressiveDCETest,DeadNestedSwitch)3474 TEST_F(AggressiveDCETest, DeadNestedSwitch) {
3475 const std::string text = R"(
3476 ; CHECK: OpLabel
3477 ; CHECK: OpBranch [[block:%\w+]]
3478 ; CHECK-NOT: OpSwitch
3479 ; CHECK-NEXT: [[block]] = OpLabel
3480 ; CHECK: OpBranch [[block:%\w+]]
3481 ; CHECK-NOT: OpSwitch
3482 ; CHECK-NEXT: [[block]] = OpLabel
3483 ; CHECK-NEXT: OpStore
3484 OpCapability Shader
3485 OpMemoryModel Logical GLSL450
3486 OpEntryPoint Fragment %func "func" %x
3487 OpExecutionMode %func OriginUpperLeft
3488 OpName %func "func"
3489 %void = OpTypeVoid
3490 %1 = OpTypeFunction %void
3491 %uint = OpTypeInt 32 0
3492 %uint_0 = OpConstant %uint 0
3493 %uint_ptr_Output = OpTypePointer Output %uint
3494 %uint_ptr_Input = OpTypePointer Input %uint
3495 %x = OpVariable %uint_ptr_Output Output
3496 %a = OpVariable %uint_ptr_Input Input
3497 %func = OpFunction %void None %1
3498 %entry = OpLabel
3499 OpBranch %header
3500 %header = OpLabel
3501 %ld = OpLoad %uint %a
3502 OpLoopMerge %merge %continue None
3503 OpBranch %postheader
3504 %postheader = OpLabel
3505 ; This switch doesn't require an OpSelectionMerge and is nested in the dead loop.
3506 OpSwitch %ld %merge 0 %extra 1 %continue
3507 %extra = OpLabel
3508 OpBranch %continue
3509 %continue = OpLabel
3510 OpBranch %header
3511 %merge = OpLabel
3512 OpStore %x %uint_0
3513 OpReturn
3514 OpFunctionEnd
3515 )";
3516
3517 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
3518 }
3519
TEST_F(AggressiveDCETest,LiveNestedSwitch)3520 TEST_F(AggressiveDCETest, LiveNestedSwitch) {
3521 const std::string text = R"(OpCapability Shader
3522 OpMemoryModel Logical GLSL450
3523 OpEntryPoint Fragment %func "func" %3 %10
3524 OpExecutionMode %func OriginUpperLeft
3525 OpName %func "func"
3526 %void = OpTypeVoid
3527 %1 = OpTypeFunction %void
3528 %uint = OpTypeInt 32 0
3529 %uint_0 = OpConstant %uint 0
3530 %uint_1 = OpConstant %uint 1
3531 %_ptr_Output_uint = OpTypePointer Output %uint
3532 %_ptr_Input_uint = OpTypePointer Input %uint
3533 %3 = OpVariable %_ptr_Output_uint Output
3534 %10 = OpVariable %_ptr_Input_uint Input
3535 %func = OpFunction %void None %1
3536 %11 = OpLabel
3537 OpBranch %12
3538 %12 = OpLabel
3539 %13 = OpLoad %uint %10
3540 OpLoopMerge %14 %15 None
3541 OpBranch %16
3542 %16 = OpLabel
3543 OpSelectionMerge %18 None
3544 OpSwitch %13 %18 0 %17 1 %19
3545 %17 = OpLabel
3546 OpStore %3 %uint_1
3547 OpBranch %19
3548 %19 = OpLabel
3549 OpBranch %15
3550 %15 = OpLabel
3551 OpBranch %12
3552 %18 = OpLabel
3553 OpBranch %14
3554 %14 = OpLabel
3555 OpStore %3 %uint_0
3556 OpReturn
3557 OpFunctionEnd
3558 )";
3559
3560 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3561 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, false, true);
3562 }
3563
TEST_F(AggressiveDCETest,BasicDeleteDeadFunction)3564 TEST_F(AggressiveDCETest, BasicDeleteDeadFunction) {
3565 // The function Dead should be removed because it is never called.
3566 const std::vector<const char*> common_code = {
3567 // clang-format off
3568 "OpCapability Shader",
3569 "OpMemoryModel Logical GLSL450",
3570 "OpEntryPoint Fragment %main \"main\"",
3571 "OpName %main \"main\"",
3572 "OpName %Live \"Live\"",
3573 "%void = OpTypeVoid",
3574 "%7 = OpTypeFunction %void",
3575 "%main = OpFunction %void None %7",
3576 "%15 = OpLabel",
3577 "%16 = OpFunctionCall %void %Live",
3578 "%17 = OpFunctionCall %void %Live",
3579 "OpReturn",
3580 "OpFunctionEnd",
3581 "%Live = OpFunction %void None %7",
3582 "%20 = OpLabel",
3583 "OpReturn",
3584 "OpFunctionEnd"
3585 // clang-format on
3586 };
3587
3588 const std::vector<const char*> dead_function = {
3589 // clang-format off
3590 "%Dead = OpFunction %void None %7",
3591 "%19 = OpLabel",
3592 "OpReturn",
3593 "OpFunctionEnd",
3594 // clang-format on
3595 };
3596
3597 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3598 SinglePassRunAndCheck<AggressiveDCEPass>(
3599 JoinAllInsts(Concat(common_code, dead_function)),
3600 JoinAllInsts(common_code), /* skip_nop = */ true);
3601 }
3602
TEST_F(AggressiveDCETest,BasicKeepLiveFunction)3603 TEST_F(AggressiveDCETest, BasicKeepLiveFunction) {
3604 // Everything is reachable from an entry point, so no functions should be
3605 // deleted.
3606 const std::vector<const char*> text = {
3607 // clang-format off
3608 "OpCapability Shader",
3609 "OpMemoryModel Logical GLSL450",
3610 "OpEntryPoint Fragment %main \"main\"",
3611 "OpName %main \"main\"",
3612 "OpName %Live1 \"Live1\"",
3613 "OpName %Live2 \"Live2\"",
3614 "%void = OpTypeVoid",
3615 "%7 = OpTypeFunction %void",
3616 "%main = OpFunction %void None %7",
3617 "%15 = OpLabel",
3618 "%16 = OpFunctionCall %void %Live2",
3619 "%17 = OpFunctionCall %void %Live1",
3620 "OpReturn",
3621 "OpFunctionEnd",
3622 "%Live1 = OpFunction %void None %7",
3623 "%19 = OpLabel",
3624 "OpReturn",
3625 "OpFunctionEnd",
3626 "%Live2 = OpFunction %void None %7",
3627 "%20 = OpLabel",
3628 "OpReturn",
3629 "OpFunctionEnd"
3630 // clang-format on
3631 };
3632
3633 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3634 std::string assembly = JoinAllInsts(text);
3635 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
3636 assembly, /* skip_nop = */ true, /* do_validation = */ false);
3637 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
3638 EXPECT_EQ(assembly, std::get<0>(result));
3639 }
3640
TEST_F(AggressiveDCETest,BasicRemoveDecorationsAndNames)3641 TEST_F(AggressiveDCETest, BasicRemoveDecorationsAndNames) {
3642 // We want to remove the names and decorations associated with results that
3643 // are removed. This test will check for that.
3644 const std::string text = R"(
3645 OpCapability Shader
3646 OpMemoryModel Logical GLSL450
3647 OpEntryPoint Vertex %main "main"
3648 OpName %main "main"
3649 OpName %Dead "Dead"
3650 OpName %x "x"
3651 OpName %y "y"
3652 OpName %z "z"
3653 OpDecorate %x RelaxedPrecision
3654 OpDecorate %y RelaxedPrecision
3655 OpDecorate %z RelaxedPrecision
3656 OpDecorate %6 RelaxedPrecision
3657 OpDecorate %7 RelaxedPrecision
3658 OpDecorate %8 RelaxedPrecision
3659 %void = OpTypeVoid
3660 %10 = OpTypeFunction %void
3661 %float = OpTypeFloat 32
3662 %_ptr_Function_float = OpTypePointer Function %float
3663 %float_1 = OpConstant %float 1
3664 %main = OpFunction %void None %10
3665 %14 = OpLabel
3666 OpReturn
3667 OpFunctionEnd
3668 %Dead = OpFunction %void None %10
3669 %15 = OpLabel
3670 %x = OpVariable %_ptr_Function_float Function
3671 %y = OpVariable %_ptr_Function_float Function
3672 %z = OpVariable %_ptr_Function_float Function
3673 OpStore %x %float_1
3674 OpStore %y %float_1
3675 %6 = OpLoad %float %x
3676 %7 = OpLoad %float %y
3677 %8 = OpFAdd %float %6 %7
3678 OpStore %z %8
3679 OpReturn
3680 OpFunctionEnd)";
3681
3682 const std::string expected_output = R"(OpCapability Shader
3683 OpMemoryModel Logical GLSL450
3684 OpEntryPoint Vertex %main "main"
3685 OpName %main "main"
3686 %void = OpTypeVoid
3687 %10 = OpTypeFunction %void
3688 %main = OpFunction %void None %10
3689 %14 = OpLabel
3690 OpReturn
3691 OpFunctionEnd
3692 )";
3693
3694 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3695 SinglePassRunAndCheck<AggressiveDCEPass>(text, expected_output,
3696 /* skip_nop = */ true);
3697 }
3698
TEST_F(AggressiveDCETest,BasicAllDeadConstants)3699 TEST_F(AggressiveDCETest, BasicAllDeadConstants) {
3700 const std::string text = R"(
3701 ; CHECK-NOT: OpConstant
3702 OpCapability Shader
3703 OpCapability Float64
3704 %1 = OpExtInstImport "GLSL.std.450"
3705 OpMemoryModel Logical GLSL450
3706 OpEntryPoint Vertex %main "main"
3707 OpName %main "main"
3708 %void = OpTypeVoid
3709 %4 = OpTypeFunction %void
3710 %bool = OpTypeBool
3711 %true = OpConstantTrue %bool
3712 %false = OpConstantFalse %bool
3713 %int = OpTypeInt 32 1
3714 %9 = OpConstant %int 1
3715 %uint = OpTypeInt 32 0
3716 %11 = OpConstant %uint 2
3717 %float = OpTypeFloat 32
3718 %13 = OpConstant %float 3.1415
3719 %double = OpTypeFloat 64
3720 %15 = OpConstant %double 3.14159265358979
3721 %main = OpFunction %void None %4
3722 %16 = OpLabel
3723 OpReturn
3724 OpFunctionEnd
3725 )";
3726
3727 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
3728 }
3729
TEST_F(AggressiveDCETest,BasicNoneDeadConstants)3730 TEST_F(AggressiveDCETest, BasicNoneDeadConstants) {
3731 const std::vector<const char*> text = {
3732 // clang-format off
3733 "OpCapability Shader",
3734 "OpCapability Float64",
3735 "%1 = OpExtInstImport \"GLSL.std.450\"",
3736 "OpMemoryModel Logical GLSL450",
3737 "OpEntryPoint Vertex %main \"main\" %btv %bfv %iv %uv %fv %dv",
3738 "OpName %main \"main\"",
3739 "OpName %btv \"btv\"",
3740 "OpName %bfv \"bfv\"",
3741 "OpName %iv \"iv\"",
3742 "OpName %uv \"uv\"",
3743 "OpName %fv \"fv\"",
3744 "OpName %dv \"dv\"",
3745 "%void = OpTypeVoid",
3746 "%10 = OpTypeFunction %void",
3747 "%bool = OpTypeBool",
3748 "%_ptr_Output_bool = OpTypePointer Output %bool",
3749 "%true = OpConstantTrue %bool",
3750 "%false = OpConstantFalse %bool",
3751 "%int = OpTypeInt 32 1",
3752 "%_ptr_Output_int = OpTypePointer Output %int",
3753 "%int_1 = OpConstant %int 1",
3754 "%uint = OpTypeInt 32 0",
3755 "%_ptr_Output_uint = OpTypePointer Output %uint",
3756 "%uint_2 = OpConstant %uint 2",
3757 "%float = OpTypeFloat 32",
3758 "%_ptr_Output_float = OpTypePointer Output %float",
3759 "%float_3_1415 = OpConstant %float 3.1415",
3760 "%double = OpTypeFloat 64",
3761 "%_ptr_Output_double = OpTypePointer Output %double",
3762 "%double_3_14159265358979 = OpConstant %double 3.14159265358979",
3763 "%btv = OpVariable %_ptr_Output_bool Output",
3764 "%bfv = OpVariable %_ptr_Output_bool Output",
3765 "%iv = OpVariable %_ptr_Output_int Output",
3766 "%uv = OpVariable %_ptr_Output_uint Output",
3767 "%fv = OpVariable %_ptr_Output_float Output",
3768 "%dv = OpVariable %_ptr_Output_double Output",
3769 "%main = OpFunction %void None %10",
3770 "%27 = OpLabel",
3771 "OpStore %btv %true",
3772 "OpStore %bfv %false",
3773 "OpStore %iv %int_1",
3774 "OpStore %uv %uint_2",
3775 "OpStore %fv %float_3_1415",
3776 "OpStore %dv %double_3_14159265358979",
3777 "OpReturn",
3778 "OpFunctionEnd",
3779 // clang-format on
3780 };
3781 // All constants are used, so none of them should be eliminated.
3782 SinglePassRunAndCheck<AggressiveDCEPass>(
3783 JoinAllInsts(text), JoinAllInsts(text), /* skip_nop = */ true);
3784 }
3785
3786 struct AggressiveEliminateDeadConstantTestCase {
3787 // Type declarations and constants that should be kept.
3788 std::vector<std::string> used_consts;
3789 // Instructions that refer to constants, this is added to create uses for
3790 // some constants so they won't be treated as dead constants.
3791 std::vector<std::string> main_insts;
3792 // Dead constants that should be removed.
3793 std::vector<std::string> dead_consts;
3794 // Expectations
3795 std::vector<std::string> checks;
3796 };
3797
3798 // All types that are potentially required in
3799 // AggressiveEliminateDeadConstantTest.
3800 const std::vector<std::string> CommonTypes = {
3801 // clang-format off
3802 // scalar types
3803 "%bool = OpTypeBool",
3804 "%uint = OpTypeInt 32 0",
3805 "%int = OpTypeInt 32 1",
3806 "%float = OpTypeFloat 32",
3807 "%double = OpTypeFloat 64",
3808 // vector types
3809 "%v2bool = OpTypeVector %bool 2",
3810 "%v2uint = OpTypeVector %uint 2",
3811 "%v2int = OpTypeVector %int 2",
3812 "%v3int = OpTypeVector %int 3",
3813 "%v4int = OpTypeVector %int 4",
3814 "%v2float = OpTypeVector %float 2",
3815 "%v3float = OpTypeVector %float 3",
3816 "%v2double = OpTypeVector %double 2",
3817 // variable pointer types
3818 "%_pf_bool = OpTypePointer Output %bool",
3819 "%_pf_uint = OpTypePointer Output %uint",
3820 "%_pf_int = OpTypePointer Output %int",
3821 "%_pf_float = OpTypePointer Output %float",
3822 "%_pf_double = OpTypePointer Output %double",
3823 "%_pf_v2int = OpTypePointer Output %v2int",
3824 "%_pf_v3int = OpTypePointer Output %v3int",
3825 "%_pf_v2float = OpTypePointer Output %v2float",
3826 "%_pf_v3float = OpTypePointer Output %v3float",
3827 "%_pf_v2double = OpTypePointer Output %v2double",
3828 // struct types
3829 "%inner_struct = OpTypeStruct %bool %int %float %double",
3830 "%outer_struct = OpTypeStruct %inner_struct %int %double",
3831 "%flat_struct = OpTypeStruct %bool %int %float %double",
3832 // clang-format on
3833 };
3834
3835 using AggressiveEliminateDeadConstantTest =
3836 PassTest<::testing::TestWithParam<AggressiveEliminateDeadConstantTestCase>>;
3837
TEST_P(AggressiveEliminateDeadConstantTest,Custom)3838 TEST_P(AggressiveEliminateDeadConstantTest, Custom) {
3839 auto& tc = GetParam();
3840 AssemblyBuilder builder;
3841 builder.AppendTypesConstantsGlobals(CommonTypes)
3842 .AppendTypesConstantsGlobals(tc.used_consts)
3843 .AppendInMain(tc.main_insts);
3844 const std::string expected = builder.GetCode();
3845 builder.AppendTypesConstantsGlobals(tc.dead_consts);
3846 builder.PrependPreamble(tc.checks);
3847 const std::string assembly_with_dead_const = builder.GetCode();
3848
3849 // Do not enable validation. As the input code is invalid from the base
3850 // tests (ported from other passes).
3851 SinglePassRunAndMatch<AggressiveDCEPass>(assembly_with_dead_const, false);
3852 }
3853
3854 INSTANTIATE_TEST_SUITE_P(
3855 ScalarTypeConstants, AggressiveEliminateDeadConstantTest,
3856 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
3857 // clang-format off
3858 // Scalar type constants, one dead constant and one used constant.
3859 {
3860 /* .used_consts = */
3861 {
3862 "%used_const_int = OpConstant %int 1",
3863 },
3864 /* .main_insts = */
3865 {
3866 "%int_var = OpVariable %_pf_int Output",
3867 "OpStore %int_var %used_const_int",
3868 },
3869 /* .dead_consts = */
3870 {
3871 "%dead_const_int = OpConstant %int 1",
3872 },
3873 /* .checks = */
3874 {
3875 "; CHECK: [[const:%\\w+]] = OpConstant %int 1",
3876 "; CHECK-NOT: OpConstant",
3877 "; CHECK: OpStore {{%\\w+}} [[const]]",
3878 },
3879 },
3880 {
3881 /* .used_consts = */
3882 {
3883 "%used_const_uint = OpConstant %uint 1",
3884 },
3885 /* .main_insts = */
3886 {
3887 "%uint_var = OpVariable %_pf_uint Output",
3888 "OpStore %uint_var %used_const_uint",
3889 },
3890 /* .dead_consts = */
3891 {
3892 "%dead_const_uint = OpConstant %uint 1",
3893 },
3894 /* .checks = */
3895 {
3896 "; CHECK: [[const:%\\w+]] = OpConstant %uint 1",
3897 "; CHECK-NOT: OpConstant",
3898 "; CHECK: OpStore {{%\\w+}} [[const]]",
3899 },
3900 },
3901 {
3902 /* .used_consts = */
3903 {
3904 "%used_const_float = OpConstant %float 3.1415",
3905 },
3906 /* .main_insts = */
3907 {
3908 "%float_var = OpVariable %_pf_float Output",
3909 "OpStore %float_var %used_const_float",
3910 },
3911 /* .dead_consts = */
3912 {
3913 "%dead_const_float = OpConstant %float 3.1415",
3914 },
3915 /* .checks = */
3916 {
3917 "; CHECK: [[const:%\\w+]] = OpConstant %float 3.1415",
3918 "; CHECK-NOT: OpConstant",
3919 "; CHECK: OpStore {{%\\w+}} [[const]]",
3920 },
3921 },
3922 {
3923 /* .used_consts = */
3924 {
3925 "%used_const_double = OpConstant %double 3.14",
3926 },
3927 /* .main_insts = */
3928 {
3929 "%double_var = OpVariable %_pf_double Output",
3930 "OpStore %double_var %used_const_double",
3931 },
3932 /* .dead_consts = */
3933 {
3934 "%dead_const_double = OpConstant %double 3.14",
3935 },
3936 /* .checks = */
3937 {
3938 "; CHECK: [[const:%\\w+]] = OpConstant %double 3.14",
3939 "; CHECK-NOT: OpConstant",
3940 "; CHECK: OpStore {{%\\w+}} [[const]]",
3941 },
3942 },
3943 // clang-format on
3944 })));
3945
3946 INSTANTIATE_TEST_SUITE_P(
3947 VectorTypeConstants, AggressiveEliminateDeadConstantTest,
3948 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
3949 // clang-format off
3950 // Tests eliminating dead constant type ivec2. One dead constant vector
3951 // and one used constant vector, each built from its own group of
3952 // scalar constants.
3953 {
3954 /* .used_consts = */
3955 {
3956 "%used_int_x = OpConstant %int 1",
3957 "%used_int_y = OpConstant %int 2",
3958 "%used_v2int = OpConstantComposite %v2int %used_int_x %used_int_y",
3959 },
3960 /* .main_insts = */
3961 {
3962 "%v2int_var = OpVariable %_pf_v2int Output",
3963 "OpStore %v2int_var %used_v2int",
3964 },
3965 /* .dead_consts = */
3966 {
3967 "%dead_int_x = OpConstant %int 1",
3968 "%dead_int_y = OpConstant %int 2",
3969 "%dead_v2int = OpConstantComposite %v2int %dead_int_x %dead_int_y",
3970 },
3971 /* .checks = */
3972 {
3973 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1",
3974 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2",
3975 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2int [[constx]] [[consty]]",
3976 "; CHECK-NOT: OpConstant",
3977 "; CHECK: OpStore {{%\\w+}} [[const]]",
3978 },
3979 },
3980 // Tests eliminating dead constant ivec3. One dead constant vector and
3981 // one used constant vector. But both built from a same group of
3982 // scalar constants.
3983 {
3984 /* .used_consts = */
3985 {
3986 "%used_int_x = OpConstant %int 1",
3987 "%used_int_y = OpConstant %int 2",
3988 "%used_int_z = OpConstant %int 3",
3989 "%used_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z",
3990 },
3991 /* .main_insts = */
3992 {
3993 "%v3int_var = OpVariable %_pf_v3int Output",
3994 "OpStore %v3int_var %used_v3int",
3995 },
3996 /* .dead_consts = */
3997 {
3998 "%dead_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z",
3999 },
4000 /* .checks = */
4001 {
4002 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1",
4003 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2",
4004 "; CHECK: [[constz:%\\w+]] = OpConstant %int 3",
4005 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3int [[constx]] [[consty]] [[constz]]",
4006 "; CHECK-NOT: OpConstant",
4007 "; CHECK: OpStore {{%\\w+}} [[const]]",
4008 },
4009 },
4010 // Tests eliminating dead constant vec2. One dead constant vector and
4011 // one used constant vector. Each built from its own group of scalar
4012 // constants.
4013 {
4014 /* .used_consts = */
4015 {
4016 "%used_float_x = OpConstant %float 3.1415",
4017 "%used_float_y = OpConstant %float 4.13",
4018 "%used_v2float = OpConstantComposite %v2float %used_float_x %used_float_y",
4019 },
4020 /* .main_insts = */
4021 {
4022 "%v2float_var = OpVariable %_pf_v2float Output",
4023 "OpStore %v2float_var %used_v2float",
4024 },
4025 /* .dead_consts = */
4026 {
4027 "%dead_float_x = OpConstant %float 3.1415",
4028 "%dead_float_y = OpConstant %float 4.13",
4029 "%dead_v2float = OpConstantComposite %v2float %dead_float_x %dead_float_y",
4030 },
4031 /* .checks = */
4032 {
4033 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415",
4034 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.13",
4035 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2float [[constx]] [[consty]]",
4036 "; CHECK-NOT: OpConstant",
4037 "; CHECK: OpStore {{%\\w+}} [[const]]",
4038 },
4039 },
4040 // Tests eliminating dead constant vec3. One dead constant vector and
4041 // one used constant vector. Both built from a same group of scalar
4042 // constants.
4043 {
4044 /* .used_consts = */
4045 {
4046 "%used_float_x = OpConstant %float 3.1415",
4047 "%used_float_y = OpConstant %float 4.25",
4048 "%used_float_z = OpConstant %float 4.75",
4049 "%used_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z",
4050 },
4051 /* .main_insts = */
4052 {
4053 "%v3float_var = OpVariable %_pf_v3float Output",
4054 "OpStore %v3float_var %used_v3float",
4055 },
4056 /* .dead_consts = */
4057 {
4058 "%dead_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z",
4059 },
4060 /* .checks = */
4061 {
4062 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415",
4063 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.25",
4064 "; CHECK: [[constz:%\\w+]] = OpConstant %float 4.75",
4065 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3float [[constx]] [[consty]]",
4066 "; CHECK-NOT: OpConstant",
4067 "; CHECK: OpStore {{%\\w+}} [[const]]",
4068 },
4069 },
4070 // clang-format on
4071 })));
4072
4073 INSTANTIATE_TEST_SUITE_P(
4074 StructTypeConstants, AggressiveEliminateDeadConstantTest,
4075 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4076 // clang-format off
4077 // A plain struct type dead constants. All of its components are dead
4078 // constants too.
4079 {
4080 /* .used_consts = */ {},
4081 /* .main_insts = */ {},
4082 /* .dead_consts = */
4083 {
4084 "%dead_bool = OpConstantTrue %bool",
4085 "%dead_int = OpConstant %int 1",
4086 "%dead_float = OpConstant %float 2.5",
4087 "%dead_double = OpConstant %double 3.14159265358979",
4088 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %dead_int %dead_float %dead_double",
4089 },
4090 /* .checks = */
4091 {
4092 "; CHECK-NOT: OpConstant",
4093 },
4094 },
4095 // A plain struct type dead constants. Some of its components are dead
4096 // constants while others are not.
4097 {
4098 /* .used_consts = */
4099 {
4100 "%used_int = OpConstant %int 1",
4101 "%used_double = OpConstant %double 3.14159265358979",
4102 },
4103 /* .main_insts = */
4104 {
4105 "%int_var = OpVariable %_pf_int Output",
4106 "OpStore %int_var %used_int",
4107 "%double_var = OpVariable %_pf_double Output",
4108 "OpStore %double_var %used_double",
4109 },
4110 /* .dead_consts = */
4111 {
4112 "%dead_bool = OpConstantTrue %bool",
4113 "%dead_float = OpConstant %float 2.5",
4114 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %used_int %dead_float %used_double",
4115 },
4116 /* .checks = */
4117 {
4118 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4119 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979",
4120 "; CHECK-NOT: OpConstant",
4121 "; CHECK: OpStore {{%\\w+}} [[int]]",
4122 "; CHECK: OpStore {{%\\w+}} [[double]]",
4123 },
4124 },
4125 // A nesting struct type dead constants. All components of both outer
4126 // and inner structs are dead and should be removed after dead constant
4127 // elimination.
4128 {
4129 /* .used_consts = */ {},
4130 /* .main_insts = */ {},
4131 /* .dead_consts = */
4132 {
4133 "%dead_bool = OpConstantTrue %bool",
4134 "%dead_int = OpConstant %int 1",
4135 "%dead_float = OpConstant %float 2.5",
4136 "%dead_double = OpConstant %double 3.1415926535",
4137 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %dead_int %dead_float %dead_double",
4138 "%dead_int2 = OpConstant %int 2",
4139 "%dead_double2 = OpConstant %double 1.428571428514",
4140 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int2 %dead_double2",
4141 },
4142 /* .checks = */
4143 {
4144 "; CHECK-NOT: OpConstant",
4145 },
4146 },
4147 // A nesting struct type dead constants. Some of its components are
4148 // dead constants while others are not.
4149 {
4150 /* .used_consts = */
4151 {
4152 "%used_int = OpConstant %int 1",
4153 "%used_double = OpConstant %double 3.14159265358979",
4154 },
4155 /* .main_insts = */
4156 {
4157 "%int_var = OpVariable %_pf_int Output",
4158 "OpStore %int_var %used_int",
4159 "%double_var = OpVariable %_pf_double Output",
4160 "OpStore %double_var %used_double",
4161 },
4162 /* .dead_consts = */
4163 {
4164 "%dead_bool = OpConstantTrue %bool",
4165 "%dead_float = OpConstant %float 2.5",
4166 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %used_int %dead_float %used_double",
4167 "%dead_int = OpConstant %int 2",
4168 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int %used_double",
4169 },
4170 /* .checks = */
4171 {
4172 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4173 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979",
4174 "; CHECK-NOT: OpConstant",
4175 "; CHECK: OpStore {{%\\w+}} [[int]]",
4176 "; CHECK: OpStore {{%\\w+}} [[double]]",
4177 },
4178 },
4179 // A nesting struct case. The inner struct is used while the outer struct is not
4180 {
4181 /* .used_const = */
4182 {
4183 "%used_bool = OpConstantTrue %bool",
4184 "%used_int = OpConstant %int 1",
4185 "%used_float = OpConstant %float 1.23",
4186 "%used_double = OpConstant %double 1.2345678901234",
4187 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4188 },
4189 /* .main_insts = */
4190 {
4191 "%bool_var = OpVariable %_pf_bool Output",
4192 "%bool_from_inner_struct = OpCompositeExtract %bool %used_inner_struct 0",
4193 "OpStore %bool_var %bool_from_inner_struct",
4194 },
4195 /* .dead_consts = */
4196 {
4197 "%dead_int = OpConstant %int 2",
4198 "%dead_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %dead_int %used_double"
4199 },
4200 /* .checks = */
4201 {
4202 "; CHECK: [[bool:%\\w+]] = OpConstantTrue",
4203 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4204 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23",
4205 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234",
4206 "; CHECK: [[struct:%\\w+]] = OpConstantComposite %inner_struct [[bool]] [[int]] [[float]] [[double]]",
4207 "; CHECK-NOT: OpConstant",
4208 "; CHECK: OpCompositeExtract %bool [[struct]]",
4209 }
4210 },
4211 // A nesting struct case. The outer struct is used, so the inner struct should not
4212 // be removed even though it is not used anywhere.
4213 {
4214 /* .used_const = */
4215 {
4216 "%used_bool = OpConstantTrue %bool",
4217 "%used_int = OpConstant %int 1",
4218 "%used_float = OpConstant %float 1.23",
4219 "%used_double = OpConstant %double 1.2345678901234",
4220 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4221 "%used_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double"
4222 },
4223 /* .main_insts = */
4224 {
4225 "%int_var = OpVariable %_pf_int Output",
4226 "%int_from_outer_struct = OpCompositeExtract %int %used_outer_struct 1",
4227 "OpStore %int_var %int_from_outer_struct",
4228 },
4229 /* .dead_consts = */ {},
4230 /* .checks = */
4231 {
4232 "; CHECK: [[bool:%\\w+]] = OpConstantTrue %bool",
4233 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4234 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23",
4235 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234",
4236 "; CHECK: [[inner_struct:%\\w+]] = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4237 "; CHECK: [[outer_struct:%\\w+]] = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double",
4238 "; CHECK: OpCompositeExtract %int [[outer_struct]]",
4239 },
4240 },
4241 // clang-format on
4242 })));
4243
4244 INSTANTIATE_TEST_SUITE_P(
4245 ScalarTypeSpecConstants, AggressiveEliminateDeadConstantTest,
4246 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4247 // clang-format off
4248 // All scalar type spec constants.
4249 {
4250 /* .used_consts = */
4251 {
4252 "%used_bool = OpSpecConstantTrue %bool",
4253 "%used_uint = OpSpecConstant %uint 2",
4254 "%used_int = OpSpecConstant %int 2",
4255 "%used_float = OpSpecConstant %float 2.5",
4256 "%used_double = OpSpecConstant %double 1.428571428514",
4257 },
4258 /* .main_insts = */
4259 {
4260 "%bool_var = OpVariable %_pf_bool Output",
4261 "%uint_var = OpVariable %_pf_uint Output",
4262 "%int_var = OpVariable %_pf_int Output",
4263 "%float_var = OpVariable %_pf_float Output",
4264 "%double_var = OpVariable %_pf_double Output",
4265 "OpStore %bool_var %used_bool",
4266 "OpStore %uint_var %used_uint",
4267 "OpStore %int_var %used_int",
4268 "OpStore %float_var %used_float",
4269 "OpStore %double_var %used_double",
4270 },
4271 /* .dead_consts = */
4272 {
4273 "%dead_bool = OpSpecConstantTrue %bool",
4274 "%dead_uint = OpSpecConstant %uint 2",
4275 "%dead_int = OpSpecConstant %int 2",
4276 "%dead_float = OpSpecConstant %float 2.5",
4277 "%dead_double = OpSpecConstant %double 1.428571428514",
4278 },
4279 /* .checks = */
4280 {
4281 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool",
4282 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 2",
4283 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 2",
4284 "; CHECK: [[float:%\\w+]] = OpSpecConstant %float 2.5",
4285 "; CHECK: [[double:%\\w+]] = OpSpecConstant %double 1.428571428514",
4286 "; CHECK-NOT: OpSpecConstant",
4287 "; CHECK: OpStore {{%\\w+}} [[bool]]",
4288 "; CHECK: OpStore {{%\\w+}} [[uint]]",
4289 "; CHECK: OpStore {{%\\w+}} [[int]]",
4290 "; CHECK: OpStore {{%\\w+}} [[float]]",
4291 "; CHECK: OpStore {{%\\w+}} [[double]]",
4292 },
4293 },
4294 // clang-format on
4295 })));
4296
4297 INSTANTIATE_TEST_SUITE_P(
4298 VectorTypeSpecConstants, AggressiveEliminateDeadConstantTest,
4299 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4300 // clang-format off
4301 // Bool vector type spec constants. One vector has all component dead,
4302 // another vector has one dead boolean and one used boolean.
4303 {
4304 /* .used_consts = */
4305 {
4306 "%used_bool = OpSpecConstantTrue %bool",
4307 },
4308 /* .main_insts = */
4309 {
4310 "%bool_var = OpVariable %_pf_bool Output",
4311 "OpStore %bool_var %used_bool",
4312 },
4313 /* .dead_consts = */
4314 {
4315 "%dead_bool = OpSpecConstantFalse %bool",
4316 "%dead_bool_vec1 = OpSpecConstantComposite %v2bool %dead_bool %dead_bool",
4317 "%dead_bool_vec2 = OpSpecConstantComposite %v2bool %dead_bool %used_bool",
4318 },
4319 /* .checks = */
4320 {
4321 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool",
4322 "; CHECK-NOT: OpSpecConstant",
4323 "; CHECK: OpStore {{%\\w+}} [[bool]]",
4324 },
4325 },
4326
4327 // Uint vector type spec constants. One vector has all component dead,
4328 // another vector has one dead unsigned integer and one used unsigned
4329 // integer.
4330 {
4331 /* .used_consts = */
4332 {
4333 "%used_uint = OpSpecConstant %uint 3",
4334 },
4335 /* .main_insts = */
4336 {
4337 "%uint_var = OpVariable %_pf_uint Output",
4338 "OpStore %uint_var %used_uint",
4339 },
4340 /* .dead_consts = */
4341 {
4342 "%dead_uint = OpSpecConstant %uint 1",
4343 "%dead_uint_vec1 = OpSpecConstantComposite %v2uint %dead_uint %dead_uint",
4344 "%dead_uint_vec2 = OpSpecConstantComposite %v2uint %dead_uint %used_uint",
4345 },
4346 /* .checks = */
4347 {
4348 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 3",
4349 "; CHECK-NOT: OpSpecConstant",
4350 "; CHECK: OpStore {{%\\w+}} [[uint]]",
4351 },
4352 },
4353
4354 // Int vector type spec constants. One vector has all component dead,
4355 // another vector has one dead integer and one used integer.
4356 {
4357 /* .used_consts = */
4358 {
4359 "%used_int = OpSpecConstant %int 3",
4360 },
4361 /* .main_insts = */
4362 {
4363 "%int_var = OpVariable %_pf_int Output",
4364 "OpStore %int_var %used_int",
4365 },
4366 /* .dead_consts = */
4367 {
4368 "%dead_int = OpSpecConstant %int 1",
4369 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_int %dead_int",
4370 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_int %used_int",
4371 },
4372 /* .checks = */
4373 {
4374 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 3",
4375 "; CHECK-NOT: OpSpecConstant",
4376 "; CHECK: OpStore {{%\\w+}} [[int]]",
4377 },
4378 },
4379
4380 // Int vector type spec constants built with both spec constants and
4381 // front-end constants.
4382 {
4383 /* .used_consts = */
4384 {
4385 "%used_spec_int = OpSpecConstant %int 3",
4386 "%used_front_end_int = OpConstant %int 3",
4387 },
4388 /* .main_insts = */
4389 {
4390 "%int_var1 = OpVariable %_pf_int Output",
4391 "OpStore %int_var1 %used_spec_int",
4392 "%int_var2 = OpVariable %_pf_int Output",
4393 "OpStore %int_var2 %used_front_end_int",
4394 },
4395 /* .dead_consts = */
4396 {
4397 "%dead_spec_int = OpSpecConstant %int 1",
4398 "%dead_front_end_int = OpConstant %int 1",
4399 // Dead front-end and dead spec constants
4400 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_spec_int %dead_front_end_int",
4401 // Used front-end and dead spec constants
4402 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_spec_int %used_front_end_int",
4403 // Dead front-end and used spec constants
4404 "%dead_int_vec3 = OpSpecConstantComposite %v2int %dead_front_end_int %used_spec_int",
4405 },
4406 /* .checks = */
4407 {
4408 "; CHECK: [[int1:%\\w+]] = OpSpecConstant %int 3",
4409 "; CHECK: [[int2:%\\w+]] = OpConstant %int 3",
4410 "; CHECK-NOT: OpSpecConstant",
4411 "; CHECK-NOT: OpConstant",
4412 "; CHECK: OpStore {{%\\w+}} [[int1]]",
4413 "; CHECK: OpStore {{%\\w+}} [[int2]]",
4414 },
4415 },
4416 // clang-format on
4417 })));
4418
4419 INSTANTIATE_TEST_SUITE_P(
4420 SpecConstantOp, AggressiveEliminateDeadConstantTest,
4421 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4422 // clang-format off
4423 // Cast operations: uint <-> int <-> bool
4424 {
4425 /* .used_consts = */ {},
4426 /* .main_insts = */ {},
4427 /* .dead_consts = */
4428 {
4429 // Assistant constants, only used in dead spec constant
4430 // operations.
4431 "%signed_zero = OpConstant %int 0",
4432 "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
4433 "%unsigned_zero = OpConstant %uint 0",
4434 "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
4435 "%signed_one = OpConstant %int 1",
4436 "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
4437 "%unsigned_one = OpConstant %uint 1",
4438 "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
4439
4440 // Spec constants that support casting to each other.
4441 "%dead_bool = OpSpecConstantTrue %bool",
4442 "%dead_uint = OpSpecConstant %uint 1",
4443 "%dead_int = OpSpecConstant %int 2",
4444 "%dead_bool_vec = OpSpecConstantComposite %v2bool %dead_bool %dead_bool",
4445 "%dead_uint_vec = OpSpecConstantComposite %v2uint %dead_uint %dead_uint",
4446 "%dead_int_vec = OpSpecConstantComposite %v2int %dead_int %dead_int",
4447
4448 // Scalar cast to boolean spec constant.
4449 "%int_to_bool = OpSpecConstantOp %bool INotEqual %dead_int %signed_zero",
4450 "%uint_to_bool = OpSpecConstantOp %bool INotEqual %dead_uint %unsigned_zero",
4451
4452 // Vector cast to boolean spec constant.
4453 "%int_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_int_vec %signed_zero_vec",
4454 "%uint_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_uint_vec %unsigned_zero_vec",
4455
4456 // Scalar cast to int spec constant.
4457 "%bool_to_int = OpSpecConstantOp %int Select %dead_bool %signed_one %signed_zero",
4458 "%uint_to_int = OpSpecConstantOp %uint IAdd %dead_uint %unsigned_zero",
4459
4460 // Vector cast to int spec constant.
4461 "%bool_to_int_vec = OpSpecConstantOp %v2int Select %dead_bool_vec %signed_one_vec %signed_zero_vec",
4462 "%uint_to_int_vec = OpSpecConstantOp %v2uint IAdd %dead_uint_vec %unsigned_zero_vec",
4463
4464 // Scalar cast to uint spec constant.
4465 "%bool_to_uint = OpSpecConstantOp %uint Select %dead_bool %unsigned_one %unsigned_zero",
4466 "%int_to_uint_vec = OpSpecConstantOp %uint IAdd %dead_int %signed_zero",
4467
4468 // Vector cast to uint spec constant.
4469 "%bool_to_uint_vec = OpSpecConstantOp %v2uint Select %dead_bool_vec %unsigned_one_vec %unsigned_zero_vec",
4470 "%int_to_uint = OpSpecConstantOp %v2uint IAdd %dead_int_vec %signed_zero_vec",
4471 },
4472 /* .checks = */
4473 {
4474 "; CHECK-NOT: OpConstant",
4475 "; CHECK-NOT: OpSpecConstant",
4476 },
4477 },
4478
4479 // Add, sub, mul, div, rem.
4480 {
4481 /* .used_consts = */ {},
4482 /* .main_insts = */ {},
4483 /* .dead_consts = */
4484 {
4485 "%dead_spec_int_a = OpSpecConstant %int 1",
4486 "%dead_spec_int_a_vec = OpSpecConstantComposite %v2int %dead_spec_int_a %dead_spec_int_a",
4487
4488 "%dead_spec_int_b = OpSpecConstant %int 2",
4489 "%dead_spec_int_b_vec = OpSpecConstantComposite %v2int %dead_spec_int_b %dead_spec_int_b",
4490
4491 "%dead_const_int_c = OpConstant %int 3",
4492 "%dead_const_int_c_vec = OpConstantComposite %v2int %dead_const_int_c %dead_const_int_c",
4493
4494 // Add
4495 "%add_a_b = OpSpecConstantOp %int IAdd %dead_spec_int_a %dead_spec_int_b",
4496 "%add_a_b_vec = OpSpecConstantOp %v2int IAdd %dead_spec_int_a_vec %dead_spec_int_b_vec",
4497
4498 // Sub
4499 "%sub_a_b = OpSpecConstantOp %int ISub %dead_spec_int_a %dead_spec_int_b",
4500 "%sub_a_b_vec = OpSpecConstantOp %v2int ISub %dead_spec_int_a_vec %dead_spec_int_b_vec",
4501
4502 // Mul
4503 "%mul_a_b = OpSpecConstantOp %int IMul %dead_spec_int_a %dead_spec_int_b",
4504 "%mul_a_b_vec = OpSpecConstantOp %v2int IMul %dead_spec_int_a_vec %dead_spec_int_b_vec",
4505
4506 // Div
4507 "%div_a_b = OpSpecConstantOp %int SDiv %dead_spec_int_a %dead_spec_int_b",
4508 "%div_a_b_vec = OpSpecConstantOp %v2int SDiv %dead_spec_int_a_vec %dead_spec_int_b_vec",
4509
4510 // Bitwise Xor
4511 "%xor_a_b = OpSpecConstantOp %int BitwiseXor %dead_spec_int_a %dead_spec_int_b",
4512 "%xor_a_b_vec = OpSpecConstantOp %v2int BitwiseXor %dead_spec_int_a_vec %dead_spec_int_b_vec",
4513
4514 // Scalar Comparison
4515 "%less_a_b = OpSpecConstantOp %bool SLessThan %dead_spec_int_a %dead_spec_int_b",
4516 },
4517 /* .checks = */
4518 {
4519 "; CHECK-NOT: OpConstant",
4520 "; CHECK-NOT: OpSpecConstant",
4521 },
4522 },
4523
4524 // Vectors without used swizzles should be removed.
4525 {
4526 /* .used_consts = */
4527 {
4528 "%used_int = OpConstant %int 3",
4529 },
4530 /* .main_insts = */
4531 {
4532 "%int_var = OpVariable %_pf_int Output",
4533 "OpStore %int_var %used_int",
4534 },
4535 /* .dead_consts = */
4536 {
4537 "%dead_int = OpConstant %int 3",
4538
4539 "%dead_spec_int_a = OpSpecConstant %int 1",
4540 "%vec_a = OpSpecConstantComposite %v4int %dead_spec_int_a %dead_spec_int_a %dead_int %dead_int",
4541
4542 "%dead_spec_int_b = OpSpecConstant %int 2",
4543 "%vec_b = OpSpecConstantComposite %v4int %dead_spec_int_b %dead_spec_int_b %used_int %used_int",
4544
4545 // Extract scalar
4546 "%a_x = OpSpecConstantOp %int CompositeExtract %vec_a 0",
4547 "%b_x = OpSpecConstantOp %int CompositeExtract %vec_b 0",
4548
4549 // Extract vector
4550 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1",
4551 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1",
4552 },
4553 /* .checks = */
4554 {
4555 "; CHECK: [[int:%\\w+]] = OpConstant %int 3",
4556 "; CHECK-NOT: OpConstant",
4557 "; CHECK-NOT: OpSpecConstant",
4558 "; CHECK: OpStore {{%\\w+}} [[int]]",
4559 },
4560 },
4561 // Vectors with used swizzles should not be removed.
4562 {
4563 /* .used_consts = */
4564 {
4565 "%used_int = OpConstant %int 3",
4566 "%used_spec_int_a = OpSpecConstant %int 1",
4567 "%used_spec_int_b = OpSpecConstant %int 2",
4568 // Create vectors
4569 "%vec_a = OpSpecConstantComposite %v4int %used_spec_int_a %used_spec_int_a %used_int %used_int",
4570 "%vec_b = OpSpecConstantComposite %v4int %used_spec_int_b %used_spec_int_b %used_int %used_int",
4571 // Extract vector
4572 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1",
4573 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1",
4574 },
4575 /* .main_insts = */
4576 {
4577 "%v2int_var_a = OpVariable %_pf_v2int Output",
4578 "%v2int_var_b = OpVariable %_pf_v2int Output",
4579 "OpStore %v2int_var_a %a_xy",
4580 "OpStore %v2int_var_b %b_xy",
4581 },
4582 /* .dead_consts = */ {},
4583 /* .checks = */
4584 {
4585 "; CHECK: [[int:%\\w+]] = OpConstant %int 3",
4586 "; CHECK: [[a:%\\w+]] = OpSpecConstant %int 1",
4587 "; CHECK: [[b:%\\w+]] = OpSpecConstant %int 2",
4588 "; CHECK: [[veca:%\\w+]] = OpSpecConstantComposite %v4int [[a]] [[a]] [[int]] [[int]]",
4589 "; CHECK: [[vecb:%\\w+]] = OpSpecConstantComposite %v4int [[b]] [[b]] [[int]] [[int]]",
4590 "; CHECK: [[exa:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[veca]] [[veca]] 0 1",
4591 "; CHECK: [[exb:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[vecb]] [[vecb]] 0 1",
4592 "; CHECK-NOT: OpConstant",
4593 "; CHECK-NOT: OpSpecConstant",
4594 "; CHECK: OpStore {{%\\w+}} [[exa]]",
4595 "; CHECK: OpStore {{%\\w+}} [[exb]]",
4596 },
4597 },
4598 // clang-format on
4599 })));
4600
4601 INSTANTIATE_TEST_SUITE_P(
4602 LongDefUseChain, AggressiveEliminateDeadConstantTest,
4603 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4604 // clang-format off
4605 // Long Def-Use chain with binary operations.
4606 {
4607 /* .used_consts = */
4608 {
4609 "%array_size = OpConstant %int 4",
4610 "%type_arr_int_4 = OpTypeArray %int %array_size",
4611 "%used_int_0 = OpConstant %int 100",
4612 "%used_int_1 = OpConstant %int 1",
4613 "%used_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_1",
4614 "%used_int_3 = OpSpecConstantOp %int ISub %used_int_0 %used_int_2",
4615 "%used_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_3",
4616 "%used_int_5 = OpSpecConstantOp %int ISub %used_int_0 %used_int_4",
4617 "%used_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_5",
4618 "%used_int_7 = OpSpecConstantOp %int ISub %used_int_0 %used_int_6",
4619 "%used_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_7",
4620 "%used_int_9 = OpSpecConstantOp %int ISub %used_int_0 %used_int_8",
4621 "%used_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_9",
4622 "%used_int_11 = OpSpecConstantOp %int ISub %used_int_0 %used_int_10",
4623 "%used_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_11",
4624 "%used_int_13 = OpSpecConstantOp %int ISub %used_int_0 %used_int_12",
4625 "%used_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_13",
4626 "%used_int_15 = OpSpecConstantOp %int ISub %used_int_0 %used_int_14",
4627 "%used_int_16 = OpSpecConstantOp %int ISub %used_int_0 %used_int_15",
4628 "%used_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_16",
4629 "%used_int_18 = OpSpecConstantOp %int ISub %used_int_0 %used_int_17",
4630 "%used_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_18",
4631 "%used_int_20 = OpSpecConstantOp %int ISub %used_int_0 %used_int_19",
4632 "%used_vec_a = OpSpecConstantComposite %v2int %used_int_18 %used_int_19",
4633 "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a",
4634 "%used_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0",
4635 "%used_array = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21",
4636 },
4637 /* .main_insts = */
4638 {
4639 "%int_var = OpVariable %_pf_int Output",
4640 "%used_array_2 = OpCompositeExtract %int %used_array 2",
4641 "OpStore %int_var %used_array_2",
4642 },
4643 /* .dead_consts = */
4644 {
4645 "%dead_int_1 = OpConstant %int 2",
4646 "%dead_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_1",
4647 "%dead_int_3 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_2",
4648 "%dead_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_3",
4649 "%dead_int_5 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_4",
4650 "%dead_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_5",
4651 "%dead_int_7 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_6",
4652 "%dead_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_7",
4653 "%dead_int_9 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_8",
4654 "%dead_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_9",
4655 "%dead_int_11 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_10",
4656 "%dead_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_11",
4657 "%dead_int_13 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_12",
4658 "%dead_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_13",
4659 "%dead_int_15 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_14",
4660 "%dead_int_16 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_15",
4661 "%dead_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_16",
4662 "%dead_int_18 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_17",
4663 "%dead_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_18",
4664 "%dead_int_20 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_19",
4665 "%dead_vec_a = OpSpecConstantComposite %v2int %dead_int_18 %dead_int_19",
4666 "%dead_vec_b = OpSpecConstantOp %v2int IMul %dead_vec_a %dead_vec_a",
4667 "%dead_int_21 = OpSpecConstantOp %int CompositeExtract %dead_vec_b 0",
4668 "%dead_array = OpConstantComposite %type_arr_int_4 %dead_int_20 %used_int_20 %dead_int_19 %used_int_19",
4669 },
4670 /* .checks = */
4671 {
4672 "; CHECK: OpConstant %int 4",
4673 "; CHECK: [[array:%\\w+]] = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21",
4674 "; CHECK-NOT: OpConstant",
4675 "; CHECK-NOT: OpSpecConstant",
4676 "; CHECK: OpStore {{%\\w+}} [[array]]",
4677 },
4678 },
4679 // Long Def-Use chain with swizzle
4680 // clang-format on
4681 })));
4682
TEST_F(AggressiveDCETest,DeadDecorationGroup)4683 TEST_F(AggressiveDCETest, DeadDecorationGroup) {
4684 // The decoration group should be eliminated because the target of group
4685 // decorate is dead.
4686 const std::string text = R"(
4687 ; CHECK-NOT: OpDecorat
4688 ; CHECK-NOT: OpGroupDecorate
4689 OpCapability Shader
4690 OpMemoryModel Logical GLSL450
4691 OpEntryPoint Fragment %main "main"
4692 OpExecutionMode %main OriginUpperLeft
4693 OpDecorate %1 Restrict
4694 OpDecorate %1 Aliased
4695 %1 = OpDecorationGroup
4696 OpGroupDecorate %1 %var
4697 %void = OpTypeVoid
4698 %func = OpTypeFunction %void
4699 %uint = OpTypeInt 32 0
4700 %uint_ptr = OpTypePointer Function %uint
4701 %main = OpFunction %void None %func
4702 %2 = OpLabel
4703 %var = OpVariable %uint_ptr Function
4704 OpReturn
4705 OpFunctionEnd
4706 )";
4707
4708 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4709 }
4710
TEST_F(AggressiveDCETest,DeadDecorationGroupAndValidDecorationMgr)4711 TEST_F(AggressiveDCETest, DeadDecorationGroupAndValidDecorationMgr) {
4712 // The decoration group should be eliminated because the target of group
4713 // decorate is dead.
4714 const std::string text = R"(
4715 OpCapability Shader
4716 OpMemoryModel Logical GLSL450
4717 OpEntryPoint Fragment %main "main"
4718 OpExecutionMode %main OriginUpperLeft
4719 OpDecorate %1 Restrict
4720 OpDecorate %1 Aliased
4721 %1 = OpDecorationGroup
4722 OpGroupDecorate %1 %var
4723 %void = OpTypeVoid
4724 %func = OpTypeFunction %void
4725 %uint = OpTypeInt 32 0
4726 %uint_ptr = OpTypePointer Function %uint
4727 %main = OpFunction %void None %func
4728 %2 = OpLabel
4729 %var = OpVariable %uint_ptr Function
4730 OpReturn
4731 OpFunctionEnd
4732 )";
4733
4734 auto pass = MakeUnique<AggressiveDCEPass>();
4735 auto consumer = [](spv_message_level_t, const char*, const spv_position_t&,
4736 const char* message) {
4737 std::cerr << message << std::endl;
4738 };
4739 auto context = BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, text);
4740
4741 // Build the decoration manager before the pass.
4742 context->get_decoration_mgr();
4743
4744 const auto status = pass->Run(context.get());
4745 EXPECT_EQ(status, Pass::Status::SuccessWithChange);
4746 }
4747
TEST_F(AggressiveDCETest,ParitallyDeadDecorationGroup)4748 TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroup) {
4749 const std::string text = R"(
4750 ; CHECK: OpDecorate [[grp:%\w+]] Restrict
4751 ; CHECK: [[grp]] = OpDecorationGroup
4752 ; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]]
4753 ; CHECK: [[output]] = OpVariable {{%\w+}} Output
4754 ; CHECK-NOT: OpVariable {{%\w+}} Function
4755 OpCapability Shader
4756 OpMemoryModel Logical GLSL450
4757 OpEntryPoint Fragment %main "main" %output
4758 OpExecutionMode %main OriginUpperLeft
4759 OpDecorate %1 Restrict
4760 %1 = OpDecorationGroup
4761 OpGroupDecorate %1 %var %output
4762 %void = OpTypeVoid
4763 %func = OpTypeFunction %void
4764 %uint = OpTypeInt 32 0
4765 %uint_ptr_Function = OpTypePointer Function %uint
4766 %uint_ptr_Output = OpTypePointer Output %uint
4767 %uint_0 = OpConstant %uint 0
4768 %output = OpVariable %uint_ptr_Output Output
4769 %main = OpFunction %void None %func
4770 %2 = OpLabel
4771 %var = OpVariable %uint_ptr_Function Function
4772 OpStore %output %uint_0
4773 OpReturn
4774 OpFunctionEnd
4775 )";
4776
4777 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4778 }
4779
TEST_F(AggressiveDCETest,ParitallyDeadDecorationGroupDifferentGroupDecorate)4780 TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroupDifferentGroupDecorate) {
4781 const std::string text = R"(
4782 ; CHECK: OpDecorate [[grp:%\w+]] Restrict
4783 ; CHECK: [[grp]] = OpDecorationGroup
4784 ; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]]
4785 ; CHECK-NOT: OpGroupDecorate
4786 ; CHECK: [[output]] = OpVariable {{%\w+}} Output
4787 ; CHECK-NOT: OpVariable {{%\w+}} Function
4788 OpCapability Shader
4789 OpMemoryModel Logical GLSL450
4790 OpEntryPoint Fragment %main "main" %output
4791 OpExecutionMode %main OriginUpperLeft
4792 OpDecorate %1 Restrict
4793 %1 = OpDecorationGroup
4794 OpGroupDecorate %1 %output
4795 OpGroupDecorate %1 %var
4796 %void = OpTypeVoid
4797 %func = OpTypeFunction %void
4798 %uint = OpTypeInt 32 0
4799 %uint_ptr_Function = OpTypePointer Function %uint
4800 %uint_ptr_Output = OpTypePointer Output %uint
4801 %uint_0 = OpConstant %uint 0
4802 %output = OpVariable %uint_ptr_Output Output
4803 %main = OpFunction %void None %func
4804 %2 = OpLabel
4805 %var = OpVariable %uint_ptr_Function Function
4806 OpStore %output %uint_0
4807 OpReturn
4808 OpFunctionEnd
4809 )";
4810
4811 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4812 }
4813
TEST_F(AggressiveDCETest,DeadGroupMemberDecorate)4814 TEST_F(AggressiveDCETest, DeadGroupMemberDecorate) {
4815 const std::string text = R"(
4816 ; CHECK-NOT: OpDec
4817 ; CHECK-NOT: OpGroup
4818 OpCapability Shader
4819 OpMemoryModel Logical GLSL450
4820 OpEntryPoint Fragment %main "main"
4821 OpExecutionMode %main OriginUpperLeft
4822 OpDecorate %1 Offset 0
4823 OpDecorate %1 Uniform
4824 %1 = OpDecorationGroup
4825 OpGroupMemberDecorate %1 %var 0
4826 %void = OpTypeVoid
4827 %func = OpTypeFunction %void
4828 %uint = OpTypeInt 32 0
4829 %struct = OpTypeStruct %uint %uint
4830 %struct_ptr = OpTypePointer Function %struct
4831 %main = OpFunction %void None %func
4832 %2 = OpLabel
4833 %var = OpVariable %struct_ptr Function
4834 OpReturn
4835 OpFunctionEnd
4836 )";
4837
4838 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4839 }
4840
TEST_F(AggressiveDCETest,PartiallyDeadGroupMemberDecorate)4841 TEST_F(AggressiveDCETest, PartiallyDeadGroupMemberDecorate) {
4842 const std::string text = R"(
4843 ; CHECK: OpDecorate [[grp:%\w+]] Offset 0
4844 ; CHECK: OpDecorate [[grp]] RelaxedPrecision
4845 ; CHECK: [[grp]] = OpDecorationGroup
4846 ; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1
4847 ; CHECK: [[output]] = OpTypeStruct
4848 ; CHECK-NOT: OpTypeStruct
4849 OpCapability Shader
4850 OpMemoryModel Logical GLSL450
4851 OpEntryPoint Fragment %main "main" %output
4852 OpExecutionMode %main OriginUpperLeft
4853 OpDecorate %1 Offset 0
4854 OpDecorate %1 RelaxedPrecision
4855 %1 = OpDecorationGroup
4856 OpGroupMemberDecorate %1 %var_struct 0 %output_struct 1
4857 %void = OpTypeVoid
4858 %func = OpTypeFunction %void
4859 %uint = OpTypeInt 32 0
4860 %var_struct = OpTypeStruct %uint %uint
4861 %output_struct = OpTypeStruct %uint %uint
4862 %struct_ptr_Function = OpTypePointer Function %var_struct
4863 %struct_ptr_Output = OpTypePointer Output %output_struct
4864 %uint_ptr_Output = OpTypePointer Output %uint
4865 %output = OpVariable %struct_ptr_Output Output
4866 %uint_0 = OpConstant %uint 0
4867 %main = OpFunction %void None %func
4868 %2 = OpLabel
4869 %var = OpVariable %struct_ptr_Function Function
4870 %3 = OpAccessChain %uint_ptr_Output %output %uint_0
4871 OpStore %3 %uint_0
4872 OpReturn
4873 OpFunctionEnd
4874 )";
4875
4876 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4877 }
4878
TEST_F(AggressiveDCETest,PartiallyDeadGroupMemberDecorateDifferentGroupDecorate)4879 TEST_F(AggressiveDCETest,
4880 PartiallyDeadGroupMemberDecorateDifferentGroupDecorate) {
4881 const std::string text = R"(
4882 ; CHECK: OpDecorate [[grp:%\w+]] Offset 0
4883 ; CHECK: OpDecorate [[grp]] RelaxedPrecision
4884 ; CHECK: [[grp]] = OpDecorationGroup
4885 ; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1
4886 ; CHECK-NOT: OpGroupMemberDecorate
4887 ; CHECK: [[output]] = OpTypeStruct
4888 ; CHECK-NOT: OpTypeStruct
4889 OpCapability Shader
4890 OpMemoryModel Logical GLSL450
4891 OpEntryPoint Fragment %main "main" %output
4892 OpExecutionMode %main OriginUpperLeft
4893 OpDecorate %1 Offset 0
4894 OpDecorate %1 RelaxedPrecision
4895 %1 = OpDecorationGroup
4896 OpGroupMemberDecorate %1 %var_struct 0
4897 OpGroupMemberDecorate %1 %output_struct 1
4898 %void = OpTypeVoid
4899 %func = OpTypeFunction %void
4900 %uint = OpTypeInt 32 0
4901 %var_struct = OpTypeStruct %uint %uint
4902 %output_struct = OpTypeStruct %uint %uint
4903 %struct_ptr_Function = OpTypePointer Function %var_struct
4904 %struct_ptr_Output = OpTypePointer Output %output_struct
4905 %uint_ptr_Output = OpTypePointer Output %uint
4906 %output = OpVariable %struct_ptr_Output Output
4907 %uint_0 = OpConstant %uint 0
4908 %main = OpFunction %void None %func
4909 %2 = OpLabel
4910 %var = OpVariable %struct_ptr_Function Function
4911 %3 = OpAccessChain %uint_ptr_Output %output %uint_0
4912 OpStore %3 %uint_0
4913 OpReturn
4914 OpFunctionEnd
4915 )";
4916
4917 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4918 }
4919
4920 // Test for #1404
TEST_F(AggressiveDCETest,DontRemoveWorkgroupSize)4921 TEST_F(AggressiveDCETest, DontRemoveWorkgroupSize) {
4922 const std::string text = R"(
4923 ; CHECK: OpDecorate [[wgs:%\w+]] BuiltIn WorkgroupSize
4924 ; CHECK: [[wgs]] = OpSpecConstantComposite
4925 OpCapability Shader
4926 OpMemoryModel Logical GLSL450
4927 OpEntryPoint GLCompute %func "func"
4928 OpExecutionMode %func LocalSize 1 1 1
4929 OpDecorate %1 BuiltIn WorkgroupSize
4930 %void = OpTypeVoid
4931 %int = OpTypeInt 32 0
4932 %functy = OpTypeFunction %void
4933 %v3int = OpTypeVector %int 3
4934 %2 = OpSpecConstant %int 1
4935 %1 = OpSpecConstantComposite %v3int %2 %2 %2
4936 %func = OpFunction %void None %functy
4937 %3 = OpLabel
4938 OpReturn
4939 OpFunctionEnd
4940 )";
4941
4942 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4943 }
4944
4945 // Test for #1214
TEST_F(AggressiveDCETest,LoopHeaderIsAlsoAnotherLoopMerge)4946 TEST_F(AggressiveDCETest, LoopHeaderIsAlsoAnotherLoopMerge) {
4947 const std::string text = R"(OpCapability Shader
4948 OpMemoryModel Logical GLSL450
4949 OpEntryPoint Fragment %1 "func" %2
4950 OpExecutionMode %1 OriginUpperLeft
4951 %void = OpTypeVoid
4952 %bool = OpTypeBool
4953 %true = OpConstantTrue %bool
4954 %uint = OpTypeInt 32 0
4955 %_ptr_Output_uint = OpTypePointer Output %uint
4956 %2 = OpVariable %_ptr_Output_uint Output
4957 %uint_0 = OpConstant %uint 0
4958 %9 = OpTypeFunction %void
4959 %1 = OpFunction %void None %9
4960 %10 = OpLabel
4961 OpBranch %11
4962 %11 = OpLabel
4963 OpLoopMerge %12 %13 None
4964 OpBranchConditional %true %14 %13
4965 %14 = OpLabel
4966 OpStore %2 %uint_0
4967 OpLoopMerge %15 %16 None
4968 OpBranchConditional %true %15 %16
4969 %16 = OpLabel
4970 OpBranch %14
4971 %15 = OpLabel
4972 OpBranchConditional %true %12 %13
4973 %13 = OpLabel
4974 OpBranch %11
4975 %12 = OpLabel
4976 %17 = OpPhi %uint %uint_0 %15 %uint_0 %18
4977 OpStore %2 %17
4978 OpLoopMerge %19 %18 None
4979 OpBranchConditional %true %19 %18
4980 %18 = OpLabel
4981 OpBranch %12
4982 %19 = OpLabel
4983 OpReturn
4984 OpFunctionEnd
4985 )";
4986
4987 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
4988 }
4989
TEST_F(AggressiveDCETest,BreaksDontVisitPhis)4990 TEST_F(AggressiveDCETest, BreaksDontVisitPhis) {
4991 const std::string text = R"(
4992 OpCapability Shader
4993 OpMemoryModel Logical GLSL450
4994 OpEntryPoint Fragment %func "func" %var
4995 OpExecutionMode %func OriginUpperLeft
4996 %void = OpTypeVoid
4997 %bool = OpTypeBool
4998 %true = OpConstantTrue %bool
4999 %int = OpTypeInt 32 0
5000 %int_ptr_Output = OpTypePointer Output %int
5001 %var = OpVariable %int_ptr_Output Output
5002 %int0 = OpConstant %int 0
5003 %functy = OpTypeFunction %void
5004 %func = OpFunction %void None %functy
5005 %entry = OpLabel
5006 OpBranch %outer_header
5007 %outer_header = OpLabel
5008 OpLoopMerge %outer_merge %outer_continue None
5009 OpBranchConditional %true %inner_header %outer_continue
5010 %inner_header = OpLabel
5011 %phi = OpPhi %int %int0 %outer_header %int0 %inner_continue
5012 OpStore %var %phi
5013 OpLoopMerge %inner_merge %inner_continue None
5014 OpBranchConditional %true %inner_merge %inner_continue
5015 %inner_continue = OpLabel
5016 OpBranch %inner_header
5017 %inner_merge = OpLabel
5018 OpBranch %outer_continue
5019 %outer_continue = OpLabel
5020 %p = OpPhi %int %int0 %outer_header %int0 %inner_merge
5021 OpStore %var %p
5022 OpBranch %outer_header
5023 %outer_merge = OpLabel
5024 OpReturn
5025 OpFunctionEnd
5026 )";
5027
5028 EXPECT_EQ(Pass::Status::SuccessWithoutChange,
5029 std::get<1>(SinglePassRunAndDisassemble<AggressiveDCEPass>(
5030 text, false, true)));
5031 }
5032
5033 // Test for #1212
TEST_F(AggressiveDCETest,ConstStoreInnerLoop)5034 TEST_F(AggressiveDCETest, ConstStoreInnerLoop) {
5035 const std::string text = R"(OpCapability Shader
5036 OpMemoryModel Logical GLSL450
5037 OpEntryPoint Vertex %1 "main" %2
5038 %void = OpTypeVoid
5039 %4 = OpTypeFunction %void
5040 %float = OpTypeFloat 32
5041 %bool = OpTypeBool
5042 %true = OpConstantTrue %bool
5043 %_ptr_Output_float = OpTypePointer Output %float
5044 %2 = OpVariable %_ptr_Output_float Output
5045 %float_3 = OpConstant %float 3
5046 %1 = OpFunction %void None %4
5047 %13 = OpLabel
5048 OpBranch %14
5049 %14 = OpLabel
5050 OpLoopMerge %15 %16 None
5051 OpBranchConditional %true %17 %15
5052 %17 = OpLabel
5053 OpStore %2 %float_3
5054 OpLoopMerge %18 %17 None
5055 OpBranchConditional %true %18 %17
5056 %18 = OpLabel
5057 OpBranch %15
5058 %16 = OpLabel
5059 OpBranch %14
5060 %15 = OpLabel
5061 OpBranch %20
5062 %20 = OpLabel
5063 OpReturn
5064 OpFunctionEnd
5065 )";
5066
5067 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5068 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5069 }
5070
5071 // Test for #1212
TEST_F(AggressiveDCETest,InnerLoopCopy)5072 TEST_F(AggressiveDCETest, InnerLoopCopy) {
5073 const std::string text = R"(OpCapability Shader
5074 OpMemoryModel Logical GLSL450
5075 OpEntryPoint Vertex %1 "main" %2 %3
5076 %void = OpTypeVoid
5077 %5 = OpTypeFunction %void
5078 %float = OpTypeFloat 32
5079 %bool = OpTypeBool
5080 %true = OpConstantTrue %bool
5081 %_ptr_Output_float = OpTypePointer Output %float
5082 %_ptr_Input_float = OpTypePointer Input %float
5083 %2 = OpVariable %_ptr_Output_float Output
5084 %3 = OpVariable %_ptr_Input_float Input
5085 %1 = OpFunction %void None %5
5086 %14 = OpLabel
5087 OpBranch %15
5088 %15 = OpLabel
5089 OpLoopMerge %16 %17 None
5090 OpBranchConditional %true %18 %16
5091 %18 = OpLabel
5092 %19 = OpLoad %float %3
5093 OpStore %2 %19
5094 OpLoopMerge %20 %18 None
5095 OpBranchConditional %true %20 %18
5096 %20 = OpLabel
5097 OpBranch %16
5098 %17 = OpLabel
5099 OpBranch %15
5100 %16 = OpLabel
5101 OpBranch %22
5102 %22 = OpLabel
5103 OpReturn
5104 OpFunctionEnd
5105 )";
5106
5107 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5108 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5109 }
5110
TEST_F(AggressiveDCETest,AtomicAdd)5111 TEST_F(AggressiveDCETest, AtomicAdd) {
5112 const std::string text = R"(OpCapability SampledBuffer
5113 OpCapability StorageImageExtendedFormats
5114 OpCapability ImageBuffer
5115 OpCapability Shader
5116 %1 = OpExtInstImport "GLSL.std.450"
5117 OpMemoryModel Logical GLSL450
5118 OpEntryPoint GLCompute %2 "min"
5119 OpExecutionMode %2 LocalSize 64 1 1
5120 OpSource HLSL 600
5121 OpDecorate %4 DescriptorSet 4
5122 OpDecorate %4 Binding 70
5123 %uint = OpTypeInt 32 0
5124 %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
5125 %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
5126 %_ptr_Private_6 = OpTypePointer Private %6
5127 %void = OpTypeVoid
5128 %10 = OpTypeFunction %void
5129 %uint_0 = OpConstant %uint 0
5130 %uint_1 = OpConstant %uint 1
5131 %_ptr_Image_uint = OpTypePointer Image %uint
5132 %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
5133 %16 = OpVariable %_ptr_Private_6 Private
5134 %2 = OpFunction %void None %10
5135 %17 = OpLabel
5136 %18 = OpLoad %6 %4
5137 OpStore %16 %18
5138 %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
5139 %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
5140 OpReturn
5141 OpFunctionEnd
5142 )";
5143
5144 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5145 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5146 }
5147
TEST_F(AggressiveDCETest,SafelyRemoveDecorateString)5148 TEST_F(AggressiveDCETest, SafelyRemoveDecorateString) {
5149 const std::string preamble = R"(OpCapability Shader
5150 OpExtension "SPV_GOOGLE_hlsl_functionality1"
5151 OpMemoryModel Logical GLSL450
5152 OpEntryPoint Fragment %1 "main"
5153 OpExecutionMode %1 OriginUpperLeft
5154 )";
5155
5156 const std::string body_before =
5157 R"(OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "FOOBAR"
5158 %void = OpTypeVoid
5159 %4 = OpTypeFunction %void
5160 %uint = OpTypeInt 32 0
5161 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5162 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
5163 %1 = OpFunction %void None %4
5164 %7 = OpLabel
5165 OpReturn
5166 OpFunctionEnd
5167 )";
5168
5169 const std::string body_after = R"(%void = OpTypeVoid
5170 %4 = OpTypeFunction %void
5171 %1 = OpFunction %void None %4
5172 %7 = OpLabel
5173 OpReturn
5174 OpFunctionEnd
5175 )";
5176
5177 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5178 SinglePassRunAndCheck<AggressiveDCEPass>(preamble + body_before,
5179 preamble + body_after, true, true);
5180 }
5181
TEST_F(AggressiveDCETest,CopyMemoryToGlobal)5182 TEST_F(AggressiveDCETest, CopyMemoryToGlobal) {
5183 // |local| is loaded in an OpCopyMemory instruction. So the store must be
5184 // kept alive.
5185 const std::string test =
5186 R"(OpCapability Geometry
5187 %1 = OpExtInstImport "GLSL.std.450"
5188 OpMemoryModel Logical GLSL450
5189 OpEntryPoint Geometry %main "main" %global
5190 OpExecutionMode %main Triangles
5191 OpExecutionMode %main Invocations 1
5192 OpExecutionMode %main OutputTriangleStrip
5193 OpExecutionMode %main OutputVertices 5
5194 OpSource GLSL 440
5195 OpName %main "main"
5196 OpName %local "local"
5197 OpName %global "global"
5198 %void = OpTypeVoid
5199 %7 = OpTypeFunction %void
5200 %float = OpTypeFloat 32
5201 %v4float = OpTypeVector %float 4
5202 %12 = OpConstantNull %v4float
5203 %_ptr_Function_v4float = OpTypePointer Function %v4float
5204 %_ptr_Output_v4float = OpTypePointer Output %v4float
5205 %global = OpVariable %_ptr_Output_v4float Output
5206 %main = OpFunction %void None %7
5207 %19 = OpLabel
5208 %local = OpVariable %_ptr_Function_v4float Function
5209 OpStore %local %12
5210 OpCopyMemory %global %local
5211 OpEndPrimitive
5212 OpReturn
5213 OpFunctionEnd
5214 )";
5215
5216 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5217 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5218 }
5219
TEST_F(AggressiveDCETest,CopyMemoryToLocal)5220 TEST_F(AggressiveDCETest, CopyMemoryToLocal) {
5221 // Make sure the store to |local2| using OpCopyMemory is kept and keeps
5222 // |local1| alive.
5223 const std::string test =
5224 R"(OpCapability Geometry
5225 %1 = OpExtInstImport "GLSL.std.450"
5226 OpMemoryModel Logical GLSL450
5227 OpEntryPoint Geometry %main "main" %global
5228 OpExecutionMode %main Triangles
5229 OpExecutionMode %main Invocations 1
5230 OpExecutionMode %main OutputTriangleStrip
5231 OpExecutionMode %main OutputVertices 5
5232 OpSource GLSL 440
5233 OpName %main "main"
5234 OpName %local1 "local1"
5235 OpName %local2 "local2"
5236 OpName %global "global"
5237 %void = OpTypeVoid
5238 %7 = OpTypeFunction %void
5239 %float = OpTypeFloat 32
5240 %v4float = OpTypeVector %float 4
5241 %12 = OpConstantNull %v4float
5242 %_ptr_Function_v4float = OpTypePointer Function %v4float
5243 %_ptr_Output_v4float = OpTypePointer Output %v4float
5244 %global = OpVariable %_ptr_Output_v4float Output
5245 %main = OpFunction %void None %7
5246 %19 = OpLabel
5247 %local1 = OpVariable %_ptr_Function_v4float Function
5248 %local2 = OpVariable %_ptr_Function_v4float Function
5249 OpStore %local1 %12
5250 OpCopyMemory %local2 %local1
5251 OpCopyMemory %global %local2
5252 OpEndPrimitive
5253 OpReturn
5254 OpFunctionEnd
5255 )";
5256
5257 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5258 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5259 }
5260
TEST_F(AggressiveDCETest,RemoveCopyMemoryToLocal)5261 TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal) {
5262 // Test that we remove function scope variables that are stored to using
5263 // OpCopyMemory, but are never loaded. We can remove both |local1| and
5264 // |local2|.
5265 const std::string test =
5266 R"(OpCapability Geometry
5267 %1 = OpExtInstImport "GLSL.std.450"
5268 OpMemoryModel Logical GLSL450
5269 OpEntryPoint Geometry %main "main" %global
5270 OpExecutionMode %main Triangles
5271 OpExecutionMode %main Invocations 1
5272 OpExecutionMode %main OutputTriangleStrip
5273 OpExecutionMode %main OutputVertices 5
5274 OpSource GLSL 440
5275 OpName %main "main"
5276 OpName %local1 "local1"
5277 OpName %local2 "local2"
5278 OpName %global "global"
5279 %void = OpTypeVoid
5280 %7 = OpTypeFunction %void
5281 %float = OpTypeFloat 32
5282 %v4float = OpTypeVector %float 4
5283 %12 = OpConstantNull %v4float
5284 %_ptr_Function_v4float = OpTypePointer Function %v4float
5285 %_ptr_Output_v4float = OpTypePointer Output %v4float
5286 %global = OpVariable %_ptr_Output_v4float Output
5287 %main = OpFunction %void None %7
5288 %19 = OpLabel
5289 %local1 = OpVariable %_ptr_Function_v4float Function
5290 %local2 = OpVariable %_ptr_Function_v4float Function
5291 OpStore %local1 %12
5292 OpCopyMemory %local2 %local1
5293 OpEndPrimitive
5294 OpReturn
5295 OpFunctionEnd
5296 )";
5297
5298 const std::string result =
5299 R"(OpCapability Geometry
5300 %1 = OpExtInstImport "GLSL.std.450"
5301 OpMemoryModel Logical GLSL450
5302 OpEntryPoint Geometry %main "main" %global
5303 OpExecutionMode %main Triangles
5304 OpExecutionMode %main Invocations 1
5305 OpExecutionMode %main OutputTriangleStrip
5306 OpExecutionMode %main OutputVertices 5
5307 OpSource GLSL 440
5308 OpName %main "main"
5309 OpName %global "global"
5310 %void = OpTypeVoid
5311 %7 = OpTypeFunction %void
5312 %float = OpTypeFloat 32
5313 %v4float = OpTypeVector %float 4
5314 %_ptr_Output_v4float = OpTypePointer Output %v4float
5315 %global = OpVariable %_ptr_Output_v4float Output
5316 %main = OpFunction %void None %7
5317 %19 = OpLabel
5318 OpEndPrimitive
5319 OpReturn
5320 OpFunctionEnd
5321 )";
5322
5323 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5324 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true);
5325 }
5326
TEST_F(AggressiveDCETest,RemoveCopyMemoryToLocal2)5327 TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal2) {
5328 // We are able to remove "local2" because it is not loaded, but have to keep
5329 // the stores to "local1".
5330 const std::string test =
5331 R"(OpCapability Geometry
5332 %1 = OpExtInstImport "GLSL.std.450"
5333 OpMemoryModel Logical GLSL450
5334 OpEntryPoint Geometry %main "main" %global
5335 OpExecutionMode %main Triangles
5336 OpExecutionMode %main Invocations 1
5337 OpExecutionMode %main OutputTriangleStrip
5338 OpExecutionMode %main OutputVertices 5
5339 OpSource GLSL 440
5340 OpName %main "main"
5341 OpName %local1 "local1"
5342 OpName %local2 "local2"
5343 OpName %global "global"
5344 %void = OpTypeVoid
5345 %7 = OpTypeFunction %void
5346 %float = OpTypeFloat 32
5347 %v4float = OpTypeVector %float 4
5348 %12 = OpConstantNull %v4float
5349 %_ptr_Function_v4float = OpTypePointer Function %v4float
5350 %_ptr_Output_v4float = OpTypePointer Output %v4float
5351 %global = OpVariable %_ptr_Output_v4float Output
5352 %main = OpFunction %void None %7
5353 %19 = OpLabel
5354 %local1 = OpVariable %_ptr_Function_v4float Function
5355 %local2 = OpVariable %_ptr_Function_v4float Function
5356 OpStore %local1 %12
5357 OpCopyMemory %local2 %local1
5358 OpCopyMemory %global %local1
5359 OpEndPrimitive
5360 OpReturn
5361 OpFunctionEnd
5362 )";
5363
5364 const std::string result =
5365 R"(OpCapability Geometry
5366 %1 = OpExtInstImport "GLSL.std.450"
5367 OpMemoryModel Logical GLSL450
5368 OpEntryPoint Geometry %main "main" %global
5369 OpExecutionMode %main Triangles
5370 OpExecutionMode %main Invocations 1
5371 OpExecutionMode %main OutputTriangleStrip
5372 OpExecutionMode %main OutputVertices 5
5373 OpSource GLSL 440
5374 OpName %main "main"
5375 OpName %local1 "local1"
5376 OpName %global "global"
5377 %void = OpTypeVoid
5378 %7 = OpTypeFunction %void
5379 %float = OpTypeFloat 32
5380 %v4float = OpTypeVector %float 4
5381 %12 = OpConstantNull %v4float
5382 %_ptr_Function_v4float = OpTypePointer Function %v4float
5383 %_ptr_Output_v4float = OpTypePointer Output %v4float
5384 %global = OpVariable %_ptr_Output_v4float Output
5385 %main = OpFunction %void None %7
5386 %19 = OpLabel
5387 %local1 = OpVariable %_ptr_Function_v4float Function
5388 OpStore %local1 %12
5389 OpCopyMemory %global %local1
5390 OpEndPrimitive
5391 OpReturn
5392 OpFunctionEnd
5393 )";
5394
5395 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5396 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true);
5397 }
5398
TEST_F(AggressiveDCETest,StructuredIfWithConditionalExit)5399 TEST_F(AggressiveDCETest, StructuredIfWithConditionalExit) {
5400 // We are able to remove "local2" because it is not loaded, but have to keep
5401 // the stores to "local1".
5402 const std::string test =
5403 R"(OpCapability Shader
5404 %1 = OpExtInstImport "GLSL.std.450"
5405 OpMemoryModel Logical GLSL450
5406 OpEntryPoint Fragment %main "main"
5407 OpExecutionMode %main OriginUpperLeft
5408 OpSource GLSL 140
5409 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
5410 OpSourceExtension "GL_GOOGLE_include_directive"
5411 OpName %main "main"
5412 OpName %a "a"
5413 %void = OpTypeVoid
5414 %5 = OpTypeFunction %void
5415 %int = OpTypeInt 32 1
5416 %_ptr_Uniform_int = OpTypePointer Uniform %int
5417 %int_0 = OpConstant %int 0
5418 %bool = OpTypeBool
5419 %int_100 = OpConstant %int 100
5420 %int_1 = OpConstant %int 1
5421 %a = OpVariable %_ptr_Uniform_int Uniform
5422 %main = OpFunction %void None %5
5423 %12 = OpLabel
5424 %13 = OpLoad %int %a
5425 %14 = OpSGreaterThan %bool %13 %int_0
5426 OpSelectionMerge %15 None
5427 OpBranchConditional %14 %16 %15
5428 %16 = OpLabel
5429 %17 = OpLoad %int %a
5430 %18 = OpSLessThan %bool %17 %int_100
5431 OpBranchConditional %18 %19 %15
5432 %19 = OpLabel
5433 OpStore %a %int_1
5434 OpBranch %15
5435 %15 = OpLabel
5436 OpReturn
5437 OpFunctionEnd
5438 )";
5439
5440 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5441 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5442 }
5443
TEST_F(AggressiveDCETest,CountingLoopNotEliminated)5444 TEST_F(AggressiveDCETest, CountingLoopNotEliminated) {
5445 // #version 310 es
5446 //
5447 // precision highp float;
5448 // precision highp int;
5449 //
5450 // layout(location = 0) out vec4 _GLF_color;
5451 //
5452 // void main()
5453 // {
5454 // float data[1];
5455 // for (int c = 0; c < 1; c++) {
5456 // if (true) {
5457 // do {
5458 // for (int i = 0; i < 1; i++) {
5459 // data[i] = 1.0;
5460 // }
5461 // } while (false);
5462 // }
5463 // }
5464 // _GLF_color = vec4(data[0], 0.0, 0.0, 1.0);
5465 // }
5466 const std::string test =
5467 R"(OpCapability Shader
5468 %1 = OpExtInstImport "GLSL.std.450"
5469 OpMemoryModel Logical GLSL450
5470 OpEntryPoint Fragment %main "main" %_GLF_color
5471 OpExecutionMode %main OriginUpperLeft
5472 OpSource ESSL 310
5473 OpName %main "main"
5474 OpName %c "c"
5475 OpName %i "i"
5476 OpName %data "data"
5477 OpName %_GLF_color "_GLF_color"
5478 OpDecorate %_GLF_color Location 0
5479 %void = OpTypeVoid
5480 %8 = OpTypeFunction %void
5481 %int = OpTypeInt 32 1
5482 %_ptr_Function_int = OpTypePointer Function %int
5483 %int_0 = OpConstant %int 0
5484 %int_1 = OpConstant %int 1
5485 %bool = OpTypeBool
5486 %float = OpTypeFloat 32
5487 %uint = OpTypeInt 32 0
5488 %uint_1 = OpConstant %uint 1
5489 %_arr_float_uint_1 = OpTypeArray %float %uint_1
5490 %_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1
5491 %float_1 = OpConstant %float 1
5492 %_ptr_Function_float = OpTypePointer Function %float
5493 %false = OpConstantFalse %bool
5494 %v4float = OpTypeVector %float 4
5495 %_ptr_Output_v4float = OpTypePointer Output %v4float
5496 %_GLF_color = OpVariable %_ptr_Output_v4float Output
5497 %float_0 = OpConstant %float 0
5498 %main = OpFunction %void None %8
5499 %26 = OpLabel
5500 %c = OpVariable %_ptr_Function_int Function
5501 %i = OpVariable %_ptr_Function_int Function
5502 %data = OpVariable %_ptr_Function__arr_float_uint_1 Function
5503 OpStore %c %int_0
5504 OpBranch %27
5505 %27 = OpLabel
5506 OpLoopMerge %28 %29 None
5507 OpBranch %30
5508 %30 = OpLabel
5509 %31 = OpLoad %int %c
5510 %32 = OpSLessThan %bool %31 %int_1
5511 OpBranchConditional %32 %33 %28
5512 %33 = OpLabel
5513 OpBranch %34
5514 %34 = OpLabel
5515 OpBranch %35
5516 %35 = OpLabel
5517 OpLoopMerge %36 %37 None
5518 OpBranch %38
5519 %38 = OpLabel
5520 OpStore %i %int_0
5521 OpBranch %39
5522 %39 = OpLabel
5523 OpLoopMerge %40 %41 None
5524 OpBranch %42
5525 %42 = OpLabel
5526 %43 = OpLoad %int %i
5527 %44 = OpSLessThan %bool %43 %int_1
5528 OpBranchConditional %44 %46 %40
5529 %46 = OpLabel
5530 %47 = OpLoad %int %i
5531 %48 = OpAccessChain %_ptr_Function_float %data %47
5532 OpStore %48 %float_1
5533 OpBranch %41
5534 %41 = OpLabel
5535 %49 = OpLoad %int %i
5536 %50 = OpIAdd %int %49 %int_1
5537 OpStore %i %50
5538 OpBranch %39
5539 %40 = OpLabel
5540 OpBranch %37
5541 %37 = OpLabel
5542 OpBranchConditional %false %35 %36
5543 %36 = OpLabel
5544 OpBranch %45
5545 %45 = OpLabel
5546 OpBranch %29
5547 %29 = OpLabel
5548 %51 = OpLoad %int %c
5549 %52 = OpIAdd %int %51 %int_1
5550 OpStore %c %52
5551 OpBranch %27
5552 %28 = OpLabel
5553 %53 = OpAccessChain %_ptr_Function_float %data %int_0
5554 %54 = OpLoad %float %53
5555 %55 = OpCompositeConstruct %v4float %54 %float_0 %float_0 %float_1
5556 OpStore %_GLF_color %55
5557 OpReturn
5558 OpFunctionEnd
5559 )";
5560
5561 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5562 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5563 }
5564
TEST_F(AggressiveDCETest,EliminateLoopWithUnreachable)5565 TEST_F(AggressiveDCETest, EliminateLoopWithUnreachable) {
5566 // #version 430
5567 //
5568 // layout(std430) buffer U_t
5569 // {
5570 // float g_F[10];
5571 // float g_S;
5572 // };
5573 //
5574 // layout(location = 0)out float o;
5575 //
5576 // void main(void)
5577 // {
5578 // // Useless loop
5579 // for (int i = 0; i<10; i++) {
5580 // if (g_F[i] == 0.0)
5581 // break;
5582 // else
5583 // break;
5584 // // Unreachable merge block created here.
5585 // // Need to edit SPIR-V to change to OpUnreachable
5586 // }
5587 // o = g_S;
5588 // }
5589
5590 const std::string before =
5591 R"(OpCapability Shader
5592 %1 = OpExtInstImport "GLSL.std.450"
5593 OpMemoryModel Logical GLSL450
5594 OpEntryPoint Fragment %main "main" %o
5595 OpExecutionMode %main OriginUpperLeft
5596 OpSource GLSL 430
5597 OpName %main "main"
5598 OpName %i "i"
5599 OpName %U_t "U_t"
5600 OpMemberName %U_t 0 "g_F"
5601 OpMemberName %U_t 1 "g_S"
5602 OpName %_ ""
5603 OpName %o "o"
5604 OpDecorate %_arr_float_uint_10 ArrayStride 4
5605 OpMemberDecorate %U_t 0 Offset 0
5606 OpMemberDecorate %U_t 1 Offset 40
5607 OpDecorate %U_t BufferBlock
5608 OpDecorate %_ DescriptorSet 0
5609 OpDecorate %o Location 0
5610 %void = OpTypeVoid
5611 %9 = OpTypeFunction %void
5612 %int = OpTypeInt 32 1
5613 %_ptr_Function_int = OpTypePointer Function %int
5614 %int_0 = OpConstant %int 0
5615 %int_10 = OpConstant %int 10
5616 %bool = OpTypeBool
5617 %float = OpTypeFloat 32
5618 %uint = OpTypeInt 32 0
5619 %uint_10 = OpConstant %uint 10
5620 %_arr_float_uint_10 = OpTypeArray %float %uint_10
5621 %U_t = OpTypeStruct %_arr_float_uint_10 %float
5622 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
5623 %_ = OpVariable %_ptr_Uniform_U_t Uniform
5624 %_ptr_Uniform_float = OpTypePointer Uniform %float
5625 %float_0 = OpConstant %float 0
5626 %int_1 = OpConstant %int 1
5627 %_ptr_Output_float = OpTypePointer Output %float
5628 %o = OpVariable %_ptr_Output_float Output
5629 %main = OpFunction %void None %9
5630 %23 = OpLabel
5631 %i = OpVariable %_ptr_Function_int Function
5632 OpStore %i %int_0
5633 OpBranch %24
5634 %24 = OpLabel
5635 OpLoopMerge %25 %26 None
5636 OpBranch %27
5637 %27 = OpLabel
5638 %28 = OpLoad %int %i
5639 %29 = OpSLessThan %bool %28 %int_10
5640 OpBranchConditional %29 %30 %25
5641 %30 = OpLabel
5642 %31 = OpLoad %int %i
5643 %32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %31
5644 %33 = OpLoad %float %32
5645 %34 = OpFOrdEqual %bool %33 %float_0
5646 OpSelectionMerge %35 None
5647 OpBranchConditional %34 %36 %37
5648 %36 = OpLabel
5649 OpBranch %25
5650 %37 = OpLabel
5651 OpBranch %25
5652 %35 = OpLabel
5653 OpUnreachable
5654 %26 = OpLabel
5655 %38 = OpLoad %int %i
5656 %39 = OpIAdd %int %38 %int_1
5657 OpStore %i %39
5658 OpBranch %24
5659 %25 = OpLabel
5660 %40 = OpAccessChain %_ptr_Uniform_float %_ %int_1
5661 %41 = OpLoad %float %40
5662 OpStore %o %41
5663 OpReturn
5664 OpFunctionEnd
5665 )";
5666
5667 const std::string after =
5668 R"(OpCapability Shader
5669 %1 = OpExtInstImport "GLSL.std.450"
5670 OpMemoryModel Logical GLSL450
5671 OpEntryPoint Fragment %main "main" %o
5672 OpExecutionMode %main OriginUpperLeft
5673 OpSource GLSL 430
5674 OpName %main "main"
5675 OpName %U_t "U_t"
5676 OpMemberName %U_t 0 "g_F"
5677 OpMemberName %U_t 1 "g_S"
5678 OpName %_ ""
5679 OpName %o "o"
5680 OpDecorate %_arr_float_uint_10 ArrayStride 4
5681 OpMemberDecorate %U_t 0 Offset 0
5682 OpMemberDecorate %U_t 1 Offset 40
5683 OpDecorate %U_t BufferBlock
5684 OpDecorate %_ DescriptorSet 0
5685 OpDecorate %o Location 0
5686 %void = OpTypeVoid
5687 %9 = OpTypeFunction %void
5688 %int = OpTypeInt 32 1
5689 %float = OpTypeFloat 32
5690 %uint = OpTypeInt 32 0
5691 %uint_10 = OpConstant %uint 10
5692 %_arr_float_uint_10 = OpTypeArray %float %uint_10
5693 %U_t = OpTypeStruct %_arr_float_uint_10 %float
5694 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
5695 %_ = OpVariable %_ptr_Uniform_U_t Uniform
5696 %_ptr_Uniform_float = OpTypePointer Uniform %float
5697 %int_1 = OpConstant %int 1
5698 %_ptr_Output_float = OpTypePointer Output %float
5699 %o = OpVariable %_ptr_Output_float Output
5700 %main = OpFunction %void None %9
5701 %23 = OpLabel
5702 OpBranch %24
5703 %24 = OpLabel
5704 OpBranch %25
5705 %25 = OpLabel
5706 %40 = OpAccessChain %_ptr_Uniform_float %_ %int_1
5707 %41 = OpLoad %float %40
5708 OpStore %o %41
5709 OpReturn
5710 OpFunctionEnd
5711 )";
5712
5713 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5714 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
5715 }
5716
TEST_F(AggressiveDCETest,DeadHlslCounterBufferGOOGLE)5717 TEST_F(AggressiveDCETest, DeadHlslCounterBufferGOOGLE) {
5718 // We are able to remove "local2" because it is not loaded, but have to keep
5719 // the stores to "local1".
5720 const std::string test =
5721 R"(
5722 ; CHECK-NOT: OpDecorateId
5723 ; CHECK: [[var:%\w+]] = OpVariable
5724 ; CHECK-NOT: OpVariable
5725 ; CHECK: [[ac:%\w+]] = OpAccessChain {{%\w+}} [[var]]
5726 ; CHECK: OpStore [[ac]]
5727 OpCapability Shader
5728 OpExtension "SPV_GOOGLE_hlsl_functionality1"
5729 OpMemoryModel Logical GLSL450
5730 OpEntryPoint GLCompute %1 "main"
5731 OpExecutionMode %1 LocalSize 32 1 1
5732 OpSource HLSL 600
5733 OpDecorate %_runtimearr_v2float ArrayStride 8
5734 OpMemberDecorate %_struct_3 0 Offset 0
5735 OpDecorate %_struct_3 BufferBlock
5736 OpMemberDecorate %_struct_4 0 Offset 0
5737 OpDecorate %_struct_4 BufferBlock
5738 OpDecorateId %5 HlslCounterBufferGOOGLE %6
5739 OpDecorate %5 DescriptorSet 0
5740 OpDecorate %5 Binding 0
5741 OpDecorate %6 DescriptorSet 0
5742 OpDecorate %6 Binding 1
5743 %float = OpTypeFloat 32
5744 %v2float = OpTypeVector %float 2
5745 %_runtimearr_v2float = OpTypeRuntimeArray %v2float
5746 %_struct_3 = OpTypeStruct %_runtimearr_v2float
5747 %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
5748 %int = OpTypeInt 32 1
5749 %_struct_4 = OpTypeStruct %int
5750 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
5751 %void = OpTypeVoid
5752 %13 = OpTypeFunction %void
5753 %19 = OpConstantNull %v2float
5754 %int_0 = OpConstant %int 0
5755 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
5756 %5 = OpVariable %_ptr_Uniform__struct_3 Uniform
5757 %6 = OpVariable %_ptr_Uniform__struct_4 Uniform
5758 %1 = OpFunction %void None %13
5759 %22 = OpLabel
5760 %23 = OpAccessChain %_ptr_Uniform_v2float %5 %int_0 %int_0
5761 OpStore %23 %19
5762 OpReturn
5763 OpFunctionEnd
5764 )";
5765
5766 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5767 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
5768 }
5769
TEST_F(AggressiveDCETest,Dead)5770 TEST_F(AggressiveDCETest, Dead) {
5771 // We are able to remove "local2" because it is not loaded, but have to keep
5772 // the stores to "local1".
5773 const std::string test =
5774 R"(
5775 ; CHECK: OpCapability
5776 ; CHECK-NOT: OpMemberDecorateStringGOOGLE
5777 ; CHECK: OpFunctionEnd
5778 OpCapability Shader
5779 OpExtension "SPV_GOOGLE_hlsl_functionality1"
5780 %1 = OpExtInstImport "GLSL.std.450"
5781 OpMemoryModel Logical GLSL450
5782 OpEntryPoint Vertex %VSMain "VSMain"
5783 OpSource HLSL 500
5784 OpName %VSMain "VSMain"
5785 OpName %PSInput "PSInput"
5786 OpMemberName %PSInput 0 "Pos"
5787 OpMemberName %PSInput 1 "uv"
5788 OpMemberDecorateStringGOOGLE %PSInput 0 HlslSemanticGOOGLE "SV_POSITION"
5789 OpMemberDecorateStringGOOGLE %PSInput 1 HlslSemanticGOOGLE "TEX_COORD"
5790 %void = OpTypeVoid
5791 %5 = OpTypeFunction %void
5792 %float = OpTypeFloat 32
5793 %v2float = OpTypeVector %float 2
5794 %v4float = OpTypeVector %float 4
5795 %PSInput = OpTypeStruct %v4float %v2float
5796 %VSMain = OpFunction %void None %5
5797 %9 = OpLabel
5798 OpReturn
5799 OpFunctionEnd
5800 )";
5801
5802 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5803 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
5804 }
5805
TEST_F(AggressiveDCETest,DeadInfiniteLoop)5806 TEST_F(AggressiveDCETest, DeadInfiniteLoop) {
5807 const std::string test = R"(
5808 ; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]]
5809 ; CHECK: [[block]] = OpLabel
5810 ; CHECK-NEXT: OpBranch [[block:%\w+]]
5811 ; CHECK: [[block]] = OpLabel
5812 ; CHECK-NEXT: OpBranch [[block:%\w+]]
5813 ; CHECK: [[block]] = OpLabel
5814 ; CHECK-NEXT: OpReturn
5815 OpCapability Shader
5816 OpMemoryModel Logical GLSL450
5817 OpEntryPoint Fragment %2 "main"
5818 OpExecutionMode %2 OriginUpperLeft
5819 %6 = OpTypeVoid
5820 %7 = OpTypeFunction %6
5821 %8 = OpTypeFloat 32
5822 %9 = OpTypeVector %8 3
5823 %10 = OpTypeFunction %9
5824 %11 = OpConstant %8 1
5825 %12 = OpConstantComposite %9 %11 %11 %11
5826 %13 = OpTypeInt 32 1
5827 %32 = OpUndef %13
5828 %2 = OpFunction %6 None %7
5829 %33 = OpLabel
5830 OpBranch %34
5831 %34 = OpLabel
5832 OpLoopMerge %35 %36 None
5833 OpBranch %37
5834 %37 = OpLabel
5835 %38 = OpFunctionCall %9 %39
5836 OpSelectionMerge %40 None
5837 OpSwitch %32 %40 14 %41 58 %42
5838 %42 = OpLabel
5839 OpBranch %43
5840 %43 = OpLabel
5841 OpLoopMerge %44 %45 None
5842 OpBranch %45
5843 %45 = OpLabel
5844 OpBranch %43
5845 %44 = OpLabel
5846 OpUnreachable
5847 %41 = OpLabel
5848 OpBranch %36
5849 %40 = OpLabel
5850 OpBranch %36
5851 %36 = OpLabel
5852 OpBranch %34
5853 %35 = OpLabel
5854 OpReturn
5855 OpFunctionEnd
5856 %39 = OpFunction %9 None %10
5857 %46 = OpLabel
5858 OpReturnValue %12
5859 OpFunctionEnd
5860 )";
5861
5862 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5863 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
5864 }
5865
TEST_F(AggressiveDCETest,DeadInfiniteLoopReturnValue)5866 TEST_F(AggressiveDCETest, DeadInfiniteLoopReturnValue) {
5867 const std::string test = R"(
5868 ; CHECK: [[vec3:%\w+]] = OpTypeVector
5869 ; CHECK: [[undef:%\w+]] = OpUndef [[vec3]]
5870 ; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]]
5871 ; CHECK: [[block]] = OpLabel
5872 ; CHECK-NEXT: OpBranch [[block:%\w+]]
5873 ; CHECK: [[block]] = OpLabel
5874 ; CHECK-NEXT: OpBranch [[block:%\w+]]
5875 ; CHECK: [[block]] = OpLabel
5876 ; CHECK-NEXT: OpReturnValue [[undef]]
5877 OpCapability Shader
5878 OpMemoryModel Logical GLSL450
5879 OpEntryPoint Fragment %2 "main"
5880 OpExecutionMode %2 OriginUpperLeft
5881 %6 = OpTypeVoid
5882 %7 = OpTypeFunction %6
5883 %8 = OpTypeFloat 32
5884 %9 = OpTypeVector %8 3
5885 %10 = OpTypeFunction %9
5886 %11 = OpConstant %8 1
5887 %12 = OpConstantComposite %9 %11 %11 %11
5888 %13 = OpTypeInt 32 1
5889 %32 = OpUndef %13
5890 %2 = OpFunction %6 None %7
5891 %entry = OpLabel
5892 %call = OpFunctionCall %9 %func
5893 OpReturn
5894 OpFunctionEnd
5895 %func = OpFunction %9 None %10
5896 %33 = OpLabel
5897 OpBranch %34
5898 %34 = OpLabel
5899 OpLoopMerge %35 %36 None
5900 OpBranch %37
5901 %37 = OpLabel
5902 %38 = OpFunctionCall %9 %39
5903 OpSelectionMerge %40 None
5904 OpSwitch %32 %40 14 %41 58 %42
5905 %42 = OpLabel
5906 OpBranch %43
5907 %43 = OpLabel
5908 OpLoopMerge %44 %45 None
5909 OpBranch %45
5910 %45 = OpLabel
5911 OpBranch %43
5912 %44 = OpLabel
5913 OpUnreachable
5914 %41 = OpLabel
5915 OpBranch %36
5916 %40 = OpLabel
5917 OpBranch %36
5918 %36 = OpLabel
5919 OpBranch %34
5920 %35 = OpLabel
5921 OpReturnValue %12
5922 OpFunctionEnd
5923 %39 = OpFunction %9 None %10
5924 %46 = OpLabel
5925 OpReturnValue %12
5926 OpFunctionEnd
5927 )";
5928
5929 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5930 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
5931 }
5932
TEST_F(AggressiveDCETest,TestVariablePointer)5933 TEST_F(AggressiveDCETest, TestVariablePointer) {
5934 const std::string before =
5935 R"(OpCapability Shader
5936 OpCapability VariablePointers
5937 %1 = OpExtInstImport "GLSL.std.450"
5938 OpMemoryModel Logical GLSL450
5939 OpEntryPoint GLCompute %2 "main"
5940 OpExecutionMode %2 LocalSize 1 1 1
5941 OpSource GLSL 450
5942 OpMemberDecorate %_struct_3 0 Offset 0
5943 OpDecorate %_struct_3 Block
5944 OpDecorate %4 DescriptorSet 0
5945 OpDecorate %4 Binding 0
5946 OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
5947 OpDecorate %_arr_int_int_128 ArrayStride 4
5948 %void = OpTypeVoid
5949 %8 = OpTypeFunction %void
5950 %int = OpTypeInt 32 1
5951 %int_128 = OpConstant %int 128
5952 %_arr_int_int_128 = OpTypeArray %int %int_128
5953 %_struct_3 = OpTypeStruct %_arr_int_int_128
5954 %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
5955 %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
5956 %bool = OpTypeBool
5957 %true = OpConstantTrue %bool
5958 %int_0 = OpConstant %int 0
5959 %int_1 = OpConstant %int 1
5960 %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
5961 %2 = OpFunction %void None %8
5962 %16 = OpLabel
5963 %17 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
5964 OpBranch %18
5965 %18 = OpLabel
5966 %19 = OpPhi %_ptr_StorageBuffer_int %17 %16 %20 %21
5967 OpLoopMerge %22 %21 None
5968 OpBranchConditional %true %23 %22
5969 %23 = OpLabel
5970 OpStore %19 %int_0
5971 OpBranch %21
5972 %21 = OpLabel
5973 %20 = OpPtrAccessChain %_ptr_StorageBuffer_int %19 %int_1
5974 OpBranch %18
5975 %22 = OpLabel
5976 OpReturn
5977 OpFunctionEnd
5978 )";
5979
5980 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5981 SinglePassRunAndCheck<AggressiveDCEPass>(before, before, true, true);
5982 }
5983
TEST_F(AggressiveDCETest,DeadInputInterfaceV13)5984 TEST_F(AggressiveDCETest, DeadInputInterfaceV13) {
5985 const std::string spirv = R"(
5986 ; CHECK: OpEntryPoint GLCompute %main "main"
5987 ; CHECK-NOT: OpVariable
5988 OpCapability Shader
5989 OpMemoryModel Logical GLSL450
5990 OpEntryPoint GLCompute %main "main" %dead
5991 OpExecutionMode %main LocalSize 1 1 1
5992 OpName %main "main"
5993 %void = OpTypeVoid
5994 %int = OpTypeInt 32 0
5995 %ptr_input_int = OpTypePointer Input %int
5996 %dead = OpVariable %ptr_input_int Input
5997 %void_fn = OpTypeFunction %void
5998 %main = OpFunction %void None %void_fn
5999 %entry = OpLabel
6000 OpReturn
6001 OpFunctionEnd
6002 )";
6003
6004 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3);
6005 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6006 }
6007
TEST_F(AggressiveDCETest,DeadInputInterfaceV14)6008 TEST_F(AggressiveDCETest, DeadInputInterfaceV14) {
6009 const std::string spirv = R"(
6010 ; CHECK: OpEntryPoint GLCompute %main "main"
6011 ; CHECK-NOT: OpVariable
6012 OpCapability Shader
6013 OpMemoryModel Logical GLSL450
6014 OpEntryPoint GLCompute %main "main" %dead
6015 OpExecutionMode %main LocalSize 1 1 1
6016 OpName %main "main"
6017 %void = OpTypeVoid
6018 %int = OpTypeInt 32 0
6019 %ptr_input_int = OpTypePointer Input %int
6020 %dead = OpVariable %ptr_input_int Input
6021 %void_fn = OpTypeFunction %void
6022 %main = OpFunction %void None %void_fn
6023 %entry = OpLabel
6024 OpReturn
6025 OpFunctionEnd
6026 )";
6027
6028 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6029 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6030 }
6031
TEST_F(AggressiveDCETest,DeadInterfaceV14)6032 TEST_F(AggressiveDCETest, DeadInterfaceV14) {
6033 const std::string spirv = R"(
6034 ; CHECK-NOT: OpEntryPoint GLCompute %main "main" %
6035 ; CHECK: OpEntryPoint GLCompute %main "main"
6036 ; CHECK-NOT: OpVariable
6037 OpCapability Shader
6038 OpMemoryModel Logical GLSL450
6039 OpEntryPoint GLCompute %main "main" %dead
6040 OpExecutionMode %main LocalSize 1 1 1
6041 OpName %main "main"
6042 %void = OpTypeVoid
6043 %int = OpTypeInt 32 0
6044 %ptr_private_int = OpTypePointer Private %int
6045 %dead = OpVariable %ptr_private_int Private
6046 %void_fn = OpTypeFunction %void
6047 %main = OpFunction %void None %void_fn
6048 %entry = OpLabel
6049 OpReturn
6050 OpFunctionEnd
6051 )";
6052
6053 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6054 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6055 }
6056
TEST_F(AggressiveDCETest,DeadInterfacesV14)6057 TEST_F(AggressiveDCETest, DeadInterfacesV14) {
6058 const std::string spirv = R"(
6059 ; CHECK: OpEntryPoint GLCompute %main "main" %live1 %live2
6060 ; CHECK-NOT: %dead
6061 OpCapability Shader
6062 OpMemoryModel Logical GLSL450
6063 OpEntryPoint GLCompute %main "main" %live1 %dead1 %dead2 %live2
6064 OpExecutionMode %main LocalSize 1 1 1
6065 OpName %main "main"
6066 OpName %live1 "live1"
6067 OpName %live2 "live2"
6068 OpName %dead1 "dead1"
6069 OpName %dead2 "dead2"
6070 %void = OpTypeVoid
6071 %int = OpTypeInt 32 0
6072 %int0 = OpConstant %int 0
6073 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
6074 %live1 = OpVariable %ptr_ssbo_int StorageBuffer
6075 %live2 = OpVariable %ptr_ssbo_int StorageBuffer
6076 %dead1 = OpVariable %ptr_ssbo_int StorageBuffer
6077 %dead2 = OpVariable %ptr_ssbo_int StorageBuffer
6078 %void_fn = OpTypeFunction %void
6079 %main = OpFunction %void None %void_fn
6080 %entry = OpLabel
6081 OpStore %live1 %int0
6082 OpStore %live2 %int0
6083 OpReturn
6084 OpFunctionEnd
6085 )";
6086
6087 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6088 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6089 }
6090
TEST_F(AggressiveDCETest,PreserveBindings)6091 TEST_F(AggressiveDCETest, PreserveBindings) {
6092 const std::string spirv = R"(
6093 ; CHECK: OpDecorate %unusedSampler DescriptorSet 0
6094 ; CHECK: OpDecorate %unusedSampler Binding 0
6095 OpCapability Shader
6096 %1 = OpExtInstImport "GLSL.std.450"
6097 OpMemoryModel Logical GLSL450
6098 OpEntryPoint Fragment %main "main"
6099 OpExecutionMode %main OriginUpperLeft
6100 OpSource GLSL 430
6101 OpName %main "main"
6102 OpName %unusedSampler "unusedSampler"
6103 OpDecorate %unusedSampler DescriptorSet 0
6104 OpDecorate %unusedSampler Binding 0
6105 %void = OpTypeVoid
6106 %5 = OpTypeFunction %void
6107 %float = OpTypeFloat 32
6108 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
6109 %8 = OpTypeSampledImage %7
6110 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
6111 %unusedSampler = OpVariable %_ptr_UniformConstant_8 UniformConstant
6112 %main = OpFunction %void None %5
6113 %10 = OpLabel
6114 OpReturn
6115 OpFunctionEnd
6116 )";
6117
6118 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6119
6120 OptimizerOptions()->preserve_bindings_ = true;
6121
6122 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6123 }
6124
TEST_F(AggressiveDCETest,PreserveSpecConstants)6125 TEST_F(AggressiveDCETest, PreserveSpecConstants) {
6126 const std::string spirv = R"(
6127 ; CHECK: OpName %specConstant "specConstant"
6128 ; CHECK: %specConstant = OpSpecConstant %int 0
6129 OpCapability Shader
6130 %1 = OpExtInstImport "GLSL.std.450"
6131 OpMemoryModel Logical GLSL450
6132 OpEntryPoint Fragment %main "main"
6133 OpExecutionMode %main OriginUpperLeft
6134 OpSource GLSL 430
6135 OpName %main "main"
6136 OpName %specConstant "specConstant"
6137 OpDecorate %specConstant SpecId 0
6138 %void = OpTypeVoid
6139 %3 = OpTypeFunction %void
6140 %int = OpTypeInt 32 1
6141 %specConstant = OpSpecConstant %int 0
6142 %main = OpFunction %void None %3
6143 %5 = OpLabel
6144 OpReturn
6145 OpFunctionEnd
6146 )";
6147
6148 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6149
6150 OptimizerOptions()->preserve_spec_constants_ = true;
6151
6152 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6153 }
6154
TEST_F(AggressiveDCETest,LiveDecorateId)6155 TEST_F(AggressiveDCETest, LiveDecorateId) {
6156 const std::string spirv = R"(OpCapability Shader
6157 OpMemoryModel Logical GLSL450
6158 OpEntryPoint GLCompute %1 "main" %2
6159 OpExecutionMode %1 LocalSize 8 1 1
6160 OpDecorate %2 DescriptorSet 0
6161 OpDecorate %2 Binding 0
6162 OpDecorateId %3 UniformId %uint_2
6163 %void = OpTypeVoid
6164 %uint = OpTypeInt 32 0
6165 %uint_2 = OpConstant %uint 2
6166 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
6167 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
6168 %8 = OpTypeFunction %void
6169 %1 = OpFunction %void None %8
6170 %9 = OpLabel
6171 %3 = OpLoad %uint %2
6172 OpStore %2 %3
6173 OpReturn
6174 OpFunctionEnd
6175 )";
6176
6177 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6178 OptimizerOptions()->preserve_spec_constants_ = true;
6179 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
6180 }
6181
TEST_F(AggressiveDCETest,LiveDecorateIdOnGroup)6182 TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) {
6183 const std::string spirv = R"(OpCapability Shader
6184 OpMemoryModel Logical GLSL450
6185 OpEntryPoint GLCompute %1 "main" %2
6186 OpExecutionMode %1 LocalSize 8 1 1
6187 OpDecorate %2 DescriptorSet 0
6188 OpDecorate %2 Binding 0
6189 OpDecorateId %3 UniformId %uint_2
6190 %3 = OpDecorationGroup
6191 OpGroupDecorate %3 %5
6192 %void = OpTypeVoid
6193 %uint = OpTypeInt 32 0
6194 %uint_2 = OpConstant %uint 2
6195 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
6196 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
6197 %9 = OpTypeFunction %void
6198 %1 = OpFunction %void None %9
6199 %10 = OpLabel
6200 %5 = OpLoad %uint %2
6201 OpStore %2 %5
6202 OpReturn
6203 OpFunctionEnd
6204 )";
6205
6206 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6207 OptimizerOptions()->preserve_spec_constants_ = true;
6208 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
6209 }
6210
TEST_F(AggressiveDCETest,NoEliminateForwardPointer)6211 TEST_F(AggressiveDCETest, NoEliminateForwardPointer) {
6212 // clang-format off
6213 //
6214 // #version 450
6215 // #extension GL_EXT_buffer_reference : enable
6216 //
6217 // // forward reference
6218 // layout(buffer_reference) buffer blockType;
6219 //
6220 // layout(buffer_reference, std430, buffer_reference_align = 16) buffer blockType {
6221 // int x;
6222 // blockType next;
6223 // };
6224 //
6225 // layout(std430) buffer rootBlock {
6226 // blockType root;
6227 // } r;
6228 //
6229 // void main()
6230 // {
6231 // blockType b = r.root;
6232 // b = b.next;
6233 // b.x = 531;
6234 // }
6235 //
6236 // clang-format on
6237
6238 const std::string predefs1 =
6239 R"(OpCapability Shader
6240 OpCapability PhysicalStorageBufferAddresses
6241 OpExtension "SPV_EXT_physical_storage_buffer"
6242 OpExtension "SPV_KHR_storage_buffer_storage_class"
6243 %1 = OpExtInstImport "GLSL.std.450"
6244 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6245 OpEntryPoint GLCompute %main "main"
6246 OpExecutionMode %main LocalSize 1 1 1
6247 OpSource GLSL 450
6248 OpSourceExtension "GL_EXT_buffer_reference"
6249 )";
6250
6251 const std::string names_before =
6252 R"(OpName %main "main"
6253 OpName %blockType "blockType"
6254 OpMemberName %blockType 0 "x"
6255 OpMemberName %blockType 1 "next"
6256 OpName %b "b"
6257 OpName %rootBlock "rootBlock"
6258 OpMemberName %rootBlock 0 "root"
6259 OpName %r "r"
6260 OpMemberDecorate %blockType 0 Offset 0
6261 OpMemberDecorate %blockType 1 Offset 8
6262 OpDecorate %blockType Block
6263 OpDecorate %b AliasedPointer
6264 OpMemberDecorate %rootBlock 0 Offset 0
6265 OpDecorate %rootBlock Block
6266 OpDecorate %r DescriptorSet 0
6267 OpDecorate %r Binding 0
6268 )";
6269
6270 const std::string names_after =
6271 R"(OpName %main "main"
6272 OpName %blockType "blockType"
6273 OpMemberName %blockType 0 "x"
6274 OpMemberName %blockType 1 "next"
6275 OpName %rootBlock "rootBlock"
6276 OpMemberName %rootBlock 0 "root"
6277 OpName %r "r"
6278 OpMemberDecorate %blockType 0 Offset 0
6279 OpMemberDecorate %blockType 1 Offset 8
6280 OpDecorate %blockType Block
6281 OpMemberDecorate %rootBlock 0 Offset 0
6282 OpDecorate %rootBlock Block
6283 OpDecorate %r DescriptorSet 0
6284 OpDecorate %r Binding 0
6285 )";
6286
6287 const std::string predefs2_before =
6288 R"(%void = OpTypeVoid
6289 %3 = OpTypeFunction %void
6290 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
6291 %int = OpTypeInt 32 1
6292 %blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType
6293 %_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType
6294 %_ptr_Function__ptr_PhysicalStorageBuffer_blockType = OpTypePointer Function %_ptr_PhysicalStorageBuffer_blockType
6295 %rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType
6296 %_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock
6297 %r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer
6298 %int_0 = OpConstant %int 0
6299 %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6300 %int_1 = OpConstant %int 1
6301 %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6302 %int_531 = OpConstant %int 531
6303 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
6304 )";
6305
6306 const std::string predefs2_after =
6307 R"(%void = OpTypeVoid
6308 %8 = OpTypeFunction %void
6309 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
6310 %int = OpTypeInt 32 1
6311 %blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType
6312 %_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType
6313 %rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType
6314 %_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock
6315 %r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer
6316 %int_0 = OpConstant %int 0
6317 %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6318 %int_1 = OpConstant %int 1
6319 %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6320 %int_531 = OpConstant %int 531
6321 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
6322 )";
6323
6324 const std::string func_before =
6325 R"(%main = OpFunction %void None %3
6326 %5 = OpLabel
6327 %b = OpVariable %_ptr_Function__ptr_PhysicalStorageBuffer_blockType Function
6328 %16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
6329 %17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16
6330 %21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1
6331 %22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
6332 OpStore %b %22
6333 %26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0
6334 OpStore %26 %int_531 Aligned 16
6335 OpReturn
6336 OpFunctionEnd
6337 )";
6338
6339 const std::string func_after =
6340 R"(%main = OpFunction %void None %8
6341 %19 = OpLabel
6342 %20 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
6343 %21 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %20
6344 %22 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %21 %int_1
6345 %23 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %22 Aligned 8
6346 %24 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %23 %int_0
6347 OpStore %24 %int_531 Aligned 16
6348 OpReturn
6349 OpFunctionEnd
6350 )";
6351
6352 SinglePassRunAndCheck<AggressiveDCEPass>(
6353 predefs1 + names_before + predefs2_before + func_before,
6354 predefs1 + names_after + predefs2_after + func_after, true, true);
6355 }
6356
TEST_F(AggressiveDCETest,MultipleFunctionProcessIndependently)6357 TEST_F(AggressiveDCETest, MultipleFunctionProcessIndependently) {
6358 const std::string spirv = R"(
6359 OpCapability Shader
6360 OpMemoryModel Logical GLSL450
6361 OpEntryPoint GLCompute %entryHistogram "entryHistogram" %gl_GlobalInvocationID %gl_LocalInvocationIndex
6362 OpEntryPoint GLCompute %entryAverage "entryAverage" %gl_GlobalInvocationID %gl_LocalInvocationIndex
6363 OpExecutionMode %entryHistogram LocalSize 16 16 1
6364 OpExecutionMode %entryAverage LocalSize 256 1 1
6365 OpSource HLSL 640
6366 OpName %type_RWStructuredBuffer_uint "type.RWStructuredBuffer.uint"
6367 OpName %uHistogram "uHistogram"
6368 OpName %type_ACSBuffer_counter "type.ACSBuffer.counter"
6369 OpMemberName %type_ACSBuffer_counter 0 "counter"
6370 OpName %counter_var_uHistogram "counter.var.uHistogram"
6371 OpName %sharedHistogram "sharedHistogram"
6372 OpName %entryHistogram "entryHistogram"
6373 OpName %param_var_id "param.var.id"
6374 OpName %param_var_idx "param.var.idx"
6375 OpName %entryAverage "entryAverage"
6376 OpName %param_var_id_0 "param.var.id"
6377 OpName %param_var_idx_0 "param.var.idx"
6378 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
6379 OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
6380 OpDecorate %uHistogram DescriptorSet 0
6381 OpDecorate %uHistogram Binding 0
6382 OpDecorate %counter_var_uHistogram DescriptorSet 0
6383 OpDecorate %counter_var_uHistogram Binding 1
6384 OpDecorate %_runtimearr_uint ArrayStride 4
6385 OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0
6386 OpDecorate %type_RWStructuredBuffer_uint BufferBlock
6387 OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0
6388 OpDecorate %type_ACSBuffer_counter BufferBlock
6389 %uint = OpTypeInt 32 0
6390 %uint_0 = OpConstant %uint 0
6391 %uint_1 = OpConstant %uint 1
6392 %uint_2 = OpConstant %uint 2
6393 %uint_4 = OpConstant %uint 4
6394 %uint_8 = OpConstant %uint 8
6395 %uint_16 = OpConstant %uint 16
6396 %uint_32 = OpConstant %uint 32
6397 %uint_64 = OpConstant %uint 64
6398 %uint_128 = OpConstant %uint 128
6399 %uint_256 = OpConstant %uint 256
6400 %uint_512 = OpConstant %uint 512
6401 %uint_254 = OpConstant %uint 254
6402 %uint_255 = OpConstant %uint 255
6403 %int = OpTypeInt 32 1
6404 %int_0 = OpConstant %int 0
6405 %_runtimearr_uint = OpTypeRuntimeArray %uint
6406 %type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint
6407 %_ptr_Uniform_type_RWStructuredBuffer_uint = OpTypePointer Uniform %type_RWStructuredBuffer_uint
6408 %type_ACSBuffer_counter = OpTypeStruct %int
6409 %_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter
6410 %_arr_uint_uint_256 = OpTypeArray %uint %uint_256
6411 %_ptr_Workgroup__arr_uint_uint_256 = OpTypePointer Workgroup %_arr_uint_uint_256
6412 %v3uint = OpTypeVector %uint 3
6413 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
6414 %_ptr_Input_uint = OpTypePointer Input %uint
6415 %void = OpTypeVoid
6416 %49 = OpTypeFunction %void
6417 %_ptr_Function_v3uint = OpTypePointer Function %v3uint
6418 %_ptr_Function_uint = OpTypePointer Function %uint
6419 %52 = OpTypeFunction %void %_ptr_Function_v3uint %_ptr_Function_uint
6420 %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
6421 %uint_264 = OpConstant %uint 264
6422 %bool = OpTypeBool
6423 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
6424 %uHistogram = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
6425 %counter_var_uHistogram = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
6426 %sharedHistogram = OpVariable %_ptr_Workgroup__arr_uint_uint_256 Workgroup
6427 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
6428 %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
6429 %entryHistogram = OpFunction %void None %49
6430 %57 = OpLabel
6431 %param_var_id = OpVariable %_ptr_Function_v3uint Function
6432 %param_var_idx = OpVariable %_ptr_Function_uint Function
6433 %58 = OpLoad %v3uint %gl_GlobalInvocationID
6434 %59 = OpLoad %uint %gl_LocalInvocationIndex
6435 %79 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %int_0
6436 %80 = OpAtomicIAdd %uint %79 %uint_1 %uint_0 %uint_1
6437 OpReturn
6438 OpFunctionEnd
6439 %entryAverage = OpFunction %void None %49
6440 %63 = OpLabel
6441 %param_var_id_0 = OpVariable %_ptr_Function_v3uint Function
6442 %param_var_idx_0 = OpVariable %_ptr_Function_uint Function
6443 %64 = OpLoad %v3uint %gl_GlobalInvocationID
6444 %65 = OpLoad %uint %gl_LocalInvocationIndex
6445 OpStore %param_var_idx_0 %65
6446 %83 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6447 OpStore %83 %uint_0
6448
6449 ; CHECK: [[ieq:%\w+]] = OpIEqual
6450 ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
6451 ; CHECK-NEXT: OpBranchConditional [[ieq]] [[not_elim:%\w+]] [[merge]]
6452 ; CHECK-NEXT: [[not_elim]] = OpLabel
6453 ; CHECK: [[merge]] = OpLabel
6454
6455 OpControlBarrier %uint_2 %uint_2 %uint_264
6456 %85 = OpIEqual %bool %65 %uint_0
6457 OpSelectionMerge %89 None
6458 OpBranchConditional %85 %86 %89
6459 %86 = OpLabel
6460 %88 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6461 OpStore %88 %uint_1
6462 OpBranch %89
6463 %89 = OpLabel
6464 OpControlBarrier %uint_2 %uint_2 %uint_264
6465 %91 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6466 %92 = OpLoad %uint %91
6467 %94 = OpAccessChain %_ptr_Uniform_uint %uHistogram %int_0 %65
6468 OpStore %94 %92
6469 OpReturn
6470 OpFunctionEnd
6471 )";
6472
6473 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3);
6474
6475 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6476 }
6477
TEST_F(AggressiveDCETest,DebugInfoKeepInFunctionElimStoreVar)6478 TEST_F(AggressiveDCETest, DebugInfoKeepInFunctionElimStoreVar) {
6479 // Verify that dead local variable tc and store eliminated but all
6480 // in-function debuginfo kept.
6481 //
6482 // The SPIR-V has been inlined and local single store eliminated
6483 //
6484 // Texture2D g_tColor;
6485 // SamplerState g_sAniso;
6486 //
6487 // struct PS_INPUT {
6488 // float2 vTextureCoords : TEXCOORD2;
6489 // };
6490 //
6491 // struct PS_OUTPUT {
6492 // float4 vColor : SV_Target0;
6493 // };
6494 //
6495 // PS_OUTPUT MainPs(PS_INPUT i) {
6496 // PS_OUTPUT ps_output;
6497 // float2 tc = i.vTextureCoords.xy;
6498 // ps_output.vColor = g_tColor.Sample(g_sAniso, tc);
6499 // return ps_output;
6500 // }
6501
6502 const std::string text = R"(
6503 OpCapability Shader
6504 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
6505 OpMemoryModel Logical GLSL450
6506 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
6507 OpExecutionMode %MainPs OriginUpperLeft
6508 %7 = OpString "foo.frag"
6509 %8 = OpString "PS_OUTPUT"
6510 %9 = OpString "float"
6511 %10 = OpString "vColor"
6512 %11 = OpString "PS_INPUT"
6513 %12 = OpString "vTextureCoords"
6514 %13 = OpString "@type.2d.image"
6515 %14 = OpString "type.2d.image"
6516 %15 = OpString "Texture2D.TemplateParam"
6517 %16 = OpString "src.MainPs"
6518 %17 = OpString "tc"
6519 %18 = OpString "ps_output"
6520 %19 = OpString "i"
6521 %20 = OpString "@type.sampler"
6522 %21 = OpString "type.sampler"
6523 %22 = OpString "g_sAniso"
6524 %23 = OpString "g_tColor"
6525 OpName %type_2d_image "type.2d.image"
6526 OpName %g_tColor "g_tColor"
6527 OpName %type_sampler "type.sampler"
6528 OpName %g_sAniso "g_sAniso"
6529 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
6530 OpName %out_var_SV_Target0 "out.var.SV_Target0"
6531 OpName %MainPs "MainPs"
6532 OpName %PS_INPUT "PS_INPUT"
6533 OpMemberName %PS_INPUT 0 "vTextureCoords"
6534 OpName %param_var_i "param.var.i"
6535 OpName %PS_OUTPUT "PS_OUTPUT"
6536 OpMemberName %PS_OUTPUT 0 "vColor"
6537 OpName %type_sampled_image "type.sampled.image"
6538 OpDecorate %in_var_TEXCOORD2 Location 0
6539 OpDecorate %out_var_SV_Target0 Location 0
6540 OpDecorate %g_tColor DescriptorSet 0
6541 OpDecorate %g_tColor Binding 0
6542 OpDecorate %g_sAniso DescriptorSet 0
6543 OpDecorate %g_sAniso Binding 1
6544 %int = OpTypeInt 32 1
6545 %int_0 = OpConstant %int 0
6546 %uint = OpTypeInt 32 0
6547 %uint_32 = OpConstant %uint 32
6548 %float = OpTypeFloat 32
6549 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
6550 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
6551 %type_sampler = OpTypeSampler
6552 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
6553 %v2float = OpTypeVector %float 2
6554 %_ptr_Input_v2float = OpTypePointer Input %v2float
6555 %v4float = OpTypeVector %float 4
6556 %_ptr_Output_v4float = OpTypePointer Output %v4float
6557 %void = OpTypeVoid
6558 %uint_128 = OpConstant %uint 128
6559 %uint_0 = OpConstant %uint 0
6560 %uint_64 = OpConstant %uint 64
6561 %45 = OpTypeFunction %void
6562 %PS_INPUT = OpTypeStruct %v2float
6563 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
6564 %PS_OUTPUT = OpTypeStruct %v4float
6565 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
6566 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
6567 %_ptr_Function_v2float = OpTypePointer Function %v2float
6568 %type_sampled_image = OpTypeSampledImage %type_2d_image
6569 %_ptr_Function_v4float = OpTypePointer Function %v4float
6570 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
6571 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
6572 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
6573 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
6574 %51 = OpExtInst %void %1 DebugInfoNone
6575 %52 = OpExtInst %void %1 DebugExpression
6576 %53 = OpExtInst %void %1 DebugOperation Deref
6577 %54 = OpExtInst %void %1 DebugExpression %53
6578 %55 = OpExtInst %void %1 DebugSource %7
6579 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL
6580 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58
6581 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float
6582 %60 = OpExtInst %void %1 DebugTypeVector %59 4
6583 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
6584 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62
6585 %63 = OpExtInst %void %1 DebugTypeVector %59 2
6586 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
6587 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate
6588 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0
6589 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65
6590 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61
6591 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51
6592 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68
6593 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal
6594 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal
6595 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1
6596 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate
6597 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition
6598 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition
6599 %MainPs = OpFunction %void None %45
6600 %76 = OpLabel
6601 %107 = OpExtInst %void %1 DebugScope %69
6602 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69
6603 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
6604 %79 = OpVariable %_ptr_Function_v2float Function
6605 %108 = OpExtInst %void %1 DebugNoScope
6606 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope
6607 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
6608 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
6609 %82 = OpLoad %v2float %in_var_TEXCOORD2
6610 %83 = OpCompositeConstruct %PS_INPUT %82
6611 OpStore %param_var_i %83
6612 %109 = OpExtInst %void %1 DebugScope %68
6613 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
6614 %110 = OpExtInst %void %1 DebugScope %69
6615 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
6616 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %68
6617 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
6618 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69
6619 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %71 %78 %52
6620 OpLine %7 19 17
6621 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
6622 %89 = OpLoad %v2float %88
6623 OpLine %7 19 12
6624 OpStore %79 %89
6625 ;CHECK-NOT: OpStore %79 %89
6626 OpLine %7 19 12
6627 %106 = OpExtInst %void %1 DebugValue %70 %89 %52
6628 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugValue %70 %89 %52
6629 OpLine %7 20 26
6630 %91 = OpLoad %type_2d_image %g_tColor
6631 OpLine %7 20 46
6632 %92 = OpLoad %type_sampler %g_sAniso
6633 OpLine %7 20 26
6634 %94 = OpSampledImage %type_sampled_image %91 %92
6635 %95 = OpImageSampleImplicitLod %v4float %94 %89 None
6636 OpLine %7 20 5
6637 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
6638 OpStore %96 %95
6639 OpLine %7 21 12
6640 %97 = OpLoad %PS_OUTPUT %78
6641 OpLine %7 21 5
6642 OpStore %81 %97
6643 %111 = OpExtInst %void %1 DebugNoScope
6644 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope
6645 %100 = OpCompositeExtract %v4float %97 0
6646 OpStore %out_var_SV_Target0 %100
6647 OpReturn
6648 OpFunctionEnd
6649 )";
6650
6651 SetTargetEnv(SPV_ENV_VULKAN_1_2);
6652 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6653 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
6654 }
6655
TEST_F(AggressiveDCETest,ShaderDebugInfoKeepInFunctionElimStoreVar)6656 TEST_F(AggressiveDCETest, ShaderDebugInfoKeepInFunctionElimStoreVar) {
6657 // Verify that dead local variable tc and store eliminated but all
6658 // in-function NonSemantic Shader debuginfo kept.
6659
6660 const std::string text = R"(
6661 OpCapability Shader
6662 OpExtension "SPV_KHR_non_semantic_info"
6663 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
6664 OpMemoryModel Logical GLSL450
6665 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
6666 OpExecutionMode %MainPs OriginUpperLeft
6667 %7 = OpString "foo.frag"
6668 %8 = OpString "PS_OUTPUT"
6669 %9 = OpString "float"
6670 %10 = OpString "vColor"
6671 %11 = OpString "PS_INPUT"
6672 %12 = OpString "vTextureCoords"
6673 %13 = OpString "@type.2d.image"
6674 %14 = OpString "type.2d.image"
6675 %15 = OpString "Texture2D.TemplateParam"
6676 %16 = OpString "src.MainPs"
6677 %17 = OpString "tc"
6678 %18 = OpString "ps_output"
6679 %19 = OpString "i"
6680 %20 = OpString "@type.sampler"
6681 %21 = OpString "type.sampler"
6682 %22 = OpString "g_sAniso"
6683 %23 = OpString "g_tColor"
6684 OpName %type_2d_image "type.2d.image"
6685 OpName %g_tColor "g_tColor"
6686 OpName %type_sampler "type.sampler"
6687 OpName %g_sAniso "g_sAniso"
6688 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
6689 OpName %out_var_SV_Target0 "out.var.SV_Target0"
6690 OpName %MainPs "MainPs"
6691 OpName %PS_INPUT "PS_INPUT"
6692 OpMemberName %PS_INPUT 0 "vTextureCoords"
6693 OpName %param_var_i "param.var.i"
6694 OpName %PS_OUTPUT "PS_OUTPUT"
6695 OpMemberName %PS_OUTPUT 0 "vColor"
6696 OpName %type_sampled_image "type.sampled.image"
6697 OpDecorate %in_var_TEXCOORD2 Location 0
6698 OpDecorate %out_var_SV_Target0 Location 0
6699 OpDecorate %g_tColor DescriptorSet 0
6700 OpDecorate %g_tColor Binding 0
6701 OpDecorate %g_sAniso DescriptorSet 0
6702 OpDecorate %g_sAniso Binding 1
6703 %int = OpTypeInt 32 1
6704 %int_0 = OpConstant %int 0
6705 %uint = OpTypeInt 32 0
6706 %uint_32 = OpConstant %uint 32
6707 %float = OpTypeFloat 32
6708 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
6709 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
6710 %type_sampler = OpTypeSampler
6711 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
6712 %v2float = OpTypeVector %float 2
6713 %_ptr_Input_v2float = OpTypePointer Input %v2float
6714 %v4float = OpTypeVector %float 4
6715 %_ptr_Output_v4float = OpTypePointer Output %v4float
6716 %void = OpTypeVoid
6717 %uint_128 = OpConstant %uint 128
6718 %uint_0 = OpConstant %uint 0
6719 %uint_1 = OpConstant %uint 1
6720 %uint_2 = OpConstant %uint 2
6721 %uint_3 = OpConstant %uint 3
6722 %uint_4 = OpConstant %uint 4
6723 %uint_5 = OpConstant %uint 5
6724 %uint_7 = OpConstant %uint 7
6725 %uint_8 = OpConstant %uint 8
6726 %uint_10 = OpConstant %uint 10
6727 %uint_11 = OpConstant %uint 11
6728 %uint_12 = OpConstant %uint 12
6729 %uint_14 = OpConstant %uint 14
6730 %uint_15 = OpConstant %uint 15
6731 %uint_16 = OpConstant %uint 16
6732 %uint_17 = OpConstant %uint 17
6733 %uint_19 = OpConstant %uint 19
6734 %uint_20 = OpConstant %uint 20
6735 %uint_21 = OpConstant %uint 21
6736 %uint_25 = OpConstant %uint 25
6737 %uint_29 = OpConstant %uint 29
6738 %uint_30 = OpConstant %uint 30
6739 %uint_35 = OpConstant %uint 35
6740 %uint_41 = OpConstant %uint 41
6741 %uint_48 = OpConstant %uint 48
6742 %uint_53 = OpConstant %uint 53
6743 %uint_64 = OpConstant %uint 64
6744 %45 = OpTypeFunction %void
6745 %PS_INPUT = OpTypeStruct %v2float
6746 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
6747 %PS_OUTPUT = OpTypeStruct %v4float
6748 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
6749 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
6750 %_ptr_Function_v2float = OpTypePointer Function %v2float
6751 %type_sampled_image = OpTypeSampledImage %type_2d_image
6752 %_ptr_Function_v4float = OpTypePointer Function %v4float
6753 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
6754 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
6755 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
6756 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
6757 %51 = OpExtInst %void %1 DebugInfoNone
6758 %52 = OpExtInst %void %1 DebugExpression
6759 %53 = OpExtInst %void %1 DebugOperation %uint_0
6760 %54 = OpExtInst %void %1 DebugExpression %53
6761 %55 = OpExtInst %void %1 DebugSource %7
6762 %56 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %55 %uint_5
6763 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 %uint_3 %uint_0
6764 %60 = OpExtInst %void %1 DebugTypeVector %59 %uint_4
6765 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 %uint_12 %uint_5 %uint_0 %uint_128 %uint_3
6766 %57 = OpExtInst %void %1 DebugTypeComposite %8 %uint_1 %55 %uint_10 %uint_1 %56 %8 %uint_128 %uint_3 %58
6767 %63 = OpExtInst %void %1 DebugTypeVector %59 %uint_2
6768 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 %uint_7 %uint_5 %uint_0 %uint_64 %uint_3
6769 %61 = OpExtInst %void %1 DebugTypeComposite %11 %uint_1 %55 %uint_5 %uint_1 %56 %11 %uint_64 %uint_3 %62
6770 %64 = OpExtInst %void %1 DebugTypeComposite %13 %uint_0 %55 %uint_0 %uint_0 %56 %14 %51 %uint_3
6771 %67 = OpExtInst %void %1 DebugTypeFunction %uint_3 %57 %61
6772 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 %uint_15 %uint_1 %56 %16 %uint_3 %uint_16
6773 %69 = OpExtInst %void %1 DebugLexicalBlock %55 %uint_16 %uint_1 %68
6774 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 %uint_19 %uint_12 %69 %uint_4
6775 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 %uint_17 %uint_15 %69 %uint_4
6776 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 %uint_15 %uint_29 %68 %uint_4 %uint_1
6777 %73 = OpExtInst %void %1 DebugTypeComposite %20 %uint_1 %55 %uint_0 %uint_0 %56 %21 %51 %uint_3
6778 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 %uint_3 %uint_14 %56 %22 %g_sAniso %uint_8
6779 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 %uint_1 %uint_11 %56 %23 %g_tColor %uint_8
6780 %MainPs = OpFunction %void None %45
6781 %76 = OpLabel
6782 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
6783 %79 = OpVariable %_ptr_Function_v2float Function
6784 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
6785 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
6786 %82 = OpLoad %v2float %in_var_TEXCOORD2
6787 %83 = OpCompositeConstruct %PS_INPUT %82
6788 OpStore %param_var_i %83
6789 %112 = OpExtInst %void %1 DebugFunctionDefinition %68 %MainPs
6790 %109 = OpExtInst %void %1 DebugScope %68
6791 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
6792 %110 = OpExtInst %void %1 DebugScope %69
6793 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
6794 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugFunctionDefinition %68 %MainPs
6795 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %68
6796 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
6797 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69
6798 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %71 %78 %52
6799 %300 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_17 %uint_30
6800 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_17 %uint_30
6801 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
6802 %89 = OpLoad %v2float %88
6803 %301 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35
6804 OpStore %79 %89
6805 ;CHECK-NOT: OpStore %79 %89
6806 %302 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35
6807 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35
6808 %106 = OpExtInst %void %1 DebugValue %70 %89 %52
6809 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugValue %70 %89 %52
6810 %303 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_25 %uint_32
6811 %91 = OpLoad %type_2d_image %g_tColor
6812 %304 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_41 %uint_48
6813 %92 = OpLoad %type_sampler %g_sAniso
6814 %305 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_25 %uint_53
6815 %94 = OpSampledImage %type_sampled_image %91 %92
6816 %95 = OpImageSampleImplicitLod %v4float %94 %89 None
6817 %306 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_5 %uint_53
6818 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
6819 OpStore %96 %95
6820 %307 = OpExtInst %void %1 DebugLine %55 %uint_21 %uint_21 %uint_12 %uint_20
6821 %97 = OpLoad %PS_OUTPUT %78
6822 %308 = OpExtInst %void %1 DebugLine %55 %uint_21 %uint_21 %uint_5 %uint_20
6823 OpStore %81 %97
6824 %309 = OpExtInst %void %1 DebugNoLine
6825 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoLine
6826 %111 = OpExtInst %void %1 DebugNoScope
6827 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope
6828 %100 = OpCompositeExtract %v4float %97 0
6829 OpStore %out_var_SV_Target0 %100
6830 OpReturn
6831 OpFunctionEnd
6832 )";
6833
6834 SetTargetEnv(SPV_ENV_VULKAN_1_2);
6835 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6836 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
6837 }
6838
TEST_F(AggressiveDCETest,ShaderDebugInfoGlobalDCE)6839 TEST_F(AggressiveDCETest, ShaderDebugInfoGlobalDCE) {
6840 // Verify that DebugGlobalVariable for eliminated private variable has
6841 // variable operand replaced with DebugInfoNone.
6842
6843 const std::string text = R"(OpCapability Shader
6844 OpExtension "SPV_KHR_non_semantic_info"
6845 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
6846 OpMemoryModel Logical GLSL450
6847 OpEntryPoint Fragment %MainPs "MainPs" %out_var_SV_Target0 %a
6848 OpExecutionMode %MainPs OriginUpperLeft
6849 %5 = OpString "source2.hlsl"
6850 %24 = OpString "float"
6851 %29 = OpString "vColor"
6852 %33 = OpString "PS_OUTPUT"
6853 %37 = OpString "MainPs"
6854 %38 = OpString ""
6855 %42 = OpString "ps_output"
6856 %46 = OpString "a"
6857 OpName %a "a"
6858 OpName %out_var_SV_Target0 "out.var.SV_Target0"
6859 OpName %MainPs "MainPs"
6860 OpName %PS_OUTPUT "PS_OUTPUT"
6861 OpMemberName %PS_OUTPUT 0 "vColor"
6862 OpDecorate %out_var_SV_Target0 Location 0
6863 %float = OpTypeFloat 32
6864 %v4float = OpTypeVector %float 4
6865 %8 = OpConstantNull %v4float
6866 %float_0 = OpConstant %float 0
6867 %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
6868 %int = OpTypeInt 32 1
6869 %int_0 = OpConstant %int 0
6870 %uint = OpTypeInt 32 0
6871 %uint_32 = OpConstant %uint 32
6872 %_ptr_Private_v4float = OpTypePointer Private %v4float
6873 %_ptr_Output_v4float = OpTypePointer Output %v4float
6874 %void = OpTypeVoid
6875 %uint_1 = OpConstant %uint 1
6876 %uint_4 = OpConstant %uint 4
6877 %uint_5 = OpConstant %uint 5
6878 %uint_3 = OpConstant %uint 3
6879 %uint_0 = OpConstant %uint 0
6880 %uint_128 = OpConstant %uint 128
6881 %uint_12 = OpConstant %uint 12
6882 %uint_8 = OpConstant %uint 8
6883 %uint_9 = OpConstant %uint 9
6884 %uint_10 = OpConstant %uint 10
6885 %uint_15 = OpConstant %uint 15
6886 %48 = OpTypeFunction %void
6887 %PS_OUTPUT = OpTypeStruct %v4float
6888 %54 = OpTypeFunction %PS_OUTPUT
6889 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
6890 %_ptr_Function_v4float = OpTypePointer Function %v4float
6891 %a = OpVariable %_ptr_Private_v4float Private
6892 ;CHECK-NOT: %a = OpVariable %_ptr_Private_v4float Private
6893 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
6894 ;CHECK: [[dbg_none:%\w+]] = OpExtInst %void %1 DebugInfoNone
6895 %18 = OpExtInst %void %1 DebugExpression
6896 %19 = OpExtInst %void %1 DebugSource %5
6897 %20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %19 %uint_5
6898 %25 = OpExtInst %void %1 DebugTypeBasic %24 %uint_32 %uint_3 %uint_0
6899 %28 = OpExtInst %void %1 DebugTypeVector %25 %uint_4
6900 %31 = OpExtInst %void %1 DebugTypeMember %29 %28 %19 %uint_5 %uint_12 %uint_0 %uint_128 %uint_3
6901 %34 = OpExtInst %void %1 DebugTypeComposite %33 %uint_1 %19 %uint_3 %uint_8 %20 %33 %uint_128 %uint_3 %31
6902 %36 = OpExtInst %void %1 DebugTypeFunction %uint_3 %34
6903 %39 = OpExtInst %void %1 DebugFunction %37 %36 %19 %uint_8 %uint_1 %20 %38 %uint_3 %uint_9
6904 %41 = OpExtInst %void %1 DebugLexicalBlock %19 %uint_9 %uint_1 %39
6905 %43 = OpExtInst %void %1 DebugLocalVariable %42 %34 %19 %uint_10 %uint_15 %41 %uint_4
6906 %47 = OpExtInst %void %1 DebugGlobalVariable %46 %28 %19 %uint_1 %uint_15 %20 %46 %a %uint_8
6907 ;CHECK: %47 = OpExtInst %void %1 DebugGlobalVariable %46 %28 %19 %uint_1 %uint_15 %20 %46 [[dbg_none]] %uint_8
6908 %MainPs = OpFunction %void None %48
6909 %49 = OpLabel
6910 %65 = OpVariable %_ptr_Function_PS_OUTPUT Function
6911 %66 = OpVariable %_ptr_Function_PS_OUTPUT Function
6912 OpStore %a %8
6913 %72 = OpExtInst %void %1 DebugScope %41
6914 %69 = OpExtInst %void %1 DebugDeclare %43 %65 %18
6915 OpLine %5 11 5
6916 %70 = OpAccessChain %_ptr_Function_v4float %65 %int_0
6917 OpStore %70 %10
6918 OpLine %5 12 12
6919 %71 = OpLoad %PS_OUTPUT %65
6920 OpLine %5 12 5
6921 OpStore %66 %71
6922 %73 = OpExtInst %void %1 DebugNoLine
6923 %74 = OpExtInst %void %1 DebugNoScope
6924 %51 = OpLoad %PS_OUTPUT %66
6925 %53 = OpCompositeExtract %v4float %51 0
6926 OpStore %out_var_SV_Target0 %53
6927 OpLine %5 13 1
6928 OpReturn
6929 OpFunctionEnd
6930 )";
6931
6932 SetTargetEnv(SPV_ENV_VULKAN_1_2);
6933 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6934 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
6935 }
6936
TEST_F(AggressiveDCETest,DebugInfoDeclareKeepsStore)6937 TEST_F(AggressiveDCETest, DebugInfoDeclareKeepsStore) {
6938 // Verify that local variable tc and its store are kept by DebugDeclare.
6939 //
6940 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
6941 // has just been inlined.
6942
6943 const std::string text = R"(
6944 OpCapability Shader
6945 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
6946 OpMemoryModel Logical GLSL450
6947 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
6948 OpExecutionMode %MainPs OriginUpperLeft
6949 %20 = OpString "foo.frag"
6950 %24 = OpString "PS_OUTPUT"
6951 %28 = OpString "float"
6952 %31 = OpString "vColor"
6953 %33 = OpString "PS_INPUT"
6954 %38 = OpString "vTextureCoords"
6955 %40 = OpString "@type.2d.image"
6956 %41 = OpString "type.2d.image"
6957 %43 = OpString "Texture2D.TemplateParam"
6958 %47 = OpString "src.MainPs"
6959 %51 = OpString "tc"
6960 %53 = OpString "ps_output"
6961 %56 = OpString "i"
6962 %58 = OpString "@type.sampler"
6963 %59 = OpString "type.sampler"
6964 %61 = OpString "g_sAniso"
6965 %63 = OpString "g_tColor"
6966 OpName %type_2d_image "type.2d.image"
6967 OpName %g_tColor "g_tColor"
6968 OpName %type_sampler "type.sampler"
6969 OpName %g_sAniso "g_sAniso"
6970 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
6971 OpName %out_var_SV_Target0 "out.var.SV_Target0"
6972 OpName %MainPs "MainPs"
6973 OpName %PS_INPUT "PS_INPUT"
6974 OpMemberName %PS_INPUT 0 "vTextureCoords"
6975 OpName %param_var_i "param.var.i"
6976 OpName %PS_OUTPUT "PS_OUTPUT"
6977 OpMemberName %PS_OUTPUT 0 "vColor"
6978 OpName %type_sampled_image "type.sampled.image"
6979 OpDecorate %in_var_TEXCOORD2 Location 0
6980 OpDecorate %out_var_SV_Target0 Location 0
6981 OpDecorate %g_tColor DescriptorSet 0
6982 OpDecorate %g_tColor Binding 0
6983 OpDecorate %g_sAniso DescriptorSet 0
6984 OpDecorate %g_sAniso Binding 1
6985 %int = OpTypeInt 32 1
6986 %int_0 = OpConstant %int 0
6987 %uint = OpTypeInt 32 0
6988 %uint_32 = OpConstant %uint 32
6989 %float = OpTypeFloat 32
6990 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
6991 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
6992 %type_sampler = OpTypeSampler
6993 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
6994 %v2float = OpTypeVector %float 2
6995 %_ptr_Input_v2float = OpTypePointer Input %v2float
6996 %v4float = OpTypeVector %float 4
6997 %_ptr_Output_v4float = OpTypePointer Output %v4float
6998 %void = OpTypeVoid
6999 %uint_128 = OpConstant %uint 128
7000 %uint_0 = OpConstant %uint 0
7001 %uint_64 = OpConstant %uint 64
7002 %65 = OpTypeFunction %void
7003 %PS_INPUT = OpTypeStruct %v2float
7004 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7005 %PS_OUTPUT = OpTypeStruct %v4float
7006 %75 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7007 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7008 %_ptr_Function_v2float = OpTypePointer Function %v2float
7009 %type_sampled_image = OpTypeSampledImage %type_2d_image
7010 %_ptr_Function_v4float = OpTypePointer Function %v4float
7011 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7012 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7013 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7014 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7015 %39 = OpExtInst %void %1 DebugInfoNone
7016 %55 = OpExtInst %void %1 DebugExpression
7017 %22 = OpExtInst %void %1 DebugSource %20
7018 %23 = OpExtInst %void %1 DebugCompilationUnit 1 4 %22 HLSL
7019 %26 = OpExtInst %void %1 DebugTypeComposite %24 Structure %22 10 1 %23 %24 %uint_128 FlagIsProtected|FlagIsPrivate %27
7020 %29 = OpExtInst %void %1 DebugTypeBasic %28 %uint_32 Float
7021 %30 = OpExtInst %void %1 DebugTypeVector %29 4
7022 %27 = OpExtInst %void %1 DebugTypeMember %31 %30 %22 12 5 %26 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7023 %35 = OpExtInst %void %1 DebugTypeComposite %33 Structure %22 5 1 %23 %33 %uint_64 FlagIsProtected|FlagIsPrivate %36
7024 %37 = OpExtInst %void %1 DebugTypeVector %29 2
7025 %36 = OpExtInst %void %1 DebugTypeMember %38 %37 %22 7 5 %35 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7026 %42 = OpExtInst %void %1 DebugTypeComposite %40 Class %22 0 0 %23 %41 %39 FlagIsProtected|FlagIsPrivate
7027 %44 = OpExtInst %void %1 DebugTypeTemplateParameter %43 %29 %39 %22 0 0
7028 %45 = OpExtInst %void %1 DebugTypeTemplate %42 %44
7029 %46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %26 %35
7030 %48 = OpExtInst %void %1 DebugFunction %47 %46 %22 15 1 %23 %47 FlagIsProtected|FlagIsPrivate 16 %39
7031 %50 = OpExtInst %void %1 DebugLexicalBlock %22 16 1 %48
7032 %52 = OpExtInst %void %1 DebugLocalVariable %51 %37 %22 19 12 %50 FlagIsLocal
7033 %54 = OpExtInst %void %1 DebugLocalVariable %53 %26 %22 17 15 %50 FlagIsLocal
7034 %57 = OpExtInst %void %1 DebugLocalVariable %56 %35 %22 15 29 %48 FlagIsLocal 1
7035 %60 = OpExtInst %void %1 DebugTypeComposite %58 Structure %22 0 0 %23 %59 %39 FlagIsProtected|FlagIsPrivate
7036 %62 = OpExtInst %void %1 DebugGlobalVariable %61 %60 %22 3 14 %23 %61 %g_sAniso FlagIsDefinition
7037 %64 = OpExtInst %void %1 DebugGlobalVariable %63 %42 %22 1 11 %23 %63 %g_tColor FlagIsDefinition
7038 %MainPs = OpFunction %void None %65
7039 %66 = OpLabel
7040 %114 = OpExtInst %void %1 DebugScope %50
7041 %98 = OpVariable %_ptr_Function_PS_OUTPUT Function
7042 %99 = OpVariable %_ptr_Function_v2float Function
7043 %115 = OpExtInst %void %1 DebugNoScope
7044 %100 = OpVariable %_ptr_Function_PS_OUTPUT Function
7045 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7046 %70 = OpLoad %v2float %in_var_TEXCOORD2
7047 %71 = OpCompositeConstruct %PS_INPUT %70
7048 OpStore %param_var_i %71
7049 %116 = OpExtInst %void %1 DebugScope %48
7050 %102 = OpExtInst %void %1 DebugDeclare %57 %param_var_i %55
7051 %117 = OpExtInst %void %1 DebugScope %50
7052 %103 = OpExtInst %void %1 DebugDeclare %54 %98 %55
7053 OpLine %20 19 17
7054 %104 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7055 %105 = OpLoad %v2float %104
7056 OpLine %20 19 12
7057 OpStore %99 %105
7058 ;CHECK: OpStore %99 %105
7059 %106 = OpExtInst %void %1 DebugDeclare %52 %99 %55
7060 OpLine %20 20 26
7061 %107 = OpLoad %type_2d_image %g_tColor
7062 OpLine %20 20 46
7063 %108 = OpLoad %type_sampler %g_sAniso
7064 OpLine %20 20 26
7065 %110 = OpSampledImage %type_sampled_image %107 %108
7066 %111 = OpImageSampleImplicitLod %v4float %110 %105 None
7067 OpLine %20 20 5
7068 %112 = OpAccessChain %_ptr_Function_v4float %98 %int_0
7069 OpStore %112 %111
7070 OpLine %20 21 12
7071 %113 = OpLoad %PS_OUTPUT %98
7072 OpLine %20 21 5
7073 OpStore %100 %113
7074 %118 = OpExtInst %void %1 DebugNoScope
7075 %73 = OpLoad %PS_OUTPUT %100
7076 %74 = OpCompositeExtract %v4float %73 0
7077 OpStore %out_var_SV_Target0 %74
7078 OpReturn
7079 OpFunctionEnd
7080 )";
7081
7082 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7083 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7084 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7085 }
7086
TEST_F(AggressiveDCETest,DebugInfoValueDerefKeepsStore)7087 TEST_F(AggressiveDCETest, DebugInfoValueDerefKeepsStore) {
7088 // Verify that local variable tc and its store are kept by DebugValue with
7089 // Deref.
7090 //
7091 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
7092 // has just been inlined and edited to replace the DebugDeclare with the
7093 // DebugValue/Deref.
7094
7095 const std::string text = R"(
7096 OpCapability Shader
7097 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7098 OpMemoryModel Logical GLSL450
7099 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
7100 OpExecutionMode %MainPs OriginUpperLeft
7101 %7 = OpString "foo.frag"
7102 %8 = OpString "PS_OUTPUT"
7103 %9 = OpString "float"
7104 %10 = OpString "vColor"
7105 %11 = OpString "PS_INPUT"
7106 %12 = OpString "vTextureCoords"
7107 %13 = OpString "@type.2d.image"
7108 %14 = OpString "type.2d.image"
7109 %15 = OpString "Texture2D.TemplateParam"
7110 %16 = OpString "src.MainPs"
7111 %17 = OpString "tc"
7112 %18 = OpString "ps_output"
7113 %19 = OpString "i"
7114 %20 = OpString "@type.sampler"
7115 %21 = OpString "type.sampler"
7116 %22 = OpString "g_sAniso"
7117 %23 = OpString "g_tColor"
7118 OpName %type_2d_image "type.2d.image"
7119 OpName %g_tColor "g_tColor"
7120 OpName %type_sampler "type.sampler"
7121 OpName %g_sAniso "g_sAniso"
7122 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
7123 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7124 OpName %MainPs "MainPs"
7125 OpName %PS_INPUT "PS_INPUT"
7126 OpMemberName %PS_INPUT 0 "vTextureCoords"
7127 OpName %param_var_i "param.var.i"
7128 OpName %PS_OUTPUT "PS_OUTPUT"
7129 OpMemberName %PS_OUTPUT 0 "vColor"
7130 OpName %type_sampled_image "type.sampled.image"
7131 OpDecorate %in_var_TEXCOORD2 Location 0
7132 OpDecorate %out_var_SV_Target0 Location 0
7133 OpDecorate %g_tColor DescriptorSet 0
7134 OpDecorate %g_tColor Binding 0
7135 OpDecorate %g_sAniso DescriptorSet 0
7136 OpDecorate %g_sAniso Binding 1
7137 %int = OpTypeInt 32 1
7138 %int_0 = OpConstant %int 0
7139 %uint = OpTypeInt 32 0
7140 %uint_32 = OpConstant %uint 32
7141 %float = OpTypeFloat 32
7142 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7143 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7144 %type_sampler = OpTypeSampler
7145 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7146 %v2float = OpTypeVector %float 2
7147 %_ptr_Input_v2float = OpTypePointer Input %v2float
7148 %v4float = OpTypeVector %float 4
7149 %_ptr_Output_v4float = OpTypePointer Output %v4float
7150 %void = OpTypeVoid
7151 %uint_128 = OpConstant %uint 128
7152 %uint_0 = OpConstant %uint 0
7153 %uint_64 = OpConstant %uint 64
7154 %45 = OpTypeFunction %void
7155 %PS_INPUT = OpTypeStruct %v2float
7156 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7157 %PS_OUTPUT = OpTypeStruct %v4float
7158 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7159 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7160 %_ptr_Function_v2float = OpTypePointer Function %v2float
7161 %type_sampled_image = OpTypeSampledImage %type_2d_image
7162 %_ptr_Function_v4float = OpTypePointer Function %v4float
7163 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7164 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7165 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7166 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7167 %51 = OpExtInst %void %1 DebugInfoNone
7168 %52 = OpExtInst %void %1 DebugExpression
7169 %53 = OpExtInst %void %1 DebugOperation Deref
7170 %54 = OpExtInst %void %1 DebugExpression %53
7171 %55 = OpExtInst %void %1 DebugSource %7
7172 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL
7173 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58
7174 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float
7175 %60 = OpExtInst %void %1 DebugTypeVector %59 4
7176 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7177 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62
7178 %63 = OpExtInst %void %1 DebugTypeVector %59 2
7179 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7180 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate
7181 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0
7182 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65
7183 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61
7184 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51
7185 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68
7186 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal
7187 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal
7188 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1
7189 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate
7190 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition
7191 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition
7192 %MainPs = OpFunction %void None %45
7193 %76 = OpLabel
7194 %101 = OpExtInst %void %1 DebugScope %69
7195 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
7196 %79 = OpVariable %_ptr_Function_v2float Function
7197 %102 = OpExtInst %void %1 DebugNoScope
7198 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
7199 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7200 %82 = OpLoad %v2float %in_var_TEXCOORD2
7201 %83 = OpCompositeConstruct %PS_INPUT %82
7202 OpStore %param_var_i %83
7203 %103 = OpExtInst %void %1 DebugScope %68
7204 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
7205 %104 = OpExtInst %void %1 DebugScope %69
7206 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
7207 OpLine %7 19 17
7208 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7209 %89 = OpLoad %v2float %88
7210 OpLine %7 19 12
7211 OpStore %79 %89
7212 ;CHECK: OpStore %79 %89
7213 %90 = OpExtInst %void %1 DebugValue %70 %79 %54
7214 OpLine %7 20 26
7215 %91 = OpLoad %type_2d_image %g_tColor
7216 OpLine %7 20 46
7217 %92 = OpLoad %type_sampler %g_sAniso
7218 OpLine %7 20 26
7219 %94 = OpSampledImage %type_sampled_image %91 %92
7220 %95 = OpImageSampleImplicitLod %v4float %94 %89 None
7221 OpLine %7 20 5
7222 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
7223 OpStore %96 %95
7224 OpLine %7 21 12
7225 %97 = OpLoad %PS_OUTPUT %78
7226 OpLine %7 21 5
7227 OpStore %81 %97
7228 %105 = OpExtInst %void %1 DebugNoScope
7229 %99 = OpLoad %PS_OUTPUT %81
7230 %100 = OpCompositeExtract %v4float %99 0
7231 OpStore %out_var_SV_Target0 %100
7232 OpReturn
7233 OpFunctionEnd
7234 )";
7235
7236 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7237 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7238 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7239 }
7240
TEST_F(AggressiveDCETest,DebugInfoElimUnusedTextureKeepGlobalVariable)7241 TEST_F(AggressiveDCETest, DebugInfoElimUnusedTextureKeepGlobalVariable) {
7242 // Verify that unused texture g_tColor2 is eliminated but its
7243 // DebugGlobalVariable is retained but with DebugInfoNone for its Variable.
7244 //
7245 // Same shader source as DebugInfoInFunctionKeepStoreVarElim but with unused
7246 // g_tColor2 added.
7247
7248 const std::string text = R"(
7249 OpCapability Shader
7250 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7251 OpMemoryModel Logical GLSL450
7252 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_tColor2 %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
7253 OpExecutionMode %MainPs OriginUpperLeft
7254 %21 = OpString "foo6.frag"
7255 %25 = OpString "PS_OUTPUT"
7256 %29 = OpString "float"
7257 %32 = OpString "vColor"
7258 %34 = OpString "PS_INPUT"
7259 %39 = OpString "vTextureCoords"
7260 %41 = OpString "@type.2d.image"
7261 %42 = OpString "type.2d.image"
7262 %44 = OpString "Texture2D.TemplateParam"
7263 %48 = OpString "src.MainPs"
7264 %52 = OpString "tc"
7265 %54 = OpString "ps_output"
7266 %57 = OpString "i"
7267 %59 = OpString "@type.sampler"
7268 %60 = OpString "type.sampler"
7269 %62 = OpString "g_sAniso"
7270 %64 = OpString "g_tColor2"
7271 %66 = OpString "g_tColor"
7272 OpName %type_2d_image "type.2d.image"
7273 OpName %g_tColor "g_tColor"
7274 OpName %g_tColor2 "g_tColor2"
7275 OpName %type_sampler "type.sampler"
7276 OpName %g_sAniso "g_sAniso"
7277 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
7278 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7279 OpName %MainPs "MainPs"
7280 OpName %PS_INPUT "PS_INPUT"
7281 OpMemberName %PS_INPUT 0 "vTextureCoords"
7282 OpName %param_var_i "param.var.i"
7283 OpName %PS_OUTPUT "PS_OUTPUT"
7284 OpMemberName %PS_OUTPUT 0 "vColor"
7285 OpName %type_sampled_image "type.sampled.image"
7286 OpDecorate %in_var_TEXCOORD2 Location 0
7287 OpDecorate %out_var_SV_Target0 Location 0
7288 OpDecorate %g_tColor DescriptorSet 0
7289 OpDecorate %g_tColor Binding 0
7290 OpDecorate %g_tColor2 DescriptorSet 0
7291 OpDecorate %g_tColor2 Binding 1
7292 OpDecorate %g_sAniso DescriptorSet 0
7293 OpDecorate %g_sAniso Binding 2
7294 %int = OpTypeInt 32 1
7295 %int_0 = OpConstant %int 0
7296 %uint = OpTypeInt 32 0
7297 %uint_32 = OpConstant %uint 32
7298 %float = OpTypeFloat 32
7299 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7300 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7301 %type_sampler = OpTypeSampler
7302 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7303 %v2float = OpTypeVector %float 2
7304 %_ptr_Input_v2float = OpTypePointer Input %v2float
7305 %v4float = OpTypeVector %float 4
7306 %_ptr_Output_v4float = OpTypePointer Output %v4float
7307 %void = OpTypeVoid
7308 %uint_128 = OpConstant %uint 128
7309 %uint_0 = OpConstant %uint 0
7310 %uint_64 = OpConstant %uint 64
7311 %68 = OpTypeFunction %void
7312 %PS_INPUT = OpTypeStruct %v2float
7313 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7314 %PS_OUTPUT = OpTypeStruct %v4float
7315 %78 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7316 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7317 %_ptr_Function_v2float = OpTypePointer Function %v2float
7318 %type_sampled_image = OpTypeSampledImage %type_2d_image
7319 %_ptr_Function_v4float = OpTypePointer Function %v4float
7320 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7321 %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7322 ;CHECK-NOT: %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7323 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7324 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7325 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7326 %40 = OpExtInst %void %1 DebugInfoNone
7327 %56 = OpExtInst %void %1 DebugExpression
7328 %23 = OpExtInst %void %1 DebugSource %21
7329 %24 = OpExtInst %void %1 DebugCompilationUnit 1 4 %23 HLSL
7330 %27 = OpExtInst %void %1 DebugTypeComposite %25 Structure %23 11 1 %24 %25 %uint_128 FlagIsProtected|FlagIsPrivate %28
7331 %30 = OpExtInst %void %1 DebugTypeBasic %29 %uint_32 Float
7332 %31 = OpExtInst %void %1 DebugTypeVector %30 4
7333 %28 = OpExtInst %void %1 DebugTypeMember %32 %31 %23 13 5 %27 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7334 %36 = OpExtInst %void %1 DebugTypeComposite %34 Structure %23 6 1 %24 %34 %uint_64 FlagIsProtected|FlagIsPrivate %37
7335 %38 = OpExtInst %void %1 DebugTypeVector %30 2
7336 %37 = OpExtInst %void %1 DebugTypeMember %39 %38 %23 8 5 %36 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7337 %43 = OpExtInst %void %1 DebugTypeComposite %41 Class %23 0 0 %24 %42 %40 FlagIsProtected|FlagIsPrivate
7338 %45 = OpExtInst %void %1 DebugTypeTemplateParameter %44 %30 %40 %23 0 0
7339 %46 = OpExtInst %void %1 DebugTypeTemplate %43 %45
7340 %47 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %27 %36
7341 %49 = OpExtInst %void %1 DebugFunction %48 %47 %23 16 1 %24 %48 FlagIsProtected|FlagIsPrivate 17 %40
7342 %51 = OpExtInst %void %1 DebugLexicalBlock %23 17 1 %49
7343 %53 = OpExtInst %void %1 DebugLocalVariable %52 %38 %23 20 12 %51 FlagIsLocal
7344 %55 = OpExtInst %void %1 DebugLocalVariable %54 %27 %23 18 15 %51 FlagIsLocal
7345 %58 = OpExtInst %void %1 DebugLocalVariable %57 %36 %23 16 29 %49 FlagIsLocal 1
7346 %61 = OpExtInst %void %1 DebugTypeComposite %59 Structure %23 0 0 %24 %60 %40 FlagIsProtected|FlagIsPrivate
7347 %63 = OpExtInst %void %1 DebugGlobalVariable %62 %61 %23 4 14 %24 %62 %g_sAniso FlagIsDefinition
7348 %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition
7349 ;CHECK-NOT: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition
7350 ;CHECK: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %40 FlagIsDefinition
7351 %67 = OpExtInst %void %1 DebugGlobalVariable %66 %43 %23 1 11 %24 %66 %g_tColor FlagIsDefinition
7352 %MainPs = OpFunction %void None %68
7353 %69 = OpLabel
7354 %117 = OpExtInst %void %1 DebugScope %51
7355 %101 = OpVariable %_ptr_Function_PS_OUTPUT Function
7356 %102 = OpVariable %_ptr_Function_v2float Function
7357 %118 = OpExtInst %void %1 DebugNoScope
7358 %103 = OpVariable %_ptr_Function_PS_OUTPUT Function
7359 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7360 %73 = OpLoad %v2float %in_var_TEXCOORD2
7361 %74 = OpCompositeConstruct %PS_INPUT %73
7362 OpStore %param_var_i %74
7363 %119 = OpExtInst %void %1 DebugScope %49
7364 %105 = OpExtInst %void %1 DebugDeclare %58 %param_var_i %56
7365 %120 = OpExtInst %void %1 DebugScope %51
7366 %106 = OpExtInst %void %1 DebugDeclare %55 %101 %56
7367 OpLine %21 20 17
7368 %107 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7369 %108 = OpLoad %v2float %107
7370 OpLine %21 20 12
7371 OpStore %102 %108
7372 %109 = OpExtInst %void %1 DebugDeclare %53 %102 %56
7373 OpLine %21 21 26
7374 %110 = OpLoad %type_2d_image %g_tColor
7375 OpLine %21 21 46
7376 %111 = OpLoad %type_sampler %g_sAniso
7377 OpLine %21 21 57
7378 %112 = OpLoad %v2float %102
7379 OpLine %21 21 26
7380 %113 = OpSampledImage %type_sampled_image %110 %111
7381 %114 = OpImageSampleImplicitLod %v4float %113 %112 None
7382 OpLine %21 21 5
7383 %115 = OpAccessChain %_ptr_Function_v4float %101 %int_0
7384 OpStore %115 %114
7385 OpLine %21 22 12
7386 %116 = OpLoad %PS_OUTPUT %101
7387 OpLine %21 22 5
7388 OpStore %103 %116
7389 %121 = OpExtInst %void %1 DebugNoScope
7390 %76 = OpLoad %PS_OUTPUT %103
7391 %77 = OpCompositeExtract %v4float %76 0
7392 OpStore %out_var_SV_Target0 %77
7393 OpReturn
7394 OpFunctionEnd
7395 )";
7396
7397 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7398 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7399 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7400 }
7401
TEST_F(AggressiveDCETest,KeepDebugScopeParent)7402 TEST_F(AggressiveDCETest, KeepDebugScopeParent) {
7403 // Verify that local variable tc and its store are kept by DebugDeclare.
7404 //
7405 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
7406 // has just been inlined.
7407
7408 const std::string text = R"(
7409 OpCapability Shader
7410 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7411 OpMemoryModel Logical GLSL450
7412 OpEntryPoint Fragment %main "main" %out_var_SV_TARGET0
7413 OpExecutionMode %main OriginUpperLeft
7414 %11 = OpString "float"
7415 %16 = OpString "t.hlsl"
7416 %19 = OpString "src.main"
7417 OpName %out_var_SV_TARGET0 "out.var.SV_TARGET0"
7418 OpName %main "main"
7419 OpDecorate %out_var_SV_TARGET0 Location 0
7420 %float = OpTypeFloat 32
7421 %float_0 = OpConstant %float 0
7422 %v4float = OpTypeVector %float 4
7423 %7 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
7424 %uint = OpTypeInt 32 0
7425 %uint_32 = OpConstant %uint 32
7426 %_ptr_Output_v4float = OpTypePointer Output %v4float
7427 %void = OpTypeVoid
7428 %23 = OpTypeFunction %void
7429 %26 = OpTypeFunction %v4float
7430 %out_var_SV_TARGET0 = OpVariable %_ptr_Output_v4float Output
7431 %_ptr_Function_v4float = OpTypePointer Function %v4float
7432 %33 = OpExtInst %void %1 DebugInfoNone
7433 %13 = OpExtInst %void %1 DebugTypeBasic %11 %uint_32 Float
7434 %14 = OpExtInst %void %1 DebugTypeVector %13 4
7435 %15 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %14
7436 %17 = OpExtInst %void %1 DebugSource %16
7437 %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL
7438 %20 = OpExtInst %void %1 DebugFunction %19 %15 %17 1 1 %18 %19 FlagIsProtected|FlagIsPrivate 2 %33
7439 %22 = OpExtInst %void %1 DebugLexicalBlock %17 2 1 %20
7440 %main = OpFunction %void None %23
7441 %24 = OpLabel
7442 %31 = OpVariable %_ptr_Function_v4float Function
7443 ; CHECK: [[block:%\w+]] = OpExtInst %void %1 DebugLexicalBlock
7444 ; CHECK: DebugScope [[block]]
7445 %34 = OpExtInst %void %1 DebugScope %22
7446 OpLine %16 3 5
7447 OpStore %31 %7
7448 OpStore %out_var_SV_TARGET0 %7
7449 %35 = OpExtInst %void %1 DebugNoScope
7450 OpReturn
7451 OpFunctionEnd
7452 )";
7453
7454 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7455 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7456 }
7457
TEST_F(AggressiveDCETest,KeepExportFunctions)7458 TEST_F(AggressiveDCETest, KeepExportFunctions) {
7459 // All functions are reachable. In particular, ExportedFunc and Constant are
7460 // reachable because ExportedFunc is exported. Nothing should be removed.
7461 const std::vector<const char*> text = {
7462 // clang-format off
7463 "OpCapability Shader",
7464 "OpCapability Linkage",
7465 "OpMemoryModel Logical GLSL450",
7466 "OpEntryPoint Fragment %main \"main\"",
7467 "OpName %main \"main\"",
7468 "OpName %ExportedFunc \"ExportedFunc\"",
7469 "OpName %Live \"Live\"",
7470 "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export",
7471 "%void = OpTypeVoid",
7472 "%7 = OpTypeFunction %void",
7473 "%main = OpFunction %void None %7",
7474 "%15 = OpLabel",
7475 "OpReturn",
7476 "OpFunctionEnd",
7477 "%ExportedFunc = OpFunction %void None %7",
7478 "%19 = OpLabel",
7479 "%16 = OpFunctionCall %void %Live",
7480 "OpReturn",
7481 "OpFunctionEnd",
7482 "%Live = OpFunction %void None %7",
7483 "%20 = OpLabel",
7484 "OpReturn",
7485 "OpFunctionEnd"
7486 // clang-format on
7487 };
7488
7489 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7490 std::string assembly = JoinAllInsts(text);
7491 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
7492 assembly, /* skip_nop = */ true, /* do_validation = */ false);
7493 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
7494 EXPECT_EQ(assembly, std::get<0>(result));
7495 }
7496
TEST_F(AggressiveDCETest,KeepPrivateVarInExportFunctions)7497 TEST_F(AggressiveDCETest, KeepPrivateVarInExportFunctions) {
7498 // The loads and stores from the private variable should not be removed
7499 // because the functions are exported and could be called.
7500 const std::string text = R"(OpCapability Shader
7501 OpCapability Linkage
7502 OpMemoryModel Logical GLSL450
7503 OpSource HLSL 630
7504 OpName %privateVar "privateVar"
7505 OpName %ReadPrivate "ReadPrivate"
7506 OpName %WritePrivate "WritePrivate"
7507 OpName %value "value"
7508 OpDecorate %ReadPrivate LinkageAttributes "ReadPrivate" Export
7509 OpDecorate %WritePrivate LinkageAttributes "WritePrivate" Export
7510 %int = OpTypeInt 32 1
7511 %_ptr_Private_int = OpTypePointer Private %int
7512 %6 = OpTypeFunction %int
7513 %void = OpTypeVoid
7514 %_ptr_Function_int = OpTypePointer Function %int
7515 %10 = OpTypeFunction %void %_ptr_Function_int
7516 %privateVar = OpVariable %_ptr_Private_int Private
7517 %ReadPrivate = OpFunction %int None %6
7518 %12 = OpLabel
7519 %8 = OpLoad %int %privateVar
7520 OpReturnValue %8
7521 OpFunctionEnd
7522 %WritePrivate = OpFunction %void None %10
7523 %value = OpFunctionParameter %_ptr_Function_int
7524 %13 = OpLabel
7525 %14 = OpLoad %int %value
7526 OpStore %privateVar %14
7527 OpReturn
7528 OpFunctionEnd
7529 )";
7530
7531 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7532 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
7533 text, /* skip_nop = */ true, /* do_validation = */ false);
7534 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
7535 EXPECT_EQ(text, std::get<0>(result));
7536 }
7537
TEST_F(AggressiveDCETest,KeepLableNames)7538 TEST_F(AggressiveDCETest, KeepLableNames) {
7539 const std::string text = R"(OpCapability Shader
7540 OpCapability Linkage
7541 OpMemoryModel Logical GLSL450
7542 OpSource HLSL 630
7543 OpName %WritePrivate "WritePrivate"
7544 OpName %entry "entry"
7545 OpName %target "target"
7546 OpDecorate %WritePrivate LinkageAttributes "WritePrivate" Export
7547 %void = OpTypeVoid
7548 %3 = OpTypeFunction %void
7549 %WritePrivate = OpFunction %void None %3
7550 %entry = OpLabel
7551 OpBranch %target
7552 %target = OpLabel
7553 OpReturn
7554 OpFunctionEnd
7555 )";
7556
7557 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7558 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
7559 text, /* skip_nop = */ true, /* do_validation = */ false);
7560 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
7561 EXPECT_EQ(text, std::get<0>(result));
7562 }
7563
TEST_F(AggressiveDCETest,PreserveInterface)7564 TEST_F(AggressiveDCETest, PreserveInterface) {
7565 // Set preserve_interface to true. Verify that unused uniform
7566 // constant in entry point interface is not eliminated.
7567 const std::string text = R"(OpCapability RayTracingKHR
7568 OpExtension "SPV_KHR_ray_tracing"
7569 %1 = OpExtInstImport "GLSL.std.450"
7570 OpMemoryModel Logical GLSL450
7571 OpEntryPoint RayGenerationNV %2 "main" %3 %4
7572 OpDecorate %3 Location 0
7573 OpDecorate %4 DescriptorSet 2
7574 OpDecorate %4 Binding 0
7575 %void = OpTypeVoid
7576 %6 = OpTypeFunction %void
7577 %uint = OpTypeInt 32 0
7578 %uint_0 = OpConstant %uint 0
7579 %float = OpTypeFloat 32
7580 %_ptr_CallableDataNV_float = OpTypePointer CallableDataNV %float
7581 %3 = OpVariable %_ptr_CallableDataNV_float CallableDataNV
7582 %13 = OpTypeAccelerationStructureKHR
7583 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
7584 %4 = OpVariable %_ptr_UniformConstant_13 UniformConstant
7585 %2 = OpFunction %void None %6
7586 %15 = OpLabel
7587 OpExecuteCallableKHR %uint_0 %3
7588 OpReturn
7589 OpFunctionEnd
7590 )";
7591
7592 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7593 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7594 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
7595 text, /* skip_nop = */ true, /* do_validation = */ false,
7596 /* preserve_interface */ true);
7597 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
7598 EXPECT_EQ(text, std::get<0>(result));
7599 }
7600
TEST_F(AggressiveDCETest,EmptyContinueWithConditionalBranch)7601 TEST_F(AggressiveDCETest, EmptyContinueWithConditionalBranch) {
7602 const std::string text = R"(OpCapability Shader
7603 %1 = OpExtInstImport "GLSL.std.450"
7604 OpMemoryModel Logical GLSL450
7605 OpEntryPoint Fragment %2 "main"
7606 OpExecutionMode %2 OriginUpperLeft
7607 %void = OpTypeVoid
7608 %4 = OpTypeFunction %void
7609 %bool = OpTypeBool
7610 %false = OpConstantFalse %bool
7611 %2 = OpFunction %void None %4
7612 %9 = OpLabel
7613 OpBranch %10
7614 %10 = OpLabel
7615 OpLoopMerge %11 %12 None
7616 OpBranch %13
7617 %13 = OpLabel
7618 OpKill
7619 %12 = OpLabel
7620 OpBranchConditional %false %10 %10
7621 %11 = OpLabel
7622 OpUnreachable
7623 OpFunctionEnd
7624 )";
7625
7626 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7627 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7628 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, false);
7629 }
7630
TEST_F(AggressiveDCETest,FunctionBecomesUnreachableAfterDCE)7631 TEST_F(AggressiveDCETest, FunctionBecomesUnreachableAfterDCE) {
7632 const std::string text = R"(
7633 OpCapability Shader
7634 %1 = OpExtInstImport "GLSL.std.450"
7635 OpMemoryModel Logical GLSL450
7636 OpEntryPoint Fragment %2 "main"
7637 OpExecutionMode %2 OriginUpperLeft
7638 OpSource ESSL 320
7639 %void = OpTypeVoid
7640 %4 = OpTypeFunction %void
7641 %int = OpTypeInt 32 1
7642 %_ptr_Function_int = OpTypePointer Function %int
7643 %7 = OpTypeFunction %int
7644 %int_n1 = OpConstant %int -1
7645 %2 = OpFunction %void None %4
7646 %9 = OpLabel
7647 OpKill
7648 %10 = OpLabel
7649 %11 = OpFunctionCall %int %12
7650 OpReturn
7651 OpFunctionEnd
7652 ; CHECK: {{%\w+}} = OpFunction %int DontInline|Pure
7653 %12 = OpFunction %int DontInline|Pure %7
7654 ; CHECK-NEXT: {{%\w+}} = OpLabel
7655 %13 = OpLabel
7656 %14 = OpVariable %_ptr_Function_int Function
7657 ; CHECK-NEXT: OpBranch [[header:%\w+]]
7658 OpBranch %15
7659 ; CHECK-NEXT: [[header]] = OpLabel
7660 ; CHECK-NEXT: OpBranch [[merge:%\w+]]
7661 %15 = OpLabel
7662 OpLoopMerge %16 %17 None
7663 OpBranch %18
7664 %18 = OpLabel
7665 %19 = OpLoad %int %14
7666 OpBranch %17
7667 %17 = OpLabel
7668 OpBranch %15
7669 ; CHECK-NEXT: [[merge]] = OpLabel
7670 %16 = OpLabel
7671 ; CHECK-NEXT: OpReturnValue %int_n1
7672 OpReturnValue %int_n1
7673 ; CHECK-NEXT: OpFunctionEnd
7674 OpFunctionEnd
7675 )";
7676
7677 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7678 }
7679
TEST_F(AggressiveDCETest,KeepTopLevelDebugInfo)7680 TEST_F(AggressiveDCETest, KeepTopLevelDebugInfo) {
7681 // Don't eliminate DebugCompilationUnit, DebugSourceContinued, and
7682 // DebugEntryPoint
7683 const std::string text = R"(
7684 OpCapability Shader
7685 OpExtension "SPV_KHR_non_semantic_info"
7686 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
7687 OpMemoryModel Logical GLSL450
7688 OpEntryPoint Fragment %MainPs "MainPs" %out_var_SV_Target0
7689 OpExecutionMode %MainPs OriginUpperLeft
7690 %4 = OpString "foo2.frag"
7691 %5 = OpString "
7692 struct PS_OUTPUT
7693 {
7694 float4 vColor : SV_Target0 ;
7695 } ;
7696
7697 "
7698 %6 = OpString "
7699 PS_OUTPUT MainPs ( )
7700 {
7701 PS_OUTPUT ps_output ;
7702 ps_output . vColor = float4( 1.0, 0.0, 0.0, 0.0 );
7703 return ps_output ;
7704 }
7705
7706 "
7707 %7 = OpString "float"
7708 %8 = OpString "vColor"
7709 %9 = OpString "PS_OUTPUT"
7710 %10 = OpString "MainPs"
7711 %11 = OpString ""
7712 %12 = OpString "ps_output"
7713 %13 = OpString "97a939fb"
7714 %14 = OpString " foo2.frag -E MainPs -T ps_6_1 -spirv -fspv-target-env=vulkan1.2 -fspv-debug=vulkan-with-source -fcgl -Fo foo2.frag.nopt.spv -Qembed_debug"
7715 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7716 OpName %MainPs "MainPs"
7717 OpDecorate %out_var_SV_Target0 Location 0
7718 %float = OpTypeFloat 32
7719 %float_1 = OpConstant %float 1
7720 %float_0 = OpConstant %float 0
7721 %v4float = OpTypeVector %float 4
7722 %23 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_0
7723 %int = OpTypeInt 32 1
7724 %int_0 = OpConstant %int 0
7725 %uint = OpTypeInt 32 0
7726 %uint_32 = OpConstant %uint 32
7727 %_ptr_Output_v4float = OpTypePointer Output %v4float
7728 %void = OpTypeVoid
7729 %uint_1 = OpConstant %uint 1
7730 %uint_4 = OpConstant %uint 4
7731 %uint_5 = OpConstant %uint 5
7732 %uint_3 = OpConstant %uint 3
7733 %uint_0 = OpConstant %uint 0
7734 %uint_128 = OpConstant %uint 128
7735 %uint_12 = OpConstant %uint 12
7736 %uint_2 = OpConstant %uint 2
7737 %uint_8 = OpConstant %uint 8
7738 %uint_7 = OpConstant %uint 7
7739 %uint_9 = OpConstant %uint 9
7740 %uint_15 = OpConstant %uint 15
7741 %42 = OpTypeFunction %void
7742 %uint_10 = OpConstant %uint 10
7743 %uint_53 = OpConstant %uint 53
7744 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7745 %49 = OpExtInst %void %1 DebugExpression
7746 %50 = OpExtInst %void %1 DebugSource %4 %5
7747 %51 = OpExtInst %void %1 DebugSourceContinued %6
7748 ; CHECK: %51 = OpExtInst %void %1 DebugSourceContinued %6
7749 %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5
7750 ; CHECK: %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5
7751 %53 = OpExtInst %void %1 DebugTypeBasic %7 %uint_32 %uint_3 %uint_0
7752 %54 = OpExtInst %void %1 DebugTypeVector %53 %uint_4
7753 %55 = OpExtInst %void %1 DebugTypeMember %8 %54 %50 %uint_4 %uint_12 %uint_0 %uint_128 %uint_3
7754 %56 = OpExtInst %void %1 DebugTypeComposite %9 %uint_1 %50 %uint_2 %uint_8 %52 %9 %uint_128 %uint_3 %55
7755 %57 = OpExtInst %void %1 DebugTypeFunction %uint_3 %56
7756 %58 = OpExtInst %void %1 DebugFunction %10 %57 %50 %uint_7 %uint_1 %52 %11 %uint_3 %uint_8
7757 %59 = OpExtInst %void %1 DebugLexicalBlock %50 %uint_8 %uint_1 %58
7758 %60 = OpExtInst %void %1 DebugLocalVariable %12 %56 %50 %uint_9 %uint_15 %59 %uint_4
7759 %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14
7760 ; CHECK: %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14
7761 %MainPs = OpFunction %void None %42
7762 %62 = OpLabel
7763 %63 = OpExtInst %void %1 DebugFunctionDefinition %58 %MainPs
7764 %112 = OpExtInst %void %1 DebugScope %59
7765 %111 = OpExtInst %void %1 DebugLine %50 %uint_10 %uint_10 %uint_5 %uint_53
7766 %110 = OpExtInst %void %1 DebugValue %60 %23 %49 %int_0
7767 %113 = OpExtInst %void %1 DebugNoLine
7768 %114 = OpExtInst %void %1 DebugNoScope
7769 OpStore %out_var_SV_Target0 %23
7770 %66 = OpExtInst %void %1 DebugLine %50 %uint_12 %uint_12 %uint_1 %uint_1
7771 OpReturn
7772 OpFunctionEnd
7773 )";
7774
7775 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7776 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7777 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7778 }
7779
7780 } // namespace
7781 } // namespace opt
7782 } // namespace spvtools
7783