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