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