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