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 OpSwitch %13 %14 0 %17 1 %15
3952 %17 = OpLabel
3953 OpStore %3 %uint_1
3954 OpBranch %15
3955 %15 = OpLabel
3956 OpBranch %12
3957 %14 = OpLabel
3958 OpStore %3 %uint_0
3959 OpReturn
3960 OpFunctionEnd
3961 )";
3962
3963 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
3964 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, false, true);
3965 }
3966
TEST_F(AggressiveDCETest,BasicDeleteDeadFunction)3967 TEST_F(AggressiveDCETest, BasicDeleteDeadFunction) {
3968 // The function Dead should be removed because it is never called.
3969 const std::vector<const char*> common_code = {
3970 // clang-format off
3971 "OpCapability Shader",
3972 "OpMemoryModel Logical GLSL450",
3973 "OpEntryPoint Fragment %main \"main\"",
3974 "OpName %main \"main\"",
3975 "OpName %Live \"Live\"",
3976 "%void = OpTypeVoid",
3977 "%7 = OpTypeFunction %void",
3978 "%main = OpFunction %void None %7",
3979 "%15 = OpLabel",
3980 "%16 = OpFunctionCall %void %Live",
3981 "%17 = OpFunctionCall %void %Live",
3982 "OpReturn",
3983 "OpFunctionEnd",
3984 "%Live = OpFunction %void None %7",
3985 "%20 = OpLabel",
3986 "OpReturn",
3987 "OpFunctionEnd"
3988 // clang-format on
3989 };
3990
3991 const std::vector<const char*> dead_function = {
3992 // clang-format off
3993 "%Dead = OpFunction %void None %7",
3994 "%19 = OpLabel",
3995 "OpReturn",
3996 "OpFunctionEnd",
3997 // clang-format on
3998 };
3999
4000 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4001 SinglePassRunAndCheck<AggressiveDCEPass>(
4002 JoinAllInsts(Concat(common_code, dead_function)),
4003 JoinAllInsts(common_code), /* skip_nop = */ true);
4004 }
4005
TEST_F(AggressiveDCETest,BasicKeepLiveFunction)4006 TEST_F(AggressiveDCETest, BasicKeepLiveFunction) {
4007 // Everything is reachable from an entry point, so no functions should be
4008 // deleted.
4009 const std::vector<const char*> text = {
4010 // clang-format off
4011 "OpCapability Shader",
4012 "OpMemoryModel Logical GLSL450",
4013 "OpEntryPoint Fragment %main \"main\"",
4014 "OpName %main \"main\"",
4015 "OpName %Live1 \"Live1\"",
4016 "OpName %Live2 \"Live2\"",
4017 "%void = OpTypeVoid",
4018 "%7 = OpTypeFunction %void",
4019 "%main = OpFunction %void None %7",
4020 "%15 = OpLabel",
4021 "%16 = OpFunctionCall %void %Live2",
4022 "%17 = OpFunctionCall %void %Live1",
4023 "OpReturn",
4024 "OpFunctionEnd",
4025 "%Live1 = OpFunction %void None %7",
4026 "%19 = OpLabel",
4027 "OpReturn",
4028 "OpFunctionEnd",
4029 "%Live2 = OpFunction %void None %7",
4030 "%20 = OpLabel",
4031 "OpReturn",
4032 "OpFunctionEnd"
4033 // clang-format on
4034 };
4035
4036 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4037 std::string assembly = JoinAllInsts(text);
4038 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>(
4039 assembly, /* skip_nop = */ true, /* do_validation = */ false);
4040 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
4041 EXPECT_EQ(assembly, std::get<0>(result));
4042 }
4043
TEST_F(AggressiveDCETest,BasicRemoveDecorationsAndNames)4044 TEST_F(AggressiveDCETest, BasicRemoveDecorationsAndNames) {
4045 // We want to remove the names and decorations associated with results that
4046 // are removed. This test will check for that.
4047 const std::string text = R"(
4048 OpCapability Shader
4049 OpMemoryModel Logical GLSL450
4050 OpEntryPoint Vertex %main "main"
4051 OpName %main "main"
4052 OpName %Dead "Dead"
4053 OpName %x "x"
4054 OpName %y "y"
4055 OpName %z "z"
4056 OpDecorate %x RelaxedPrecision
4057 OpDecorate %y RelaxedPrecision
4058 OpDecorate %z RelaxedPrecision
4059 OpDecorate %6 RelaxedPrecision
4060 OpDecorate %7 RelaxedPrecision
4061 OpDecorate %8 RelaxedPrecision
4062 %void = OpTypeVoid
4063 %10 = OpTypeFunction %void
4064 %float = OpTypeFloat 32
4065 %_ptr_Function_float = OpTypePointer Function %float
4066 %float_1 = OpConstant %float 1
4067 %main = OpFunction %void None %10
4068 %14 = OpLabel
4069 OpReturn
4070 OpFunctionEnd
4071 %Dead = OpFunction %void None %10
4072 %15 = OpLabel
4073 %x = OpVariable %_ptr_Function_float Function
4074 %y = OpVariable %_ptr_Function_float Function
4075 %z = OpVariable %_ptr_Function_float Function
4076 OpStore %x %float_1
4077 OpStore %y %float_1
4078 %6 = OpLoad %float %x
4079 %7 = OpLoad %float %y
4080 %8 = OpFAdd %float %6 %7
4081 OpStore %z %8
4082 OpReturn
4083 OpFunctionEnd)";
4084
4085 const std::string expected_output = R"(OpCapability Shader
4086 OpMemoryModel Logical GLSL450
4087 OpEntryPoint Vertex %main "main"
4088 OpName %main "main"
4089 %void = OpTypeVoid
4090 %10 = OpTypeFunction %void
4091 %main = OpFunction %void None %10
4092 %14 = OpLabel
4093 OpReturn
4094 OpFunctionEnd
4095 )";
4096
4097 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4098 SinglePassRunAndCheck<AggressiveDCEPass>(text, expected_output,
4099 /* skip_nop = */ true);
4100 }
4101
TEST_F(AggressiveDCETest,BasicAllDeadConstants)4102 TEST_F(AggressiveDCETest, BasicAllDeadConstants) {
4103 const std::string text = R"(
4104 ; CHECK-NOT: OpConstant
4105 OpCapability Shader
4106 OpCapability Float64
4107 %1 = OpExtInstImport "GLSL.std.450"
4108 OpMemoryModel Logical GLSL450
4109 OpEntryPoint Vertex %main "main"
4110 OpName %main "main"
4111 %void = OpTypeVoid
4112 %4 = OpTypeFunction %void
4113 %bool = OpTypeBool
4114 %true = OpConstantTrue %bool
4115 %false = OpConstantFalse %bool
4116 %int = OpTypeInt 32 1
4117 %9 = OpConstant %int 1
4118 %uint = OpTypeInt 32 0
4119 %11 = OpConstant %uint 2
4120 %float = OpTypeFloat 32
4121 %13 = OpConstant %float 3.1415
4122 %double = OpTypeFloat 64
4123 %15 = OpConstant %double 3.14159265358979
4124 %main = OpFunction %void None %4
4125 %16 = OpLabel
4126 OpReturn
4127 OpFunctionEnd
4128 )";
4129
4130 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
4131 }
4132
TEST_F(AggressiveDCETest,BasicNoneDeadConstants)4133 TEST_F(AggressiveDCETest, BasicNoneDeadConstants) {
4134 const std::vector<const char*> text = {
4135 // clang-format off
4136 "OpCapability Shader",
4137 "OpCapability Float64",
4138 "%1 = OpExtInstImport \"GLSL.std.450\"",
4139 "OpMemoryModel Logical GLSL450",
4140 "OpEntryPoint Vertex %main \"main\" %btv %bfv %iv %uv %fv %dv",
4141 "OpName %main \"main\"",
4142 "OpName %btv \"btv\"",
4143 "OpName %bfv \"bfv\"",
4144 "OpName %iv \"iv\"",
4145 "OpName %uv \"uv\"",
4146 "OpName %fv \"fv\"",
4147 "OpName %dv \"dv\"",
4148 "%void = OpTypeVoid",
4149 "%10 = OpTypeFunction %void",
4150 "%bool = OpTypeBool",
4151 "%_ptr_Output_bool = OpTypePointer Output %bool",
4152 "%true = OpConstantTrue %bool",
4153 "%false = OpConstantFalse %bool",
4154 "%int = OpTypeInt 32 1",
4155 "%_ptr_Output_int = OpTypePointer Output %int",
4156 "%int_1 = OpConstant %int 1",
4157 "%uint = OpTypeInt 32 0",
4158 "%_ptr_Output_uint = OpTypePointer Output %uint",
4159 "%uint_2 = OpConstant %uint 2",
4160 "%float = OpTypeFloat 32",
4161 "%_ptr_Output_float = OpTypePointer Output %float",
4162 "%float_3_1415 = OpConstant %float 3.1415",
4163 "%double = OpTypeFloat 64",
4164 "%_ptr_Output_double = OpTypePointer Output %double",
4165 "%double_3_14159265358979 = OpConstant %double 3.14159265358979",
4166 "%btv = OpVariable %_ptr_Output_bool Output",
4167 "%bfv = OpVariable %_ptr_Output_bool Output",
4168 "%iv = OpVariable %_ptr_Output_int Output",
4169 "%uv = OpVariable %_ptr_Output_uint Output",
4170 "%fv = OpVariable %_ptr_Output_float Output",
4171 "%dv = OpVariable %_ptr_Output_double Output",
4172 "%main = OpFunction %void None %10",
4173 "%27 = OpLabel",
4174 "OpStore %btv %true",
4175 "OpStore %bfv %false",
4176 "OpStore %iv %int_1",
4177 "OpStore %uv %uint_2",
4178 "OpStore %fv %float_3_1415",
4179 "OpStore %dv %double_3_14159265358979",
4180 "OpReturn",
4181 "OpFunctionEnd",
4182 // clang-format on
4183 };
4184 // All constants are used, so none of them should be eliminated.
4185 SinglePassRunAndCheck<AggressiveDCEPass>(
4186 JoinAllInsts(text), JoinAllInsts(text), /* skip_nop = */ true);
4187 }
4188
4189 struct AggressiveEliminateDeadConstantTestCase {
4190 // Type declarations and constants that should be kept.
4191 std::vector<std::string> used_consts;
4192 // Instructions that refer to constants, this is added to create uses for
4193 // some constants so they won't be treated as dead constants.
4194 std::vector<std::string> main_insts;
4195 // Dead constants that should be removed.
4196 std::vector<std::string> dead_consts;
4197 // Expectations
4198 std::vector<std::string> checks;
4199 };
4200
4201 // All types that are potentially required in
4202 // AggressiveEliminateDeadConstantTest.
4203 const std::vector<std::string> CommonTypes = {
4204 // clang-format off
4205 // scalar types
4206 "%bool = OpTypeBool",
4207 "%uint = OpTypeInt 32 0",
4208 "%int = OpTypeInt 32 1",
4209 "%float = OpTypeFloat 32",
4210 "%double = OpTypeFloat 64",
4211 // vector types
4212 "%v2bool = OpTypeVector %bool 2",
4213 "%v2uint = OpTypeVector %uint 2",
4214 "%v2int = OpTypeVector %int 2",
4215 "%v3int = OpTypeVector %int 3",
4216 "%v4int = OpTypeVector %int 4",
4217 "%v2float = OpTypeVector %float 2",
4218 "%v3float = OpTypeVector %float 3",
4219 "%v2double = OpTypeVector %double 2",
4220 // variable pointer types
4221 "%_pf_bool = OpTypePointer Output %bool",
4222 "%_pf_uint = OpTypePointer Output %uint",
4223 "%_pf_int = OpTypePointer Output %int",
4224 "%_pf_float = OpTypePointer Output %float",
4225 "%_pf_double = OpTypePointer Output %double",
4226 "%_pf_v2int = OpTypePointer Output %v2int",
4227 "%_pf_v3int = OpTypePointer Output %v3int",
4228 "%_pf_v2float = OpTypePointer Output %v2float",
4229 "%_pf_v3float = OpTypePointer Output %v3float",
4230 "%_pf_v2double = OpTypePointer Output %v2double",
4231 // struct types
4232 "%inner_struct = OpTypeStruct %bool %int %float %double",
4233 "%outer_struct = OpTypeStruct %inner_struct %int %double",
4234 "%flat_struct = OpTypeStruct %bool %int %float %double",
4235 // clang-format on
4236 };
4237
4238 using AggressiveEliminateDeadConstantTest =
4239 PassTest<::testing::TestWithParam<AggressiveEliminateDeadConstantTestCase>>;
4240
TEST_P(AggressiveEliminateDeadConstantTest,Custom)4241 TEST_P(AggressiveEliminateDeadConstantTest, Custom) {
4242 auto& tc = GetParam();
4243 AssemblyBuilder builder;
4244 builder.AppendTypesConstantsGlobals(CommonTypes)
4245 .AppendTypesConstantsGlobals(tc.used_consts)
4246 .AppendInMain(tc.main_insts);
4247 const std::string expected = builder.GetCode();
4248 builder.AppendTypesConstantsGlobals(tc.dead_consts);
4249 builder.PrependPreamble(tc.checks);
4250 const std::string assembly_with_dead_const = builder.GetCode();
4251
4252 // Do not enable validation. As the input code is invalid from the base
4253 // tests (ported from other passes).
4254 SinglePassRunAndMatch<AggressiveDCEPass>(assembly_with_dead_const, false);
4255 }
4256
4257 INSTANTIATE_TEST_SUITE_P(
4258 ScalarTypeConstants, AggressiveEliminateDeadConstantTest,
4259 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4260 // clang-format off
4261 // Scalar type constants, one dead constant and one used constant.
4262 {
4263 /* .used_consts = */
4264 {
4265 "%used_const_int = OpConstant %int 1",
4266 },
4267 /* .main_insts = */
4268 {
4269 "%int_var = OpVariable %_pf_int Output",
4270 "OpStore %int_var %used_const_int",
4271 },
4272 /* .dead_consts = */
4273 {
4274 "%dead_const_int = OpConstant %int 1",
4275 },
4276 /* .checks = */
4277 {
4278 "; CHECK: [[const:%\\w+]] = OpConstant %int 1",
4279 "; CHECK-NOT: OpConstant",
4280 "; CHECK: OpStore {{%\\w+}} [[const]]",
4281 },
4282 },
4283 {
4284 /* .used_consts = */
4285 {
4286 "%used_const_uint = OpConstant %uint 1",
4287 },
4288 /* .main_insts = */
4289 {
4290 "%uint_var = OpVariable %_pf_uint Output",
4291 "OpStore %uint_var %used_const_uint",
4292 },
4293 /* .dead_consts = */
4294 {
4295 "%dead_const_uint = OpConstant %uint 1",
4296 },
4297 /* .checks = */
4298 {
4299 "; CHECK: [[const:%\\w+]] = OpConstant %uint 1",
4300 "; CHECK-NOT: OpConstant",
4301 "; CHECK: OpStore {{%\\w+}} [[const]]",
4302 },
4303 },
4304 {
4305 /* .used_consts = */
4306 {
4307 "%used_const_float = OpConstant %float 3.1415",
4308 },
4309 /* .main_insts = */
4310 {
4311 "%float_var = OpVariable %_pf_float Output",
4312 "OpStore %float_var %used_const_float",
4313 },
4314 /* .dead_consts = */
4315 {
4316 "%dead_const_float = OpConstant %float 3.1415",
4317 },
4318 /* .checks = */
4319 {
4320 "; CHECK: [[const:%\\w+]] = OpConstant %float 3.1415",
4321 "; CHECK-NOT: OpConstant",
4322 "; CHECK: OpStore {{%\\w+}} [[const]]",
4323 },
4324 },
4325 {
4326 /* .used_consts = */
4327 {
4328 "%used_const_double = OpConstant %double 3.14",
4329 },
4330 /* .main_insts = */
4331 {
4332 "%double_var = OpVariable %_pf_double Output",
4333 "OpStore %double_var %used_const_double",
4334 },
4335 /* .dead_consts = */
4336 {
4337 "%dead_const_double = OpConstant %double 3.14",
4338 },
4339 /* .checks = */
4340 {
4341 "; CHECK: [[const:%\\w+]] = OpConstant %double 3.14",
4342 "; CHECK-NOT: OpConstant",
4343 "; CHECK: OpStore {{%\\w+}} [[const]]",
4344 },
4345 },
4346 // clang-format on
4347 })));
4348
4349 INSTANTIATE_TEST_SUITE_P(
4350 VectorTypeConstants, AggressiveEliminateDeadConstantTest,
4351 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4352 // clang-format off
4353 // Tests eliminating dead constant type ivec2. One dead constant vector
4354 // and one used constant vector, each built from its own group of
4355 // scalar constants.
4356 {
4357 /* .used_consts = */
4358 {
4359 "%used_int_x = OpConstant %int 1",
4360 "%used_int_y = OpConstant %int 2",
4361 "%used_v2int = OpConstantComposite %v2int %used_int_x %used_int_y",
4362 },
4363 /* .main_insts = */
4364 {
4365 "%v2int_var = OpVariable %_pf_v2int Output",
4366 "OpStore %v2int_var %used_v2int",
4367 },
4368 /* .dead_consts = */
4369 {
4370 "%dead_int_x = OpConstant %int 1",
4371 "%dead_int_y = OpConstant %int 2",
4372 "%dead_v2int = OpConstantComposite %v2int %dead_int_x %dead_int_y",
4373 },
4374 /* .checks = */
4375 {
4376 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1",
4377 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2",
4378 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2int [[constx]] [[consty]]",
4379 "; CHECK-NOT: OpConstant",
4380 "; CHECK: OpStore {{%\\w+}} [[const]]",
4381 },
4382 },
4383 // Tests eliminating dead constant ivec3. One dead constant vector and
4384 // one used constant vector. But both built from a same group of
4385 // scalar constants.
4386 {
4387 /* .used_consts = */
4388 {
4389 "%used_int_x = OpConstant %int 1",
4390 "%used_int_y = OpConstant %int 2",
4391 "%used_int_z = OpConstant %int 3",
4392 "%used_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z",
4393 },
4394 /* .main_insts = */
4395 {
4396 "%v3int_var = OpVariable %_pf_v3int Output",
4397 "OpStore %v3int_var %used_v3int",
4398 },
4399 /* .dead_consts = */
4400 {
4401 "%dead_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z",
4402 },
4403 /* .checks = */
4404 {
4405 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1",
4406 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2",
4407 "; CHECK: [[constz:%\\w+]] = OpConstant %int 3",
4408 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3int [[constx]] [[consty]] [[constz]]",
4409 "; CHECK-NOT: OpConstant",
4410 "; CHECK: OpStore {{%\\w+}} [[const]]",
4411 },
4412 },
4413 // Tests eliminating dead constant vec2. One dead constant vector and
4414 // one used constant vector. Each built from its own group of scalar
4415 // constants.
4416 {
4417 /* .used_consts = */
4418 {
4419 "%used_float_x = OpConstant %float 3.1415",
4420 "%used_float_y = OpConstant %float 4.13",
4421 "%used_v2float = OpConstantComposite %v2float %used_float_x %used_float_y",
4422 },
4423 /* .main_insts = */
4424 {
4425 "%v2float_var = OpVariable %_pf_v2float Output",
4426 "OpStore %v2float_var %used_v2float",
4427 },
4428 /* .dead_consts = */
4429 {
4430 "%dead_float_x = OpConstant %float 3.1415",
4431 "%dead_float_y = OpConstant %float 4.13",
4432 "%dead_v2float = OpConstantComposite %v2float %dead_float_x %dead_float_y",
4433 },
4434 /* .checks = */
4435 {
4436 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415",
4437 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.13",
4438 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2float [[constx]] [[consty]]",
4439 "; CHECK-NOT: OpConstant",
4440 "; CHECK: OpStore {{%\\w+}} [[const]]",
4441 },
4442 },
4443 // Tests eliminating dead constant vec3. One dead constant vector and
4444 // one used constant vector. Both built from a same group of scalar
4445 // constants.
4446 {
4447 /* .used_consts = */
4448 {
4449 "%used_float_x = OpConstant %float 3.1415",
4450 "%used_float_y = OpConstant %float 4.25",
4451 "%used_float_z = OpConstant %float 4.75",
4452 "%used_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z",
4453 },
4454 /* .main_insts = */
4455 {
4456 "%v3float_var = OpVariable %_pf_v3float Output",
4457 "OpStore %v3float_var %used_v3float",
4458 },
4459 /* .dead_consts = */
4460 {
4461 "%dead_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z",
4462 },
4463 /* .checks = */
4464 {
4465 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415",
4466 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.25",
4467 "; CHECK: [[constz:%\\w+]] = OpConstant %float 4.75",
4468 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3float [[constx]] [[consty]]",
4469 "; CHECK-NOT: OpConstant",
4470 "; CHECK: OpStore {{%\\w+}} [[const]]",
4471 },
4472 },
4473 // clang-format on
4474 })));
4475
4476 INSTANTIATE_TEST_SUITE_P(
4477 StructTypeConstants, AggressiveEliminateDeadConstantTest,
4478 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4479 // clang-format off
4480 // A plain struct type dead constants. All of its components are dead
4481 // constants too.
4482 {
4483 /* .used_consts = */ {},
4484 /* .main_insts = */ {},
4485 /* .dead_consts = */
4486 {
4487 "%dead_bool = OpConstantTrue %bool",
4488 "%dead_int = OpConstant %int 1",
4489 "%dead_float = OpConstant %float 2.5",
4490 "%dead_double = OpConstant %double 3.14159265358979",
4491 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %dead_int %dead_float %dead_double",
4492 },
4493 /* .checks = */
4494 {
4495 "; CHECK-NOT: OpConstant",
4496 },
4497 },
4498 // A plain struct type dead constants. Some of its components are dead
4499 // constants while others are not.
4500 {
4501 /* .used_consts = */
4502 {
4503 "%used_int = OpConstant %int 1",
4504 "%used_double = OpConstant %double 3.14159265358979",
4505 },
4506 /* .main_insts = */
4507 {
4508 "%int_var = OpVariable %_pf_int Output",
4509 "OpStore %int_var %used_int",
4510 "%double_var = OpVariable %_pf_double Output",
4511 "OpStore %double_var %used_double",
4512 },
4513 /* .dead_consts = */
4514 {
4515 "%dead_bool = OpConstantTrue %bool",
4516 "%dead_float = OpConstant %float 2.5",
4517 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %used_int %dead_float %used_double",
4518 },
4519 /* .checks = */
4520 {
4521 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4522 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979",
4523 "; CHECK-NOT: OpConstant",
4524 "; CHECK: OpStore {{%\\w+}} [[int]]",
4525 "; CHECK: OpStore {{%\\w+}} [[double]]",
4526 },
4527 },
4528 // A nesting struct type dead constants. All components of both outer
4529 // and inner structs are dead and should be removed after dead constant
4530 // elimination.
4531 {
4532 /* .used_consts = */ {},
4533 /* .main_insts = */ {},
4534 /* .dead_consts = */
4535 {
4536 "%dead_bool = OpConstantTrue %bool",
4537 "%dead_int = OpConstant %int 1",
4538 "%dead_float = OpConstant %float 2.5",
4539 "%dead_double = OpConstant %double 3.1415926535",
4540 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %dead_int %dead_float %dead_double",
4541 "%dead_int2 = OpConstant %int 2",
4542 "%dead_double2 = OpConstant %double 1.428571428514",
4543 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int2 %dead_double2",
4544 },
4545 /* .checks = */
4546 {
4547 "; CHECK-NOT: OpConstant",
4548 },
4549 },
4550 // A nesting struct type dead constants. Some of its components are
4551 // dead constants while others are not.
4552 {
4553 /* .used_consts = */
4554 {
4555 "%used_int = OpConstant %int 1",
4556 "%used_double = OpConstant %double 3.14159265358979",
4557 },
4558 /* .main_insts = */
4559 {
4560 "%int_var = OpVariable %_pf_int Output",
4561 "OpStore %int_var %used_int",
4562 "%double_var = OpVariable %_pf_double Output",
4563 "OpStore %double_var %used_double",
4564 },
4565 /* .dead_consts = */
4566 {
4567 "%dead_bool = OpConstantTrue %bool",
4568 "%dead_float = OpConstant %float 2.5",
4569 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %used_int %dead_float %used_double",
4570 "%dead_int = OpConstant %int 2",
4571 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int %used_double",
4572 },
4573 /* .checks = */
4574 {
4575 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4576 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979",
4577 "; CHECK-NOT: OpConstant",
4578 "; CHECK: OpStore {{%\\w+}} [[int]]",
4579 "; CHECK: OpStore {{%\\w+}} [[double]]",
4580 },
4581 },
4582 // A nesting struct case. The inner struct is used while the outer struct is not
4583 {
4584 /* .used_const = */
4585 {
4586 "%used_bool = OpConstantTrue %bool",
4587 "%used_int = OpConstant %int 1",
4588 "%used_float = OpConstant %float 1.23",
4589 "%used_double = OpConstant %double 1.2345678901234",
4590 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4591 },
4592 /* .main_insts = */
4593 {
4594 "%bool_var = OpVariable %_pf_bool Output",
4595 "%bool_from_inner_struct = OpCompositeExtract %bool %used_inner_struct 0",
4596 "OpStore %bool_var %bool_from_inner_struct",
4597 },
4598 /* .dead_consts = */
4599 {
4600 "%dead_int = OpConstant %int 2",
4601 "%dead_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %dead_int %used_double"
4602 },
4603 /* .checks = */
4604 {
4605 "; CHECK: [[bool:%\\w+]] = OpConstantTrue",
4606 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4607 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23",
4608 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234",
4609 "; CHECK: [[struct:%\\w+]] = OpConstantComposite %inner_struct [[bool]] [[int]] [[float]] [[double]]",
4610 "; CHECK-NOT: OpConstant",
4611 "; CHECK: OpCompositeExtract %bool [[struct]]",
4612 }
4613 },
4614 // A nesting struct case. The outer struct is used, so the inner struct should not
4615 // be removed even though it is not used anywhere.
4616 {
4617 /* .used_const = */
4618 {
4619 "%used_bool = OpConstantTrue %bool",
4620 "%used_int = OpConstant %int 1",
4621 "%used_float = OpConstant %float 1.23",
4622 "%used_double = OpConstant %double 1.2345678901234",
4623 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4624 "%used_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double"
4625 },
4626 /* .main_insts = */
4627 {
4628 "%int_var = OpVariable %_pf_int Output",
4629 "%int_from_outer_struct = OpCompositeExtract %int %used_outer_struct 1",
4630 "OpStore %int_var %int_from_outer_struct",
4631 },
4632 /* .dead_consts = */ {},
4633 /* .checks = */
4634 {
4635 "; CHECK: [[bool:%\\w+]] = OpConstantTrue %bool",
4636 "; CHECK: [[int:%\\w+]] = OpConstant %int 1",
4637 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23",
4638 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234",
4639 "; CHECK: [[inner_struct:%\\w+]] = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double",
4640 "; CHECK: [[outer_struct:%\\w+]] = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double",
4641 "; CHECK: OpCompositeExtract %int [[outer_struct]]",
4642 },
4643 },
4644 // clang-format on
4645 })));
4646
4647 INSTANTIATE_TEST_SUITE_P(
4648 ScalarTypeSpecConstants, AggressiveEliminateDeadConstantTest,
4649 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4650 // clang-format off
4651 // All scalar type spec constants.
4652 {
4653 /* .used_consts = */
4654 {
4655 "%used_bool = OpSpecConstantTrue %bool",
4656 "%used_uint = OpSpecConstant %uint 2",
4657 "%used_int = OpSpecConstant %int 2",
4658 "%used_float = OpSpecConstant %float 2.5",
4659 "%used_double = OpSpecConstant %double 1.428571428514",
4660 },
4661 /* .main_insts = */
4662 {
4663 "%bool_var = OpVariable %_pf_bool Output",
4664 "%uint_var = OpVariable %_pf_uint Output",
4665 "%int_var = OpVariable %_pf_int Output",
4666 "%float_var = OpVariable %_pf_float Output",
4667 "%double_var = OpVariable %_pf_double Output",
4668 "OpStore %bool_var %used_bool",
4669 "OpStore %uint_var %used_uint",
4670 "OpStore %int_var %used_int",
4671 "OpStore %float_var %used_float",
4672 "OpStore %double_var %used_double",
4673 },
4674 /* .dead_consts = */
4675 {
4676 "%dead_bool = OpSpecConstantTrue %bool",
4677 "%dead_uint = OpSpecConstant %uint 2",
4678 "%dead_int = OpSpecConstant %int 2",
4679 "%dead_float = OpSpecConstant %float 2.5",
4680 "%dead_double = OpSpecConstant %double 1.428571428514",
4681 },
4682 /* .checks = */
4683 {
4684 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool",
4685 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 2",
4686 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 2",
4687 "; CHECK: [[float:%\\w+]] = OpSpecConstant %float 2.5",
4688 "; CHECK: [[double:%\\w+]] = OpSpecConstant %double 1.428571428514",
4689 "; CHECK-NOT: OpSpecConstant",
4690 "; CHECK: OpStore {{%\\w+}} [[bool]]",
4691 "; CHECK: OpStore {{%\\w+}} [[uint]]",
4692 "; CHECK: OpStore {{%\\w+}} [[int]]",
4693 "; CHECK: OpStore {{%\\w+}} [[float]]",
4694 "; CHECK: OpStore {{%\\w+}} [[double]]",
4695 },
4696 },
4697 // clang-format on
4698 })));
4699
4700 INSTANTIATE_TEST_SUITE_P(
4701 VectorTypeSpecConstants, AggressiveEliminateDeadConstantTest,
4702 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4703 // clang-format off
4704 // Bool vector type spec constants. One vector has all component dead,
4705 // another vector has one dead boolean and one used boolean.
4706 {
4707 /* .used_consts = */
4708 {
4709 "%used_bool = OpSpecConstantTrue %bool",
4710 },
4711 /* .main_insts = */
4712 {
4713 "%bool_var = OpVariable %_pf_bool Output",
4714 "OpStore %bool_var %used_bool",
4715 },
4716 /* .dead_consts = */
4717 {
4718 "%dead_bool = OpSpecConstantFalse %bool",
4719 "%dead_bool_vec1 = OpSpecConstantComposite %v2bool %dead_bool %dead_bool",
4720 "%dead_bool_vec2 = OpSpecConstantComposite %v2bool %dead_bool %used_bool",
4721 },
4722 /* .checks = */
4723 {
4724 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool",
4725 "; CHECK-NOT: OpSpecConstant",
4726 "; CHECK: OpStore {{%\\w+}} [[bool]]",
4727 },
4728 },
4729
4730 // Uint vector type spec constants. One vector has all component dead,
4731 // another vector has one dead unsigend integer and one used unsigned
4732 // integer.
4733 {
4734 /* .used_consts = */
4735 {
4736 "%used_uint = OpSpecConstant %uint 3",
4737 },
4738 /* .main_insts = */
4739 {
4740 "%uint_var = OpVariable %_pf_uint Output",
4741 "OpStore %uint_var %used_uint",
4742 },
4743 /* .dead_consts = */
4744 {
4745 "%dead_uint = OpSpecConstant %uint 1",
4746 "%dead_uint_vec1 = OpSpecConstantComposite %v2uint %dead_uint %dead_uint",
4747 "%dead_uint_vec2 = OpSpecConstantComposite %v2uint %dead_uint %used_uint",
4748 },
4749 /* .checks = */
4750 {
4751 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 3",
4752 "; CHECK-NOT: OpSpecConstant",
4753 "; CHECK: OpStore {{%\\w+}} [[uint]]",
4754 },
4755 },
4756
4757 // Int vector type spec constants. One vector has all component dead,
4758 // another vector has one dead integer and one used integer.
4759 {
4760 /* .used_consts = */
4761 {
4762 "%used_int = OpSpecConstant %int 3",
4763 },
4764 /* .main_insts = */
4765 {
4766 "%int_var = OpVariable %_pf_int Output",
4767 "OpStore %int_var %used_int",
4768 },
4769 /* .dead_consts = */
4770 {
4771 "%dead_int = OpSpecConstant %int 1",
4772 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_int %dead_int",
4773 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_int %used_int",
4774 },
4775 /* .checks = */
4776 {
4777 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 3",
4778 "; CHECK-NOT: OpSpecConstant",
4779 "; CHECK: OpStore {{%\\w+}} [[int]]",
4780 },
4781 },
4782
4783 // Int vector type spec constants built with both spec constants and
4784 // front-end constants.
4785 {
4786 /* .used_consts = */
4787 {
4788 "%used_spec_int = OpSpecConstant %int 3",
4789 "%used_front_end_int = OpConstant %int 3",
4790 },
4791 /* .main_insts = */
4792 {
4793 "%int_var1 = OpVariable %_pf_int Output",
4794 "OpStore %int_var1 %used_spec_int",
4795 "%int_var2 = OpVariable %_pf_int Output",
4796 "OpStore %int_var2 %used_front_end_int",
4797 },
4798 /* .dead_consts = */
4799 {
4800 "%dead_spec_int = OpSpecConstant %int 1",
4801 "%dead_front_end_int = OpConstant %int 1",
4802 // Dead front-end and dead spec constants
4803 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_spec_int %dead_front_end_int",
4804 // Used front-end and dead spec constants
4805 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_spec_int %used_front_end_int",
4806 // Dead front-end and used spec constants
4807 "%dead_int_vec3 = OpSpecConstantComposite %v2int %dead_front_end_int %used_spec_int",
4808 },
4809 /* .checks = */
4810 {
4811 "; CHECK: [[int1:%\\w+]] = OpSpecConstant %int 3",
4812 "; CHECK: [[int2:%\\w+]] = OpConstant %int 3",
4813 "; CHECK-NOT: OpSpecConstant",
4814 "; CHECK-NOT: OpConstant",
4815 "; CHECK: OpStore {{%\\w+}} [[int1]]",
4816 "; CHECK: OpStore {{%\\w+}} [[int2]]",
4817 },
4818 },
4819 // clang-format on
4820 })));
4821
4822 INSTANTIATE_TEST_SUITE_P(
4823 SpecConstantOp, AggressiveEliminateDeadConstantTest,
4824 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
4825 // clang-format off
4826 // Cast operations: uint <-> int <-> bool
4827 {
4828 /* .used_consts = */ {},
4829 /* .main_insts = */ {},
4830 /* .dead_consts = */
4831 {
4832 // Assistant constants, only used in dead spec constant
4833 // operations.
4834 "%signed_zero = OpConstant %int 0",
4835 "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero",
4836 "%unsigned_zero = OpConstant %uint 0",
4837 "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero",
4838 "%signed_one = OpConstant %int 1",
4839 "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one",
4840 "%unsigned_one = OpConstant %uint 1",
4841 "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one",
4842
4843 // Spec constants that support casting to each other.
4844 "%dead_bool = OpSpecConstantTrue %bool",
4845 "%dead_uint = OpSpecConstant %uint 1",
4846 "%dead_int = OpSpecConstant %int 2",
4847 "%dead_bool_vec = OpSpecConstantComposite %v2bool %dead_bool %dead_bool",
4848 "%dead_uint_vec = OpSpecConstantComposite %v2uint %dead_uint %dead_uint",
4849 "%dead_int_vec = OpSpecConstantComposite %v2int %dead_int %dead_int",
4850
4851 // Scalar cast to boolean spec constant.
4852 "%int_to_bool = OpSpecConstantOp %bool INotEqual %dead_int %signed_zero",
4853 "%uint_to_bool = OpSpecConstantOp %bool INotEqual %dead_uint %unsigned_zero",
4854
4855 // Vector cast to boolean spec constant.
4856 "%int_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_int_vec %signed_zero_vec",
4857 "%uint_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_uint_vec %unsigned_zero_vec",
4858
4859 // Scalar cast to int spec constant.
4860 "%bool_to_int = OpSpecConstantOp %int Select %dead_bool %signed_one %signed_zero",
4861 "%uint_to_int = OpSpecConstantOp %uint IAdd %dead_uint %unsigned_zero",
4862
4863 // Vector cast to int spec constant.
4864 "%bool_to_int_vec = OpSpecConstantOp %v2int Select %dead_bool_vec %signed_one_vec %signed_zero_vec",
4865 "%uint_to_int_vec = OpSpecConstantOp %v2uint IAdd %dead_uint_vec %unsigned_zero_vec",
4866
4867 // Scalar cast to uint spec constant.
4868 "%bool_to_uint = OpSpecConstantOp %uint Select %dead_bool %unsigned_one %unsigned_zero",
4869 "%int_to_uint_vec = OpSpecConstantOp %uint IAdd %dead_int %signed_zero",
4870
4871 // Vector cast to uint spec constant.
4872 "%bool_to_uint_vec = OpSpecConstantOp %v2uint Select %dead_bool_vec %unsigned_one_vec %unsigned_zero_vec",
4873 "%int_to_uint = OpSpecConstantOp %v2uint IAdd %dead_int_vec %signed_zero_vec",
4874 },
4875 /* .checks = */
4876 {
4877 "; CHECK-NOT: OpConstant",
4878 "; CHECK-NOT: OpSpecConstant",
4879 },
4880 },
4881
4882 // Add, sub, mul, div, rem.
4883 {
4884 /* .used_consts = */ {},
4885 /* .main_insts = */ {},
4886 /* .dead_consts = */
4887 {
4888 "%dead_spec_int_a = OpSpecConstant %int 1",
4889 "%dead_spec_int_a_vec = OpSpecConstantComposite %v2int %dead_spec_int_a %dead_spec_int_a",
4890
4891 "%dead_spec_int_b = OpSpecConstant %int 2",
4892 "%dead_spec_int_b_vec = OpSpecConstantComposite %v2int %dead_spec_int_b %dead_spec_int_b",
4893
4894 "%dead_const_int_c = OpConstant %int 3",
4895 "%dead_const_int_c_vec = OpConstantComposite %v2int %dead_const_int_c %dead_const_int_c",
4896
4897 // Add
4898 "%add_a_b = OpSpecConstantOp %int IAdd %dead_spec_int_a %dead_spec_int_b",
4899 "%add_a_b_vec = OpSpecConstantOp %v2int IAdd %dead_spec_int_a_vec %dead_spec_int_b_vec",
4900
4901 // Sub
4902 "%sub_a_b = OpSpecConstantOp %int ISub %dead_spec_int_a %dead_spec_int_b",
4903 "%sub_a_b_vec = OpSpecConstantOp %v2int ISub %dead_spec_int_a_vec %dead_spec_int_b_vec",
4904
4905 // Mul
4906 "%mul_a_b = OpSpecConstantOp %int IMul %dead_spec_int_a %dead_spec_int_b",
4907 "%mul_a_b_vec = OpSpecConstantOp %v2int IMul %dead_spec_int_a_vec %dead_spec_int_b_vec",
4908
4909 // Div
4910 "%div_a_b = OpSpecConstantOp %int SDiv %dead_spec_int_a %dead_spec_int_b",
4911 "%div_a_b_vec = OpSpecConstantOp %v2int SDiv %dead_spec_int_a_vec %dead_spec_int_b_vec",
4912
4913 // Bitwise Xor
4914 "%xor_a_b = OpSpecConstantOp %int BitwiseXor %dead_spec_int_a %dead_spec_int_b",
4915 "%xor_a_b_vec = OpSpecConstantOp %v2int BitwiseXor %dead_spec_int_a_vec %dead_spec_int_b_vec",
4916
4917 // Scalar Comparison
4918 "%less_a_b = OpSpecConstantOp %bool SLessThan %dead_spec_int_a %dead_spec_int_b",
4919 },
4920 /* .checks = */
4921 {
4922 "; CHECK-NOT: OpConstant",
4923 "; CHECK-NOT: OpSpecConstant",
4924 },
4925 },
4926
4927 // Vectors without used swizzles should be removed.
4928 {
4929 /* .used_consts = */
4930 {
4931 "%used_int = OpConstant %int 3",
4932 },
4933 /* .main_insts = */
4934 {
4935 "%int_var = OpVariable %_pf_int Output",
4936 "OpStore %int_var %used_int",
4937 },
4938 /* .dead_consts = */
4939 {
4940 "%dead_int = OpConstant %int 3",
4941
4942 "%dead_spec_int_a = OpSpecConstant %int 1",
4943 "%vec_a = OpSpecConstantComposite %v4int %dead_spec_int_a %dead_spec_int_a %dead_int %dead_int",
4944
4945 "%dead_spec_int_b = OpSpecConstant %int 2",
4946 "%vec_b = OpSpecConstantComposite %v4int %dead_spec_int_b %dead_spec_int_b %used_int %used_int",
4947
4948 // Extract scalar
4949 "%a_x = OpSpecConstantOp %int CompositeExtract %vec_a 0",
4950 "%b_x = OpSpecConstantOp %int CompositeExtract %vec_b 0",
4951
4952 // Extract vector
4953 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1",
4954 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1",
4955 },
4956 /* .checks = */
4957 {
4958 "; CHECK: [[int:%\\w+]] = OpConstant %int 3",
4959 "; CHECK-NOT: OpConstant",
4960 "; CHECK-NOT: OpSpecConstant",
4961 "; CHECK: OpStore {{%\\w+}} [[int]]",
4962 },
4963 },
4964 // Vectors with used swizzles should not be removed.
4965 {
4966 /* .used_consts = */
4967 {
4968 "%used_int = OpConstant %int 3",
4969 "%used_spec_int_a = OpSpecConstant %int 1",
4970 "%used_spec_int_b = OpSpecConstant %int 2",
4971 // Create vectors
4972 "%vec_a = OpSpecConstantComposite %v4int %used_spec_int_a %used_spec_int_a %used_int %used_int",
4973 "%vec_b = OpSpecConstantComposite %v4int %used_spec_int_b %used_spec_int_b %used_int %used_int",
4974 // Extract vector
4975 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1",
4976 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1",
4977 },
4978 /* .main_insts = */
4979 {
4980 "%v2int_var_a = OpVariable %_pf_v2int Output",
4981 "%v2int_var_b = OpVariable %_pf_v2int Output",
4982 "OpStore %v2int_var_a %a_xy",
4983 "OpStore %v2int_var_b %b_xy",
4984 },
4985 /* .dead_consts = */ {},
4986 /* .checks = */
4987 {
4988 "; CHECK: [[int:%\\w+]] = OpConstant %int 3",
4989 "; CHECK: [[a:%\\w+]] = OpSpecConstant %int 1",
4990 "; CHECK: [[b:%\\w+]] = OpSpecConstant %int 2",
4991 "; CHECK: [[veca:%\\w+]] = OpSpecConstantComposite %v4int [[a]] [[a]] [[int]] [[int]]",
4992 "; CHECK: [[vecb:%\\w+]] = OpSpecConstantComposite %v4int [[b]] [[b]] [[int]] [[int]]",
4993 "; CHECK: [[exa:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[veca]] [[veca]] 0 1",
4994 "; CHECK: [[exb:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[vecb]] [[vecb]] 0 1",
4995 "; CHECK-NOT: OpConstant",
4996 "; CHECK-NOT: OpSpecConstant",
4997 "; CHECK: OpStore {{%\\w+}} [[exa]]",
4998 "; CHECK: OpStore {{%\\w+}} [[exb]]",
4999 },
5000 },
5001 // clang-format on
5002 })));
5003
5004 INSTANTIATE_TEST_SUITE_P(
5005 LongDefUseChain, AggressiveEliminateDeadConstantTest,
5006 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({
5007 // clang-format off
5008 // Long Def-Use chain with binary operations.
5009 {
5010 /* .used_consts = */
5011 {
5012 "%array_size = OpConstant %int 4",
5013 "%type_arr_int_4 = OpTypeArray %int %array_size",
5014 "%used_int_0 = OpConstant %int 100",
5015 "%used_int_1 = OpConstant %int 1",
5016 "%used_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_1",
5017 "%used_int_3 = OpSpecConstantOp %int ISub %used_int_0 %used_int_2",
5018 "%used_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_3",
5019 "%used_int_5 = OpSpecConstantOp %int ISub %used_int_0 %used_int_4",
5020 "%used_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_5",
5021 "%used_int_7 = OpSpecConstantOp %int ISub %used_int_0 %used_int_6",
5022 "%used_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_7",
5023 "%used_int_9 = OpSpecConstantOp %int ISub %used_int_0 %used_int_8",
5024 "%used_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_9",
5025 "%used_int_11 = OpSpecConstantOp %int ISub %used_int_0 %used_int_10",
5026 "%used_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_11",
5027 "%used_int_13 = OpSpecConstantOp %int ISub %used_int_0 %used_int_12",
5028 "%used_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_13",
5029 "%used_int_15 = OpSpecConstantOp %int ISub %used_int_0 %used_int_14",
5030 "%used_int_16 = OpSpecConstantOp %int ISub %used_int_0 %used_int_15",
5031 "%used_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_16",
5032 "%used_int_18 = OpSpecConstantOp %int ISub %used_int_0 %used_int_17",
5033 "%used_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_18",
5034 "%used_int_20 = OpSpecConstantOp %int ISub %used_int_0 %used_int_19",
5035 "%used_vec_a = OpSpecConstantComposite %v2int %used_int_18 %used_int_19",
5036 "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a",
5037 "%used_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0",
5038 "%used_array = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21",
5039 },
5040 /* .main_insts = */
5041 {
5042 "%int_var = OpVariable %_pf_int Output",
5043 "%used_array_2 = OpCompositeExtract %int %used_array 2",
5044 "OpStore %int_var %used_array_2",
5045 },
5046 /* .dead_consts = */
5047 {
5048 "%dead_int_1 = OpConstant %int 2",
5049 "%dead_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_1",
5050 "%dead_int_3 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_2",
5051 "%dead_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_3",
5052 "%dead_int_5 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_4",
5053 "%dead_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_5",
5054 "%dead_int_7 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_6",
5055 "%dead_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_7",
5056 "%dead_int_9 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_8",
5057 "%dead_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_9",
5058 "%dead_int_11 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_10",
5059 "%dead_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_11",
5060 "%dead_int_13 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_12",
5061 "%dead_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_13",
5062 "%dead_int_15 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_14",
5063 "%dead_int_16 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_15",
5064 "%dead_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_16",
5065 "%dead_int_18 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_17",
5066 "%dead_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_18",
5067 "%dead_int_20 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_19",
5068 "%dead_vec_a = OpSpecConstantComposite %v2int %dead_int_18 %dead_int_19",
5069 "%dead_vec_b = OpSpecConstantOp %v2int IMul %dead_vec_a %dead_vec_a",
5070 "%dead_int_21 = OpSpecConstantOp %int CompositeExtract %dead_vec_b 0",
5071 "%dead_array = OpConstantComposite %type_arr_int_4 %dead_int_20 %used_int_20 %dead_int_19 %used_int_19",
5072 },
5073 /* .checks = */
5074 {
5075 "; CHECK: OpConstant %int 4",
5076 "; CHECK: [[array:%\\w+]] = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21",
5077 "; CHECK-NOT: OpConstant",
5078 "; CHECK-NOT: OpSpecConstant",
5079 "; CHECK: OpStore {{%\\w+}} [[array]]",
5080 },
5081 },
5082 // Long Def-Use chain with swizzle
5083 // clang-format on
5084 })));
5085
TEST_F(AggressiveDCETest,DeadDecorationGroup)5086 TEST_F(AggressiveDCETest, DeadDecorationGroup) {
5087 // The decoration group should be eliminated because the target of group
5088 // decorate is dead.
5089 const std::string text = R"(
5090 ; CHECK-NOT: OpDecorat
5091 ; CHECK-NOT: OpGroupDecorate
5092 OpCapability Shader
5093 OpMemoryModel Logical GLSL450
5094 OpEntryPoint Fragment %main "main"
5095 OpExecutionMode %main OriginUpperLeft
5096 OpDecorate %1 Restrict
5097 OpDecorate %1 Aliased
5098 %1 = OpDecorationGroup
5099 OpGroupDecorate %1 %var
5100 %void = OpTypeVoid
5101 %func = OpTypeFunction %void
5102 %uint = OpTypeInt 32 0
5103 %uint_ptr = OpTypePointer Function %uint
5104 %main = OpFunction %void None %func
5105 %2 = OpLabel
5106 %var = OpVariable %uint_ptr Function
5107 OpReturn
5108 OpFunctionEnd
5109 )";
5110
5111 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5112 }
5113
TEST_F(AggressiveDCETest,DeadDecorationGroupAndValidDecorationMgr)5114 TEST_F(AggressiveDCETest, DeadDecorationGroupAndValidDecorationMgr) {
5115 // The decoration group should be eliminated because the target of group
5116 // decorate is dead.
5117 const std::string text = R"(
5118 OpCapability Shader
5119 OpMemoryModel Logical GLSL450
5120 OpEntryPoint Fragment %main "main"
5121 OpExecutionMode %main OriginUpperLeft
5122 OpDecorate %1 Restrict
5123 OpDecorate %1 Aliased
5124 %1 = OpDecorationGroup
5125 OpGroupDecorate %1 %var
5126 %void = OpTypeVoid
5127 %func = OpTypeFunction %void
5128 %uint = OpTypeInt 32 0
5129 %uint_ptr = OpTypePointer Function %uint
5130 %main = OpFunction %void None %func
5131 %2 = OpLabel
5132 %var = OpVariable %uint_ptr Function
5133 OpReturn
5134 OpFunctionEnd
5135 )";
5136
5137 auto pass = MakeUnique<AggressiveDCEPass>();
5138 auto consumer = [](spv_message_level_t, const char*, const spv_position_t&,
5139 const char* message) {
5140 std::cerr << message << std::endl;
5141 };
5142 auto context = BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, text);
5143
5144 // Build the decoration manager before the pass.
5145 context->get_decoration_mgr();
5146
5147 const auto status = pass->Run(context.get());
5148 EXPECT_EQ(status, Pass::Status::SuccessWithChange);
5149 }
5150
TEST_F(AggressiveDCETest,ParitallyDeadDecorationGroup)5151 TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroup) {
5152 const std::string text = R"(
5153 ; CHECK: OpDecorate [[grp:%\w+]] Restrict
5154 ; CHECK: [[grp]] = OpDecorationGroup
5155 ; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]]
5156 ; CHECK: [[output]] = OpVariable {{%\w+}} Output
5157 ; CHECK-NOT: OpVariable {{%\w+}} Function
5158 OpCapability Shader
5159 OpMemoryModel Logical GLSL450
5160 OpEntryPoint Fragment %main "main" %output
5161 OpExecutionMode %main OriginUpperLeft
5162 OpDecorate %1 Restrict
5163 %1 = OpDecorationGroup
5164 OpGroupDecorate %1 %var %output
5165 %void = OpTypeVoid
5166 %func = OpTypeFunction %void
5167 %uint = OpTypeInt 32 0
5168 %uint_ptr_Function = OpTypePointer Function %uint
5169 %uint_ptr_Output = OpTypePointer Output %uint
5170 %uint_0 = OpConstant %uint 0
5171 %output = OpVariable %uint_ptr_Output Output
5172 %main = OpFunction %void None %func
5173 %2 = OpLabel
5174 %var = OpVariable %uint_ptr_Function Function
5175 OpStore %output %uint_0
5176 OpReturn
5177 OpFunctionEnd
5178 )";
5179
5180 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5181 }
5182
TEST_F(AggressiveDCETest,ParitallyDeadDecorationGroupDifferentGroupDecorate)5183 TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroupDifferentGroupDecorate) {
5184 const std::string text = R"(
5185 ; CHECK: OpDecorate [[grp:%\w+]] Restrict
5186 ; CHECK: [[grp]] = OpDecorationGroup
5187 ; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]]
5188 ; CHECK-NOT: OpGroupDecorate
5189 ; CHECK: [[output]] = OpVariable {{%\w+}} Output
5190 ; CHECK-NOT: OpVariable {{%\w+}} Function
5191 OpCapability Shader
5192 OpMemoryModel Logical GLSL450
5193 OpEntryPoint Fragment %main "main" %output
5194 OpExecutionMode %main OriginUpperLeft
5195 OpDecorate %1 Restrict
5196 %1 = OpDecorationGroup
5197 OpGroupDecorate %1 %output
5198 OpGroupDecorate %1 %var
5199 %void = OpTypeVoid
5200 %func = OpTypeFunction %void
5201 %uint = OpTypeInt 32 0
5202 %uint_ptr_Function = OpTypePointer Function %uint
5203 %uint_ptr_Output = OpTypePointer Output %uint
5204 %uint_0 = OpConstant %uint 0
5205 %output = OpVariable %uint_ptr_Output Output
5206 %main = OpFunction %void None %func
5207 %2 = OpLabel
5208 %var = OpVariable %uint_ptr_Function Function
5209 OpStore %output %uint_0
5210 OpReturn
5211 OpFunctionEnd
5212 )";
5213
5214 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5215 }
5216
TEST_F(AggressiveDCETest,DeadGroupMemberDecorate)5217 TEST_F(AggressiveDCETest, DeadGroupMemberDecorate) {
5218 const std::string text = R"(
5219 ; CHECK-NOT: OpDec
5220 ; CHECK-NOT: OpGroup
5221 OpCapability Shader
5222 OpMemoryModel Logical GLSL450
5223 OpEntryPoint Fragment %main "main"
5224 OpExecutionMode %main OriginUpperLeft
5225 OpDecorate %1 Offset 0
5226 OpDecorate %1 Uniform
5227 %1 = OpDecorationGroup
5228 OpGroupMemberDecorate %1 %var 0
5229 %void = OpTypeVoid
5230 %func = OpTypeFunction %void
5231 %uint = OpTypeInt 32 0
5232 %struct = OpTypeStruct %uint %uint
5233 %struct_ptr = OpTypePointer Function %struct
5234 %main = OpFunction %void None %func
5235 %2 = OpLabel
5236 %var = OpVariable %struct_ptr Function
5237 OpReturn
5238 OpFunctionEnd
5239 )";
5240
5241 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5242 }
5243
TEST_F(AggressiveDCETest,PartiallyDeadGroupMemberDecorate)5244 TEST_F(AggressiveDCETest, PartiallyDeadGroupMemberDecorate) {
5245 const std::string text = R"(
5246 ; CHECK: OpDecorate [[grp:%\w+]] Offset 0
5247 ; CHECK: OpDecorate [[grp]] RelaxedPrecision
5248 ; CHECK: [[grp]] = OpDecorationGroup
5249 ; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1
5250 ; CHECK: [[output]] = OpTypeStruct
5251 ; CHECK-NOT: OpTypeStruct
5252 OpCapability Shader
5253 OpMemoryModel Logical GLSL450
5254 OpEntryPoint Fragment %main "main" %output
5255 OpExecutionMode %main OriginUpperLeft
5256 OpDecorate %1 Offset 0
5257 OpDecorate %1 RelaxedPrecision
5258 %1 = OpDecorationGroup
5259 OpGroupMemberDecorate %1 %var_struct 0 %output_struct 1
5260 %void = OpTypeVoid
5261 %func = OpTypeFunction %void
5262 %uint = OpTypeInt 32 0
5263 %var_struct = OpTypeStruct %uint %uint
5264 %output_struct = OpTypeStruct %uint %uint
5265 %struct_ptr_Function = OpTypePointer Function %var_struct
5266 %struct_ptr_Output = OpTypePointer Output %output_struct
5267 %uint_ptr_Output = OpTypePointer Output %uint
5268 %output = OpVariable %struct_ptr_Output Output
5269 %uint_0 = OpConstant %uint 0
5270 %main = OpFunction %void None %func
5271 %2 = OpLabel
5272 %var = OpVariable %struct_ptr_Function Function
5273 %3 = OpAccessChain %uint_ptr_Output %output %uint_0
5274 OpStore %3 %uint_0
5275 OpReturn
5276 OpFunctionEnd
5277 )";
5278
5279 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5280 }
5281
TEST_F(AggressiveDCETest,PartiallyDeadGroupMemberDecorateDifferentGroupDecorate)5282 TEST_F(AggressiveDCETest,
5283 PartiallyDeadGroupMemberDecorateDifferentGroupDecorate) {
5284 const std::string text = R"(
5285 ; CHECK: OpDecorate [[grp:%\w+]] Offset 0
5286 ; CHECK: OpDecorate [[grp]] RelaxedPrecision
5287 ; CHECK: [[grp]] = OpDecorationGroup
5288 ; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1
5289 ; CHECK-NOT: OpGroupMemberDecorate
5290 ; CHECK: [[output]] = OpTypeStruct
5291 ; CHECK-NOT: OpTypeStruct
5292 OpCapability Shader
5293 OpMemoryModel Logical GLSL450
5294 OpEntryPoint Fragment %main "main" %output
5295 OpExecutionMode %main OriginUpperLeft
5296 OpDecorate %1 Offset 0
5297 OpDecorate %1 RelaxedPrecision
5298 %1 = OpDecorationGroup
5299 OpGroupMemberDecorate %1 %var_struct 0
5300 OpGroupMemberDecorate %1 %output_struct 1
5301 %void = OpTypeVoid
5302 %func = OpTypeFunction %void
5303 %uint = OpTypeInt 32 0
5304 %var_struct = OpTypeStruct %uint %uint
5305 %output_struct = OpTypeStruct %uint %uint
5306 %struct_ptr_Function = OpTypePointer Function %var_struct
5307 %struct_ptr_Output = OpTypePointer Output %output_struct
5308 %uint_ptr_Output = OpTypePointer Output %uint
5309 %output = OpVariable %struct_ptr_Output Output
5310 %uint_0 = OpConstant %uint 0
5311 %main = OpFunction %void None %func
5312 %2 = OpLabel
5313 %var = OpVariable %struct_ptr_Function Function
5314 %3 = OpAccessChain %uint_ptr_Output %output %uint_0
5315 OpStore %3 %uint_0
5316 OpReturn
5317 OpFunctionEnd
5318 )";
5319
5320 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5321 }
5322
5323 // Test for #1404
TEST_F(AggressiveDCETest,DontRemoveWorkgroupSize)5324 TEST_F(AggressiveDCETest, DontRemoveWorkgroupSize) {
5325 const std::string text = R"(
5326 ; CHECK: OpDecorate [[wgs:%\w+]] BuiltIn WorkgroupSize
5327 ; CHECK: [[wgs]] = OpSpecConstantComposite
5328 OpCapability Shader
5329 OpMemoryModel Logical GLSL450
5330 OpEntryPoint GLCompute %func "func"
5331 OpExecutionMode %func LocalSize 1 1 1
5332 OpDecorate %1 BuiltIn WorkgroupSize
5333 %void = OpTypeVoid
5334 %int = OpTypeInt 32 0
5335 %functy = OpTypeFunction %void
5336 %v3int = OpTypeVector %int 3
5337 %2 = OpSpecConstant %int 1
5338 %1 = OpSpecConstantComposite %v3int %2 %2 %2
5339 %func = OpFunction %void None %functy
5340 %3 = OpLabel
5341 OpReturn
5342 OpFunctionEnd
5343 )";
5344
5345 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
5346 }
5347
5348 // Test for #1214
TEST_F(AggressiveDCETest,LoopHeaderIsAlsoAnotherLoopMerge)5349 TEST_F(AggressiveDCETest, LoopHeaderIsAlsoAnotherLoopMerge) {
5350 const std::string text = R"(OpCapability Shader
5351 OpMemoryModel Logical GLSL450
5352 OpEntryPoint Fragment %1 "func" %2
5353 OpExecutionMode %1 OriginUpperLeft
5354 %void = OpTypeVoid
5355 %bool = OpTypeBool
5356 %true = OpConstantTrue %bool
5357 %uint = OpTypeInt 32 0
5358 %_ptr_Output_uint = OpTypePointer Output %uint
5359 %2 = OpVariable %_ptr_Output_uint Output
5360 %uint_0 = OpConstant %uint 0
5361 %9 = OpTypeFunction %void
5362 %1 = OpFunction %void None %9
5363 %10 = OpLabel
5364 OpBranch %11
5365 %11 = OpLabel
5366 OpLoopMerge %12 %13 None
5367 OpBranchConditional %true %14 %13
5368 %14 = OpLabel
5369 OpStore %2 %uint_0
5370 OpLoopMerge %15 %16 None
5371 OpBranchConditional %true %15 %16
5372 %16 = OpLabel
5373 OpBranch %14
5374 %15 = OpLabel
5375 OpBranchConditional %true %12 %13
5376 %13 = OpLabel
5377 OpBranch %11
5378 %12 = OpLabel
5379 %17 = OpPhi %uint %uint_0 %15 %uint_0 %18
5380 OpStore %2 %17
5381 OpLoopMerge %19 %18 None
5382 OpBranchConditional %true %19 %18
5383 %18 = OpLabel
5384 OpBranch %12
5385 %19 = OpLabel
5386 OpReturn
5387 OpFunctionEnd
5388 )";
5389
5390 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5391 }
5392
TEST_F(AggressiveDCETest,BreaksDontVisitPhis)5393 TEST_F(AggressiveDCETest, BreaksDontVisitPhis) {
5394 const std::string text = R"(
5395 OpCapability Shader
5396 OpMemoryModel Logical GLSL450
5397 OpEntryPoint Fragment %func "func" %var
5398 OpExecutionMode %func OriginUpperLeft
5399 %void = OpTypeVoid
5400 %bool = OpTypeBool
5401 %true = OpConstantTrue %bool
5402 %int = OpTypeInt 32 0
5403 %int_ptr_Output = OpTypePointer Output %int
5404 %var = OpVariable %int_ptr_Output Output
5405 %int0 = OpConstant %int 0
5406 %functy = OpTypeFunction %void
5407 %func = OpFunction %void None %functy
5408 %entry = OpLabel
5409 OpBranch %outer_header
5410 %outer_header = OpLabel
5411 OpLoopMerge %outer_merge %outer_continue None
5412 OpBranchConditional %true %inner_header %outer_continue
5413 %inner_header = OpLabel
5414 %phi = OpPhi %int %int0 %outer_header %int0 %inner_continue
5415 OpStore %var %phi
5416 OpLoopMerge %inner_merge %inner_continue None
5417 OpBranchConditional %true %inner_merge %inner_continue
5418 %inner_continue = OpLabel
5419 OpBranch %inner_header
5420 %inner_merge = OpLabel
5421 OpBranch %outer_continue
5422 %outer_continue = OpLabel
5423 %p = OpPhi %int %int0 %outer_header %int0 %inner_merge
5424 OpStore %var %p
5425 OpBranch %outer_header
5426 %outer_merge = OpLabel
5427 OpReturn
5428 OpFunctionEnd
5429 )";
5430
5431 EXPECT_EQ(Pass::Status::SuccessWithoutChange,
5432 std::get<1>(SinglePassRunAndDisassemble<AggressiveDCEPass>(
5433 text, false, true)));
5434 }
5435
5436 // Test for #1212
TEST_F(AggressiveDCETest,ConstStoreInnerLoop)5437 TEST_F(AggressiveDCETest, ConstStoreInnerLoop) {
5438 const std::string text = R"(OpCapability Shader
5439 OpMemoryModel Logical GLSL450
5440 OpEntryPoint Vertex %1 "main" %2
5441 %void = OpTypeVoid
5442 %4 = OpTypeFunction %void
5443 %float = OpTypeFloat 32
5444 %bool = OpTypeBool
5445 %true = OpConstantTrue %bool
5446 %_ptr_Output_float = OpTypePointer Output %float
5447 %2 = OpVariable %_ptr_Output_float Output
5448 %float_3 = OpConstant %float 3
5449 %1 = OpFunction %void None %4
5450 %13 = OpLabel
5451 OpBranch %14
5452 %14 = OpLabel
5453 OpLoopMerge %15 %16 None
5454 OpBranchConditional %true %17 %15
5455 %17 = OpLabel
5456 OpStore %2 %float_3
5457 OpLoopMerge %18 %17 None
5458 OpBranchConditional %true %18 %17
5459 %18 = OpLabel
5460 OpBranch %15
5461 %16 = OpLabel
5462 OpBranch %14
5463 %15 = OpLabel
5464 OpBranch %20
5465 %20 = OpLabel
5466 OpReturn
5467 OpFunctionEnd
5468 )";
5469
5470 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5471 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5472 }
5473
5474 // Test for #1212
TEST_F(AggressiveDCETest,InnerLoopCopy)5475 TEST_F(AggressiveDCETest, InnerLoopCopy) {
5476 const std::string text = R"(OpCapability Shader
5477 OpMemoryModel Logical GLSL450
5478 OpEntryPoint Vertex %1 "main" %2 %3
5479 %void = OpTypeVoid
5480 %5 = OpTypeFunction %void
5481 %float = OpTypeFloat 32
5482 %bool = OpTypeBool
5483 %true = OpConstantTrue %bool
5484 %_ptr_Output_float = OpTypePointer Output %float
5485 %_ptr_Input_float = OpTypePointer Input %float
5486 %2 = OpVariable %_ptr_Output_float Output
5487 %3 = OpVariable %_ptr_Input_float Input
5488 %1 = OpFunction %void None %5
5489 %14 = OpLabel
5490 OpBranch %15
5491 %15 = OpLabel
5492 OpLoopMerge %16 %17 None
5493 OpBranchConditional %true %18 %16
5494 %18 = OpLabel
5495 %19 = OpLoad %float %3
5496 OpStore %2 %19
5497 OpLoopMerge %20 %18 None
5498 OpBranchConditional %true %20 %18
5499 %20 = OpLabel
5500 OpBranch %16
5501 %17 = OpLabel
5502 OpBranch %15
5503 %16 = OpLabel
5504 OpBranch %22
5505 %22 = OpLabel
5506 OpReturn
5507 OpFunctionEnd
5508 )";
5509
5510 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5511 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5512 }
5513
TEST_F(AggressiveDCETest,AtomicAdd)5514 TEST_F(AggressiveDCETest, AtomicAdd) {
5515 const std::string text = R"(OpCapability SampledBuffer
5516 OpCapability StorageImageExtendedFormats
5517 OpCapability ImageBuffer
5518 OpCapability Shader
5519 %1 = OpExtInstImport "GLSL.std.450"
5520 OpMemoryModel Logical GLSL450
5521 OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
5522 OpExecutionMode %2 LocalSize 64 1 1
5523 OpSource HLSL 600
5524 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
5525 OpDecorate %4 DescriptorSet 4
5526 OpDecorate %4 Binding 70
5527 %uint = OpTypeInt 32 0
5528 %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
5529 %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
5530 %_ptr_Private_6 = OpTypePointer Private %6
5531 %void = OpTypeVoid
5532 %10 = OpTypeFunction %void
5533 %uint_0 = OpConstant %uint 0
5534 %uint_1 = OpConstant %uint 1
5535 %v3uint = OpTypeVector %uint 3
5536 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
5537 %_ptr_Image_uint = OpTypePointer Image %uint
5538 %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
5539 %16 = OpVariable %_ptr_Private_6 Private
5540 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
5541 %2 = OpFunction %void None %10
5542 %17 = OpLabel
5543 %18 = OpLoad %6 %4
5544 OpStore %16 %18
5545 %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
5546 %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
5547 OpReturn
5548 OpFunctionEnd
5549 )";
5550
5551 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5552 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true);
5553 }
5554
TEST_F(AggressiveDCETest,SafelyRemoveDecorateString)5555 TEST_F(AggressiveDCETest, SafelyRemoveDecorateString) {
5556 const std::string preamble = R"(OpCapability Shader
5557 OpExtension "SPV_GOOGLE_hlsl_functionality1"
5558 OpMemoryModel Logical GLSL450
5559 OpEntryPoint Fragment %1 "main"
5560 OpExecutionMode %1 OriginUpperLeft
5561 )";
5562
5563 const std::string body_before =
5564 R"(OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "FOOBAR"
5565 %void = OpTypeVoid
5566 %4 = OpTypeFunction %void
5567 %uint = OpTypeInt 32 0
5568 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5569 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
5570 %1 = OpFunction %void None %4
5571 %7 = OpLabel
5572 OpReturn
5573 OpFunctionEnd
5574 )";
5575
5576 const std::string body_after = R"(%void = OpTypeVoid
5577 %4 = OpTypeFunction %void
5578 %1 = OpFunction %void None %4
5579 %7 = OpLabel
5580 OpReturn
5581 OpFunctionEnd
5582 )";
5583
5584 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5585 SinglePassRunAndCheck<AggressiveDCEPass>(preamble + body_before,
5586 preamble + body_after, true, true);
5587 }
5588
TEST_F(AggressiveDCETest,CopyMemoryToGlobal)5589 TEST_F(AggressiveDCETest, CopyMemoryToGlobal) {
5590 // |local| is loaded in an OpCopyMemory instruction. So the store must be
5591 // kept alive.
5592 const std::string test =
5593 R"(OpCapability Geometry
5594 %1 = OpExtInstImport "GLSL.std.450"
5595 OpMemoryModel Logical GLSL450
5596 OpEntryPoint Geometry %main "main" %global
5597 OpExecutionMode %main Triangles
5598 OpExecutionMode %main Invocations 1
5599 OpExecutionMode %main OutputTriangleStrip
5600 OpExecutionMode %main OutputVertices 5
5601 OpSource GLSL 440
5602 OpName %main "main"
5603 OpName %local "local"
5604 OpName %global "global"
5605 %void = OpTypeVoid
5606 %7 = OpTypeFunction %void
5607 %float = OpTypeFloat 32
5608 %v4float = OpTypeVector %float 4
5609 %12 = OpConstantNull %v4float
5610 %_ptr_Function_v4float = OpTypePointer Function %v4float
5611 %_ptr_Output_v4float = OpTypePointer Output %v4float
5612 %global = OpVariable %_ptr_Output_v4float Output
5613 %main = OpFunction %void None %7
5614 %19 = OpLabel
5615 %local = OpVariable %_ptr_Function_v4float Function
5616 OpStore %local %12
5617 OpCopyMemory %global %local
5618 OpEndPrimitive
5619 OpReturn
5620 OpFunctionEnd
5621 )";
5622
5623 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5624 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5625 }
5626
TEST_F(AggressiveDCETest,CopyMemoryToLocal)5627 TEST_F(AggressiveDCETest, CopyMemoryToLocal) {
5628 // Make sure the store to |local2| using OpCopyMemory is kept and keeps
5629 // |local1| alive.
5630 const std::string test =
5631 R"(OpCapability Geometry
5632 %1 = OpExtInstImport "GLSL.std.450"
5633 OpMemoryModel Logical GLSL450
5634 OpEntryPoint Geometry %main "main" %global
5635 OpExecutionMode %main Triangles
5636 OpExecutionMode %main Invocations 1
5637 OpExecutionMode %main OutputTriangleStrip
5638 OpExecutionMode %main OutputVertices 5
5639 OpSource GLSL 440
5640 OpName %main "main"
5641 OpName %local1 "local1"
5642 OpName %local2 "local2"
5643 OpName %global "global"
5644 %void = OpTypeVoid
5645 %7 = OpTypeFunction %void
5646 %float = OpTypeFloat 32
5647 %v4float = OpTypeVector %float 4
5648 %12 = OpConstantNull %v4float
5649 %_ptr_Function_v4float = OpTypePointer Function %v4float
5650 %_ptr_Output_v4float = OpTypePointer Output %v4float
5651 %global = OpVariable %_ptr_Output_v4float Output
5652 %main = OpFunction %void None %7
5653 %19 = OpLabel
5654 %local1 = OpVariable %_ptr_Function_v4float Function
5655 %local2 = OpVariable %_ptr_Function_v4float Function
5656 OpStore %local1 %12
5657 OpCopyMemory %local2 %local1
5658 OpCopyMemory %global %local2
5659 OpEndPrimitive
5660 OpReturn
5661 OpFunctionEnd
5662 )";
5663
5664 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5665 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5666 }
5667
TEST_F(AggressiveDCETest,RemoveCopyMemoryToLocal)5668 TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal) {
5669 // Test that we remove function scope variables that are stored to using
5670 // OpCopyMemory, but are never loaded. We can remove both |local1| and
5671 // |local2|.
5672 const std::string test =
5673 R"(OpCapability Geometry
5674 %1 = OpExtInstImport "GLSL.std.450"
5675 OpMemoryModel Logical GLSL450
5676 OpEntryPoint Geometry %main "main" %global
5677 OpExecutionMode %main Triangles
5678 OpExecutionMode %main Invocations 1
5679 OpExecutionMode %main OutputTriangleStrip
5680 OpExecutionMode %main OutputVertices 5
5681 OpSource GLSL 440
5682 OpName %main "main"
5683 OpName %local1 "local1"
5684 OpName %local2 "local2"
5685 OpName %global "global"
5686 %void = OpTypeVoid
5687 %7 = OpTypeFunction %void
5688 %float = OpTypeFloat 32
5689 %v4float = OpTypeVector %float 4
5690 %12 = OpConstantNull %v4float
5691 %_ptr_Function_v4float = OpTypePointer Function %v4float
5692 %_ptr_Output_v4float = OpTypePointer Output %v4float
5693 %global = OpVariable %_ptr_Output_v4float Output
5694 %main = OpFunction %void None %7
5695 %19 = OpLabel
5696 %local1 = OpVariable %_ptr_Function_v4float Function
5697 %local2 = OpVariable %_ptr_Function_v4float Function
5698 OpStore %local1 %12
5699 OpCopyMemory %local2 %local1
5700 OpEndPrimitive
5701 OpReturn
5702 OpFunctionEnd
5703 )";
5704
5705 const std::string result =
5706 R"(OpCapability Geometry
5707 %1 = OpExtInstImport "GLSL.std.450"
5708 OpMemoryModel Logical GLSL450
5709 OpEntryPoint Geometry %main "main" %global
5710 OpExecutionMode %main Triangles
5711 OpExecutionMode %main Invocations 1
5712 OpExecutionMode %main OutputTriangleStrip
5713 OpExecutionMode %main OutputVertices 5
5714 OpSource GLSL 440
5715 OpName %main "main"
5716 OpName %global "global"
5717 %void = OpTypeVoid
5718 %7 = OpTypeFunction %void
5719 %float = OpTypeFloat 32
5720 %v4float = OpTypeVector %float 4
5721 %_ptr_Output_v4float = OpTypePointer Output %v4float
5722 %global = OpVariable %_ptr_Output_v4float Output
5723 %main = OpFunction %void None %7
5724 %19 = OpLabel
5725 OpEndPrimitive
5726 OpReturn
5727 OpFunctionEnd
5728 )";
5729
5730 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5731 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true);
5732 }
5733
TEST_F(AggressiveDCETest,RemoveCopyMemoryToLocal2)5734 TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal2) {
5735 // We are able to remove "local2" because it is not loaded, but have to keep
5736 // the stores to "local1".
5737 const std::string test =
5738 R"(OpCapability Geometry
5739 %1 = OpExtInstImport "GLSL.std.450"
5740 OpMemoryModel Logical GLSL450
5741 OpEntryPoint Geometry %main "main" %global
5742 OpExecutionMode %main Triangles
5743 OpExecutionMode %main Invocations 1
5744 OpExecutionMode %main OutputTriangleStrip
5745 OpExecutionMode %main OutputVertices 5
5746 OpSource GLSL 440
5747 OpName %main "main"
5748 OpName %local1 "local1"
5749 OpName %local2 "local2"
5750 OpName %global "global"
5751 %void = OpTypeVoid
5752 %7 = OpTypeFunction %void
5753 %float = OpTypeFloat 32
5754 %v4float = OpTypeVector %float 4
5755 %12 = OpConstantNull %v4float
5756 %_ptr_Function_v4float = OpTypePointer Function %v4float
5757 %_ptr_Output_v4float = OpTypePointer Output %v4float
5758 %global = OpVariable %_ptr_Output_v4float Output
5759 %main = OpFunction %void None %7
5760 %19 = OpLabel
5761 %local1 = OpVariable %_ptr_Function_v4float Function
5762 %local2 = OpVariable %_ptr_Function_v4float Function
5763 OpStore %local1 %12
5764 OpCopyMemory %local2 %local1
5765 OpCopyMemory %global %local1
5766 OpEndPrimitive
5767 OpReturn
5768 OpFunctionEnd
5769 )";
5770
5771 const std::string result =
5772 R"(OpCapability Geometry
5773 %1 = OpExtInstImport "GLSL.std.450"
5774 OpMemoryModel Logical GLSL450
5775 OpEntryPoint Geometry %main "main" %global
5776 OpExecutionMode %main Triangles
5777 OpExecutionMode %main Invocations 1
5778 OpExecutionMode %main OutputTriangleStrip
5779 OpExecutionMode %main OutputVertices 5
5780 OpSource GLSL 440
5781 OpName %main "main"
5782 OpName %local1 "local1"
5783 OpName %global "global"
5784 %void = OpTypeVoid
5785 %7 = OpTypeFunction %void
5786 %float = OpTypeFloat 32
5787 %v4float = OpTypeVector %float 4
5788 %12 = OpConstantNull %v4float
5789 %_ptr_Function_v4float = OpTypePointer Function %v4float
5790 %_ptr_Output_v4float = OpTypePointer Output %v4float
5791 %global = OpVariable %_ptr_Output_v4float Output
5792 %main = OpFunction %void None %7
5793 %19 = OpLabel
5794 %local1 = OpVariable %_ptr_Function_v4float Function
5795 OpStore %local1 %12
5796 OpCopyMemory %global %local1
5797 OpEndPrimitive
5798 OpReturn
5799 OpFunctionEnd
5800 )";
5801
5802 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5803 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true);
5804 }
5805
TEST_F(AggressiveDCETest,StructuredIfWithConditionalExit)5806 TEST_F(AggressiveDCETest, StructuredIfWithConditionalExit) {
5807 // We are able to remove "local2" because it is not loaded, but have to keep
5808 // the stores to "local1".
5809 const std::string test =
5810 R"(OpCapability Shader
5811 %1 = OpExtInstImport "GLSL.std.450"
5812 OpMemoryModel Logical GLSL450
5813 OpEntryPoint Fragment %main "main"
5814 OpExecutionMode %main OriginUpperLeft
5815 OpSource GLSL 140
5816 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
5817 OpSourceExtension "GL_GOOGLE_include_directive"
5818 OpName %main "main"
5819 OpName %a "a"
5820 %void = OpTypeVoid
5821 %5 = OpTypeFunction %void
5822 %int = OpTypeInt 32 1
5823 %_ptr_Uniform_int = OpTypePointer Uniform %int
5824 %int_0 = OpConstant %int 0
5825 %bool = OpTypeBool
5826 %int_100 = OpConstant %int 100
5827 %int_1 = OpConstant %int 1
5828 %a = OpVariable %_ptr_Uniform_int Uniform
5829 %main = OpFunction %void None %5
5830 %12 = OpLabel
5831 %13 = OpLoad %int %a
5832 %14 = OpSGreaterThan %bool %13 %int_0
5833 OpSelectionMerge %15 None
5834 OpBranchConditional %14 %16 %15
5835 %16 = OpLabel
5836 %17 = OpLoad %int %a
5837 %18 = OpSLessThan %bool %17 %int_100
5838 OpBranchConditional %18 %19 %15
5839 %19 = OpLabel
5840 OpStore %a %int_1
5841 OpBranch %15
5842 %15 = OpLabel
5843 OpReturn
5844 OpFunctionEnd
5845 )";
5846
5847 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5848 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5849 }
5850
TEST_F(AggressiveDCETest,CountingLoopNotEliminated)5851 TEST_F(AggressiveDCETest, CountingLoopNotEliminated) {
5852 // #version 310 es
5853 //
5854 // precision highp float;
5855 // precision highp int;
5856 //
5857 // layout(location = 0) out vec4 _GLF_color;
5858 //
5859 // void main()
5860 // {
5861 // float data[1];
5862 // for (int c = 0; c < 1; c++) {
5863 // if (true) {
5864 // do {
5865 // for (int i = 0; i < 1; i++) {
5866 // data[i] = 1.0;
5867 // }
5868 // } while (false);
5869 // }
5870 // }
5871 // _GLF_color = vec4(data[0], 0.0, 0.0, 1.0);
5872 // }
5873 const std::string test =
5874 R"(OpCapability Shader
5875 %1 = OpExtInstImport "GLSL.std.450"
5876 OpMemoryModel Logical GLSL450
5877 OpEntryPoint Fragment %main "main" %_GLF_color
5878 OpExecutionMode %main OriginUpperLeft
5879 OpSource ESSL 310
5880 OpName %main "main"
5881 OpName %c "c"
5882 OpName %i "i"
5883 OpName %data "data"
5884 OpName %_GLF_color "_GLF_color"
5885 OpDecorate %_GLF_color Location 0
5886 %void = OpTypeVoid
5887 %8 = OpTypeFunction %void
5888 %int = OpTypeInt 32 1
5889 %_ptr_Function_int = OpTypePointer Function %int
5890 %int_0 = OpConstant %int 0
5891 %int_1 = OpConstant %int 1
5892 %bool = OpTypeBool
5893 %float = OpTypeFloat 32
5894 %uint = OpTypeInt 32 0
5895 %uint_1 = OpConstant %uint 1
5896 %_arr_float_uint_1 = OpTypeArray %float %uint_1
5897 %_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1
5898 %float_1 = OpConstant %float 1
5899 %_ptr_Function_float = OpTypePointer Function %float
5900 %false = OpConstantFalse %bool
5901 %v4float = OpTypeVector %float 4
5902 %_ptr_Output_v4float = OpTypePointer Output %v4float
5903 %_GLF_color = OpVariable %_ptr_Output_v4float Output
5904 %float_0 = OpConstant %float 0
5905 %main = OpFunction %void None %8
5906 %26 = OpLabel
5907 %c = OpVariable %_ptr_Function_int Function
5908 %i = OpVariable %_ptr_Function_int Function
5909 %data = OpVariable %_ptr_Function__arr_float_uint_1 Function
5910 OpStore %c %int_0
5911 OpBranch %27
5912 %27 = OpLabel
5913 OpLoopMerge %28 %29 None
5914 OpBranch %30
5915 %30 = OpLabel
5916 %31 = OpLoad %int %c
5917 %32 = OpSLessThan %bool %31 %int_1
5918 OpBranchConditional %32 %33 %28
5919 %33 = OpLabel
5920 OpBranch %34
5921 %34 = OpLabel
5922 OpBranch %35
5923 %35 = OpLabel
5924 OpLoopMerge %36 %37 None
5925 OpBranch %38
5926 %38 = OpLabel
5927 OpStore %i %int_0
5928 OpBranch %39
5929 %39 = OpLabel
5930 OpLoopMerge %40 %41 None
5931 OpBranch %42
5932 %42 = OpLabel
5933 %43 = OpLoad %int %i
5934 %44 = OpSLessThan %bool %43 %int_1
5935 OpBranchConditional %44 %46 %40
5936 %46 = OpLabel
5937 %47 = OpLoad %int %i
5938 %48 = OpAccessChain %_ptr_Function_float %data %47
5939 OpStore %48 %float_1
5940 OpBranch %41
5941 %41 = OpLabel
5942 %49 = OpLoad %int %i
5943 %50 = OpIAdd %int %49 %int_1
5944 OpStore %i %50
5945 OpBranch %39
5946 %40 = OpLabel
5947 OpBranch %37
5948 %37 = OpLabel
5949 OpBranchConditional %false %35 %36
5950 %36 = OpLabel
5951 OpBranch %45
5952 %45 = OpLabel
5953 OpBranch %29
5954 %29 = OpLabel
5955 %51 = OpLoad %int %c
5956 %52 = OpIAdd %int %51 %int_1
5957 OpStore %c %52
5958 OpBranch %27
5959 %28 = OpLabel
5960 %53 = OpAccessChain %_ptr_Function_float %data %int_0
5961 %54 = OpLoad %float %53
5962 %55 = OpCompositeConstruct %v4float %54 %float_0 %float_0 %float_1
5963 OpStore %_GLF_color %55
5964 OpReturn
5965 OpFunctionEnd
5966 )";
5967
5968 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
5969 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true);
5970 }
5971
TEST_F(AggressiveDCETest,EliminateLoopWithUnreachable)5972 TEST_F(AggressiveDCETest, EliminateLoopWithUnreachable) {
5973 // #version 430
5974 //
5975 // layout(std430) buffer U_t
5976 // {
5977 // float g_F[10];
5978 // float g_S;
5979 // };
5980 //
5981 // layout(location = 0)out float o;
5982 //
5983 // void main(void)
5984 // {
5985 // // Useless loop
5986 // for (int i = 0; i<10; i++) {
5987 // if (g_F[i] == 0.0)
5988 // break;
5989 // else
5990 // break;
5991 // // Unreachable merge block created here.
5992 // // Need to edit SPIR-V to change to OpUnreachable
5993 // }
5994 // o = g_S;
5995 // }
5996
5997 const std::string before =
5998 R"(OpCapability Shader
5999 %1 = OpExtInstImport "GLSL.std.450"
6000 OpMemoryModel Logical GLSL450
6001 OpEntryPoint Fragment %main "main" %o
6002 OpExecutionMode %main OriginUpperLeft
6003 OpSource GLSL 430
6004 OpName %main "main"
6005 OpName %i "i"
6006 OpName %U_t "U_t"
6007 OpMemberName %U_t 0 "g_F"
6008 OpMemberName %U_t 1 "g_S"
6009 OpName %_ ""
6010 OpName %o "o"
6011 OpDecorate %_arr_float_uint_10 ArrayStride 4
6012 OpMemberDecorate %U_t 0 Offset 0
6013 OpMemberDecorate %U_t 1 Offset 40
6014 OpDecorate %U_t BufferBlock
6015 OpDecorate %_ DescriptorSet 0
6016 OpDecorate %o Location 0
6017 %void = OpTypeVoid
6018 %9 = OpTypeFunction %void
6019 %int = OpTypeInt 32 1
6020 %_ptr_Function_int = OpTypePointer Function %int
6021 %int_0 = OpConstant %int 0
6022 %int_10 = OpConstant %int 10
6023 %bool = OpTypeBool
6024 %float = OpTypeFloat 32
6025 %uint = OpTypeInt 32 0
6026 %uint_10 = OpConstant %uint 10
6027 %_arr_float_uint_10 = OpTypeArray %float %uint_10
6028 %U_t = OpTypeStruct %_arr_float_uint_10 %float
6029 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
6030 %_ = OpVariable %_ptr_Uniform_U_t Uniform
6031 %_ptr_Uniform_float = OpTypePointer Uniform %float
6032 %float_0 = OpConstant %float 0
6033 %int_1 = OpConstant %int 1
6034 %_ptr_Output_float = OpTypePointer Output %float
6035 %o = OpVariable %_ptr_Output_float Output
6036 %main = OpFunction %void None %9
6037 %23 = OpLabel
6038 %i = OpVariable %_ptr_Function_int Function
6039 OpStore %i %int_0
6040 OpBranch %24
6041 %24 = OpLabel
6042 OpLoopMerge %25 %26 None
6043 OpBranch %27
6044 %27 = OpLabel
6045 %28 = OpLoad %int %i
6046 %29 = OpSLessThan %bool %28 %int_10
6047 OpBranchConditional %29 %30 %25
6048 %30 = OpLabel
6049 %31 = OpLoad %int %i
6050 %32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %31
6051 %33 = OpLoad %float %32
6052 %34 = OpFOrdEqual %bool %33 %float_0
6053 OpSelectionMerge %35 None
6054 OpBranchConditional %34 %36 %37
6055 %36 = OpLabel
6056 OpBranch %25
6057 %37 = OpLabel
6058 OpBranch %25
6059 %35 = OpLabel
6060 OpUnreachable
6061 %26 = OpLabel
6062 %38 = OpLoad %int %i
6063 %39 = OpIAdd %int %38 %int_1
6064 OpStore %i %39
6065 OpBranch %24
6066 %25 = OpLabel
6067 %40 = OpAccessChain %_ptr_Uniform_float %_ %int_1
6068 %41 = OpLoad %float %40
6069 OpStore %o %41
6070 OpReturn
6071 OpFunctionEnd
6072 )";
6073
6074 const std::string after =
6075 R"(OpCapability Shader
6076 %1 = OpExtInstImport "GLSL.std.450"
6077 OpMemoryModel Logical GLSL450
6078 OpEntryPoint Fragment %main "main" %o
6079 OpExecutionMode %main OriginUpperLeft
6080 OpSource GLSL 430
6081 OpName %main "main"
6082 OpName %U_t "U_t"
6083 OpMemberName %U_t 0 "g_F"
6084 OpMemberName %U_t 1 "g_S"
6085 OpName %_ ""
6086 OpName %o "o"
6087 OpDecorate %_arr_float_uint_10 ArrayStride 4
6088 OpMemberDecorate %U_t 0 Offset 0
6089 OpMemberDecorate %U_t 1 Offset 40
6090 OpDecorate %U_t BufferBlock
6091 OpDecorate %_ DescriptorSet 0
6092 OpDecorate %o Location 0
6093 %void = OpTypeVoid
6094 %9 = OpTypeFunction %void
6095 %int = OpTypeInt 32 1
6096 %float = OpTypeFloat 32
6097 %uint = OpTypeInt 32 0
6098 %uint_10 = OpConstant %uint 10
6099 %_arr_float_uint_10 = OpTypeArray %float %uint_10
6100 %U_t = OpTypeStruct %_arr_float_uint_10 %float
6101 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
6102 %_ = OpVariable %_ptr_Uniform_U_t Uniform
6103 %_ptr_Uniform_float = OpTypePointer Uniform %float
6104 %int_1 = OpConstant %int 1
6105 %_ptr_Output_float = OpTypePointer Output %float
6106 %o = OpVariable %_ptr_Output_float Output
6107 %main = OpFunction %void None %9
6108 %23 = OpLabel
6109 OpBranch %24
6110 %24 = OpLabel
6111 OpBranch %25
6112 %25 = OpLabel
6113 %40 = OpAccessChain %_ptr_Uniform_float %_ %int_1
6114 %41 = OpLoad %float %40
6115 OpStore %o %41
6116 OpReturn
6117 OpFunctionEnd
6118 )";
6119
6120 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6121 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true);
6122 }
6123
TEST_F(AggressiveDCETest,DeadHlslCounterBufferGOOGLE)6124 TEST_F(AggressiveDCETest, DeadHlslCounterBufferGOOGLE) {
6125 // We are able to remove "local2" because it is not loaded, but have to keep
6126 // the stores to "local1".
6127 const std::string test =
6128 R"(
6129 ; CHECK-NOT: OpDecorateId
6130 ; CHECK: [[var:%\w+]] = OpVariable
6131 ; CHECK-NOT: OpVariable
6132 ; CHECK: [[ac:%\w+]] = OpAccessChain {{%\w+}} [[var]]
6133 ; CHECK: OpStore [[ac]]
6134 OpCapability Shader
6135 OpExtension "SPV_GOOGLE_hlsl_functionality1"
6136 OpMemoryModel Logical GLSL450
6137 OpEntryPoint GLCompute %1 "main"
6138 OpExecutionMode %1 LocalSize 32 1 1
6139 OpSource HLSL 600
6140 OpDecorate %_runtimearr_v2float ArrayStride 8
6141 OpMemberDecorate %_struct_3 0 Offset 0
6142 OpDecorate %_struct_3 BufferBlock
6143 OpMemberDecorate %_struct_4 0 Offset 0
6144 OpDecorate %_struct_4 BufferBlock
6145 OpDecorateId %5 HlslCounterBufferGOOGLE %6
6146 OpDecorate %5 DescriptorSet 0
6147 OpDecorate %5 Binding 0
6148 OpDecorate %6 DescriptorSet 0
6149 OpDecorate %6 Binding 1
6150 %float = OpTypeFloat 32
6151 %v2float = OpTypeVector %float 2
6152 %_runtimearr_v2float = OpTypeRuntimeArray %v2float
6153 %_struct_3 = OpTypeStruct %_runtimearr_v2float
6154 %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
6155 %int = OpTypeInt 32 1
6156 %_struct_4 = OpTypeStruct %int
6157 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
6158 %void = OpTypeVoid
6159 %13 = OpTypeFunction %void
6160 %19 = OpConstantNull %v2float
6161 %int_0 = OpConstant %int 0
6162 %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
6163 %5 = OpVariable %_ptr_Uniform__struct_3 Uniform
6164 %6 = OpVariable %_ptr_Uniform__struct_4 Uniform
6165 %1 = OpFunction %void None %13
6166 %22 = OpLabel
6167 %23 = OpAccessChain %_ptr_Uniform_v2float %5 %int_0 %int_0
6168 OpStore %23 %19
6169 OpReturn
6170 OpFunctionEnd
6171 )";
6172
6173 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6174 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
6175 }
6176
TEST_F(AggressiveDCETest,Dead)6177 TEST_F(AggressiveDCETest, Dead) {
6178 // We are able to remove "local2" because it is not loaded, but have to keep
6179 // the stores to "local1".
6180 const std::string test =
6181 R"(
6182 ; CHECK: OpCapability
6183 ; CHECK-NOT: OpMemberDecorateStringGOOGLE
6184 ; CHECK: OpFunctionEnd
6185 OpCapability Shader
6186 OpExtension "SPV_GOOGLE_hlsl_functionality1"
6187 %1 = OpExtInstImport "GLSL.std.450"
6188 OpMemoryModel Logical GLSL450
6189 OpEntryPoint Vertex %VSMain "VSMain"
6190 OpSource HLSL 500
6191 OpName %VSMain "VSMain"
6192 OpName %PSInput "PSInput"
6193 OpMemberName %PSInput 0 "Pos"
6194 OpMemberName %PSInput 1 "uv"
6195 OpMemberDecorateStringGOOGLE %PSInput 0 HlslSemanticGOOGLE "SV_POSITION"
6196 OpMemberDecorateStringGOOGLE %PSInput 1 HlslSemanticGOOGLE "TEX_COORD"
6197 %void = OpTypeVoid
6198 %5 = OpTypeFunction %void
6199 %float = OpTypeFloat 32
6200 %v2float = OpTypeVector %float 2
6201 %v4float = OpTypeVector %float 4
6202 %PSInput = OpTypeStruct %v4float %v2float
6203 %VSMain = OpFunction %void None %5
6204 %9 = OpLabel
6205 OpReturn
6206 OpFunctionEnd
6207 )";
6208
6209 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6210 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
6211 }
6212
TEST_F(AggressiveDCETest,DeadInfiniteLoop)6213 TEST_F(AggressiveDCETest, DeadInfiniteLoop) {
6214 const std::string test = R"(
6215 ; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]]
6216 ; CHECK: [[block]] = OpLabel
6217 ; CHECK-NEXT: OpBranch [[block:%\w+]]
6218 ; CHECK: [[block]] = OpLabel
6219 ; CHECK-NEXT: OpBranch [[block:%\w+]]
6220 ; CHECK: [[block]] = OpLabel
6221 ; CHECK-NEXT: OpReturn
6222 OpCapability Shader
6223 OpMemoryModel Logical GLSL450
6224 OpEntryPoint Fragment %2 "main"
6225 OpExecutionMode %2 OriginUpperLeft
6226 %6 = OpTypeVoid
6227 %7 = OpTypeFunction %6
6228 %8 = OpTypeFloat 32
6229 %9 = OpTypeVector %8 3
6230 %10 = OpTypeFunction %9
6231 %11 = OpConstant %8 1
6232 %12 = OpConstantComposite %9 %11 %11 %11
6233 %13 = OpTypeInt 32 1
6234 %32 = OpUndef %13
6235 %2 = OpFunction %6 None %7
6236 %33 = OpLabel
6237 OpBranch %34
6238 %34 = OpLabel
6239 OpLoopMerge %35 %36 None
6240 OpBranch %37
6241 %37 = OpLabel
6242 %38 = OpFunctionCall %9 %39
6243 OpSelectionMerge %40 None
6244 OpSwitch %32 %40 14 %41 58 %42
6245 %42 = OpLabel
6246 OpBranch %43
6247 %43 = OpLabel
6248 OpLoopMerge %44 %45 None
6249 OpBranch %45
6250 %45 = OpLabel
6251 OpBranch %43
6252 %44 = OpLabel
6253 OpUnreachable
6254 %41 = OpLabel
6255 OpBranch %36
6256 %40 = OpLabel
6257 OpBranch %36
6258 %36 = OpLabel
6259 OpBranch %34
6260 %35 = OpLabel
6261 OpReturn
6262 OpFunctionEnd
6263 %39 = OpFunction %9 None %10
6264 %46 = OpLabel
6265 OpReturnValue %12
6266 OpFunctionEnd
6267 )";
6268
6269 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6270 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
6271 }
6272
TEST_F(AggressiveDCETest,DeadInfiniteLoopReturnValue)6273 TEST_F(AggressiveDCETest, DeadInfiniteLoopReturnValue) {
6274 const std::string test = R"(
6275 ; CHECK: [[vec3:%\w+]] = OpTypeVector
6276 ; CHECK: [[undef:%\w+]] = OpUndef [[vec3]]
6277 ; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]]
6278 ; CHECK: [[block]] = OpLabel
6279 ; CHECK-NEXT: OpBranch [[block:%\w+]]
6280 ; CHECK: [[block]] = OpLabel
6281 ; CHECK-NEXT: OpBranch [[block:%\w+]]
6282 ; CHECK: [[block]] = OpLabel
6283 ; CHECK-NEXT: OpReturnValue [[undef]]
6284 OpCapability Shader
6285 OpMemoryModel Logical GLSL450
6286 OpEntryPoint Fragment %2 "main"
6287 OpExecutionMode %2 OriginUpperLeft
6288 %6 = OpTypeVoid
6289 %7 = OpTypeFunction %6
6290 %8 = OpTypeFloat 32
6291 %9 = OpTypeVector %8 3
6292 %10 = OpTypeFunction %9
6293 %11 = OpConstant %8 1
6294 %12 = OpConstantComposite %9 %11 %11 %11
6295 %13 = OpTypeInt 32 1
6296 %32 = OpUndef %13
6297 %2 = OpFunction %6 None %7
6298 %entry = OpLabel
6299 %call = OpFunctionCall %9 %func
6300 OpReturn
6301 OpFunctionEnd
6302 %func = OpFunction %9 None %10
6303 %33 = OpLabel
6304 OpBranch %34
6305 %34 = OpLabel
6306 OpLoopMerge %35 %36 None
6307 OpBranch %37
6308 %37 = OpLabel
6309 %38 = OpFunctionCall %9 %39
6310 OpSelectionMerge %40 None
6311 OpSwitch %32 %40 14 %41 58 %42
6312 %42 = OpLabel
6313 OpBranch %43
6314 %43 = OpLabel
6315 OpLoopMerge %44 %45 None
6316 OpBranch %45
6317 %45 = OpLabel
6318 OpBranch %43
6319 %44 = OpLabel
6320 OpUnreachable
6321 %41 = OpLabel
6322 OpBranch %36
6323 %40 = OpLabel
6324 OpBranch %36
6325 %36 = OpLabel
6326 OpBranch %34
6327 %35 = OpLabel
6328 OpReturnValue %12
6329 OpFunctionEnd
6330 %39 = OpFunction %9 None %10
6331 %46 = OpLabel
6332 OpReturnValue %12
6333 OpFunctionEnd
6334 )";
6335
6336 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6337 SinglePassRunAndMatch<AggressiveDCEPass>(test, true);
6338 }
6339
TEST_F(AggressiveDCETest,TestVariablePointer)6340 TEST_F(AggressiveDCETest, TestVariablePointer) {
6341 const std::string before =
6342 R"(OpCapability Shader
6343 OpCapability VariablePointers
6344 %1 = OpExtInstImport "GLSL.std.450"
6345 OpMemoryModel Logical GLSL450
6346 OpEntryPoint GLCompute %2 "main"
6347 OpExecutionMode %2 LocalSize 1 1 1
6348 OpSource GLSL 450
6349 OpMemberDecorate %_struct_3 0 Offset 0
6350 OpDecorate %_struct_3 Block
6351 OpDecorate %4 DescriptorSet 0
6352 OpDecorate %4 Binding 0
6353 OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
6354 OpDecorate %_arr_int_int_128 ArrayStride 4
6355 %void = OpTypeVoid
6356 %8 = OpTypeFunction %void
6357 %int = OpTypeInt 32 1
6358 %int_128 = OpConstant %int 128
6359 %_arr_int_int_128 = OpTypeArray %int %int_128
6360 %_struct_3 = OpTypeStruct %_arr_int_int_128
6361 %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
6362 %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
6363 %bool = OpTypeBool
6364 %true = OpConstantTrue %bool
6365 %int_0 = OpConstant %int 0
6366 %int_1 = OpConstant %int 1
6367 %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
6368 %2 = OpFunction %void None %8
6369 %16 = OpLabel
6370 %17 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
6371 OpBranch %18
6372 %18 = OpLabel
6373 %19 = OpPhi %_ptr_StorageBuffer_int %17 %16 %20 %21
6374 OpLoopMerge %22 %21 None
6375 OpBranchConditional %true %23 %22
6376 %23 = OpLabel
6377 OpStore %19 %int_0
6378 OpBranch %21
6379 %21 = OpLabel
6380 %20 = OpPtrAccessChain %_ptr_StorageBuffer_int %19 %int_1
6381 OpBranch %18
6382 %22 = OpLabel
6383 OpReturn
6384 OpFunctionEnd
6385 )";
6386
6387 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6388 SinglePassRunAndCheck<AggressiveDCEPass>(before, before, true, true);
6389 }
6390
TEST_F(AggressiveDCETest,DeadInputInterfaceV13)6391 TEST_F(AggressiveDCETest, DeadInputInterfaceV13) {
6392 const std::string spirv = R"(
6393 ; CHECK: OpEntryPoint GLCompute %main "main" [[var:%\w+]]
6394 ; CHECK: [[var]] = OpVariable
6395 OpCapability Shader
6396 OpMemoryModel Logical GLSL450
6397 OpEntryPoint GLCompute %main "main" %dead
6398 OpExecutionMode %main LocalSize 1 1 1
6399 OpName %main "main"
6400 %void = OpTypeVoid
6401 %int = OpTypeInt 32 0
6402 %ptr_input_int = OpTypePointer Input %int
6403 %dead = OpVariable %ptr_input_int Input
6404 %void_fn = OpTypeFunction %void
6405 %main = OpFunction %void None %void_fn
6406 %entry = OpLabel
6407 OpReturn
6408 OpFunctionEnd
6409 )";
6410
6411 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3);
6412 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6413 }
6414
TEST_F(AggressiveDCETest,DeadInputInterfaceV14)6415 TEST_F(AggressiveDCETest, DeadInputInterfaceV14) {
6416 const std::string spirv = R"(
6417 ; CHECK: OpEntryPoint GLCompute %main "main" [[var:%\w+]]
6418 ; CHECK: [[var]] = OpVariable
6419 OpCapability Shader
6420 OpMemoryModel Logical GLSL450
6421 OpEntryPoint GLCompute %main "main" %dead
6422 OpExecutionMode %main LocalSize 1 1 1
6423 OpName %main "main"
6424 %void = OpTypeVoid
6425 %int = OpTypeInt 32 0
6426 %ptr_input_int = OpTypePointer Input %int
6427 %dead = OpVariable %ptr_input_int Input
6428 %void_fn = OpTypeFunction %void
6429 %main = OpFunction %void None %void_fn
6430 %entry = OpLabel
6431 OpReturn
6432 OpFunctionEnd
6433 )";
6434
6435 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6436 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6437 }
6438
TEST_F(AggressiveDCETest,DeadInterfaceV14)6439 TEST_F(AggressiveDCETest, DeadInterfaceV14) {
6440 const std::string spirv = R"(
6441 ; CHECK-NOT: OpEntryPoint GLCompute %main "main" %
6442 ; CHECK: OpEntryPoint GLCompute %main "main"
6443 ; CHECK-NOT: OpVariable
6444 OpCapability Shader
6445 OpMemoryModel Logical GLSL450
6446 OpEntryPoint GLCompute %main "main" %dead
6447 OpExecutionMode %main LocalSize 1 1 1
6448 OpName %main "main"
6449 %void = OpTypeVoid
6450 %int = OpTypeInt 32 0
6451 %ptr_private_int = OpTypePointer Private %int
6452 %dead = OpVariable %ptr_private_int Private
6453 %void_fn = OpTypeFunction %void
6454 %main = OpFunction %void None %void_fn
6455 %entry = OpLabel
6456 OpReturn
6457 OpFunctionEnd
6458 )";
6459
6460 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6461 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6462 }
6463
TEST_F(AggressiveDCETest,DeadInterfacesV14)6464 TEST_F(AggressiveDCETest, DeadInterfacesV14) {
6465 const std::string spirv = R"(
6466 ; CHECK: OpEntryPoint GLCompute %main "main" %live1 %live2
6467 ; CHECK-NOT: %dead
6468 OpCapability Shader
6469 OpMemoryModel Logical GLSL450
6470 OpEntryPoint GLCompute %main "main" %live1 %dead1 %dead2 %live2
6471 OpExecutionMode %main LocalSize 1 1 1
6472 OpName %main "main"
6473 OpName %live1 "live1"
6474 OpName %live2 "live2"
6475 OpName %dead1 "dead1"
6476 OpName %dead2 "dead2"
6477 %void = OpTypeVoid
6478 %int = OpTypeInt 32 0
6479 %int0 = OpConstant %int 0
6480 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
6481 %live1 = OpVariable %ptr_ssbo_int StorageBuffer
6482 %live2 = OpVariable %ptr_ssbo_int StorageBuffer
6483 %dead1 = OpVariable %ptr_ssbo_int StorageBuffer
6484 %dead2 = OpVariable %ptr_ssbo_int StorageBuffer
6485 %void_fn = OpTypeFunction %void
6486 %main = OpFunction %void None %void_fn
6487 %entry = OpLabel
6488 OpStore %live1 %int0
6489 OpStore %live2 %int0
6490 OpReturn
6491 OpFunctionEnd
6492 )";
6493
6494 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6495 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6496 }
6497
TEST_F(AggressiveDCETest,PreserveBindings)6498 TEST_F(AggressiveDCETest, PreserveBindings) {
6499 const std::string spirv = R"(
6500 ; CHECK: OpDecorate %unusedSampler DescriptorSet 0
6501 ; CHECK: OpDecorate %unusedSampler Binding 0
6502 OpCapability Shader
6503 %1 = OpExtInstImport "GLSL.std.450"
6504 OpMemoryModel Logical GLSL450
6505 OpEntryPoint Fragment %main "main"
6506 OpExecutionMode %main OriginUpperLeft
6507 OpSource GLSL 430
6508 OpName %main "main"
6509 OpName %unusedSampler "unusedSampler"
6510 OpDecorate %unusedSampler DescriptorSet 0
6511 OpDecorate %unusedSampler Binding 0
6512 %void = OpTypeVoid
6513 %5 = OpTypeFunction %void
6514 %float = OpTypeFloat 32
6515 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
6516 %8 = OpTypeSampledImage %7
6517 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
6518 %unusedSampler = OpVariable %_ptr_UniformConstant_8 UniformConstant
6519 %main = OpFunction %void None %5
6520 %10 = OpLabel
6521 OpReturn
6522 OpFunctionEnd
6523 )";
6524
6525 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6526
6527 OptimizerOptions()->preserve_bindings_ = true;
6528
6529 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6530 }
6531
TEST_F(AggressiveDCETest,PreserveSpecConstants)6532 TEST_F(AggressiveDCETest, PreserveSpecConstants) {
6533 const std::string spirv = R"(
6534 ; CHECK: OpName %specConstant "specConstant"
6535 ; CHECK: %specConstant = OpSpecConstant %int 0
6536 OpCapability Shader
6537 %1 = OpExtInstImport "GLSL.std.450"
6538 OpMemoryModel Logical GLSL450
6539 OpEntryPoint Fragment %main "main"
6540 OpExecutionMode %main OriginUpperLeft
6541 OpSource GLSL 430
6542 OpName %main "main"
6543 OpName %specConstant "specConstant"
6544 OpDecorate %specConstant SpecId 0
6545 %void = OpTypeVoid
6546 %3 = OpTypeFunction %void
6547 %int = OpTypeInt 32 1
6548 %specConstant = OpSpecConstant %int 0
6549 %main = OpFunction %void None %3
6550 %5 = OpLabel
6551 OpReturn
6552 OpFunctionEnd
6553 )";
6554
6555 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6556
6557 OptimizerOptions()->preserve_spec_constants_ = true;
6558
6559 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6560 }
6561
TEST_F(AggressiveDCETest,LiveDecorateId)6562 TEST_F(AggressiveDCETest, LiveDecorateId) {
6563 const std::string spirv = R"(OpCapability Shader
6564 OpMemoryModel Logical GLSL450
6565 OpEntryPoint GLCompute %1 "main" %2
6566 OpExecutionMode %1 LocalSize 8 1 1
6567 OpDecorate %2 DescriptorSet 0
6568 OpDecorate %2 Binding 0
6569 OpDecorateId %3 UniformId %uint_2
6570 %void = OpTypeVoid
6571 %uint = OpTypeInt 32 0
6572 %uint_2 = OpConstant %uint 2
6573 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
6574 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
6575 %8 = OpTypeFunction %void
6576 %1 = OpFunction %void None %8
6577 %9 = OpLabel
6578 %3 = OpLoad %uint %2
6579 OpStore %2 %3
6580 OpReturn
6581 OpFunctionEnd
6582 )";
6583
6584 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6585 OptimizerOptions()->preserve_spec_constants_ = true;
6586 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
6587 }
6588
TEST_F(AggressiveDCETest,LiveDecorateIdOnGroup)6589 TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) {
6590 const std::string spirv = R"(OpCapability Shader
6591 OpMemoryModel Logical GLSL450
6592 OpEntryPoint GLCompute %1 "main" %2
6593 OpExecutionMode %1 LocalSize 8 1 1
6594 OpDecorate %2 DescriptorSet 0
6595 OpDecorate %2 Binding 0
6596 OpDecorateId %3 UniformId %uint_2
6597 %3 = OpDecorationGroup
6598 OpGroupDecorate %3 %5
6599 %void = OpTypeVoid
6600 %uint = OpTypeInt 32 0
6601 %uint_2 = OpConstant %uint 2
6602 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
6603 %2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
6604 %9 = OpTypeFunction %void
6605 %1 = OpFunction %void None %9
6606 %10 = OpLabel
6607 %5 = OpLoad %uint %2
6608 OpStore %2 %5
6609 OpReturn
6610 OpFunctionEnd
6611 )";
6612
6613 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
6614 OptimizerOptions()->preserve_spec_constants_ = true;
6615 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
6616 }
6617
TEST_F(AggressiveDCETest,NoEliminateForwardPointer)6618 TEST_F(AggressiveDCETest, NoEliminateForwardPointer) {
6619 // clang-format off
6620 //
6621 // #version 450
6622 // #extension GL_EXT_buffer_reference : enable
6623 //
6624 // // forward reference
6625 // layout(buffer_reference) buffer blockType;
6626 //
6627 // layout(buffer_reference, std430, buffer_reference_align = 16) buffer blockType {
6628 // int x;
6629 // blockType next;
6630 // };
6631 //
6632 // layout(std430) buffer rootBlock {
6633 // blockType root;
6634 // } r;
6635 //
6636 // void main()
6637 // {
6638 // blockType b = r.root;
6639 // b = b.next;
6640 // b.x = 531;
6641 // }
6642 //
6643 // clang-format on
6644
6645 const std::string predefs1 =
6646 R"(OpCapability Shader
6647 OpCapability PhysicalStorageBufferAddresses
6648 OpExtension "SPV_EXT_physical_storage_buffer"
6649 OpExtension "SPV_KHR_storage_buffer_storage_class"
6650 %1 = OpExtInstImport "GLSL.std.450"
6651 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6652 OpEntryPoint GLCompute %main "main"
6653 OpExecutionMode %main LocalSize 1 1 1
6654 OpSource GLSL 450
6655 OpSourceExtension "GL_EXT_buffer_reference"
6656 )";
6657
6658 const std::string names_before =
6659 R"(OpName %main "main"
6660 OpName %blockType "blockType"
6661 OpMemberName %blockType 0 "x"
6662 OpMemberName %blockType 1 "next"
6663 OpName %b "b"
6664 OpName %rootBlock "rootBlock"
6665 OpMemberName %rootBlock 0 "root"
6666 OpName %r "r"
6667 OpMemberDecorate %blockType 0 Offset 0
6668 OpMemberDecorate %blockType 1 Offset 8
6669 OpDecorate %blockType Block
6670 OpDecorate %b AliasedPointer
6671 OpMemberDecorate %rootBlock 0 Offset 0
6672 OpDecorate %rootBlock Block
6673 OpDecorate %r DescriptorSet 0
6674 OpDecorate %r Binding 0
6675 )";
6676
6677 const std::string names_after =
6678 R"(OpName %main "main"
6679 OpName %blockType "blockType"
6680 OpMemberName %blockType 0 "x"
6681 OpMemberName %blockType 1 "next"
6682 OpName %rootBlock "rootBlock"
6683 OpMemberName %rootBlock 0 "root"
6684 OpName %r "r"
6685 OpMemberDecorate %blockType 0 Offset 0
6686 OpMemberDecorate %blockType 1 Offset 8
6687 OpDecorate %blockType Block
6688 OpMemberDecorate %rootBlock 0 Offset 0
6689 OpDecorate %rootBlock Block
6690 OpDecorate %r DescriptorSet 0
6691 OpDecorate %r Binding 0
6692 )";
6693
6694 const std::string predefs2_before =
6695 R"(%void = OpTypeVoid
6696 %3 = OpTypeFunction %void
6697 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
6698 %int = OpTypeInt 32 1
6699 %blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType
6700 %_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType
6701 %_ptr_Function__ptr_PhysicalStorageBuffer_blockType = OpTypePointer Function %_ptr_PhysicalStorageBuffer_blockType
6702 %rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType
6703 %_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock
6704 %r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer
6705 %int_0 = OpConstant %int 0
6706 %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6707 %int_1 = OpConstant %int 1
6708 %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6709 %int_531 = OpConstant %int 531
6710 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
6711 )";
6712
6713 const std::string predefs2_after =
6714 R"(%void = OpTypeVoid
6715 %8 = OpTypeFunction %void
6716 OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer
6717 %int = OpTypeInt 32 1
6718 %blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType
6719 %_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType
6720 %rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType
6721 %_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock
6722 %r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer
6723 %int_0 = OpConstant %int 0
6724 %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6725 %int_1 = OpConstant %int 1
6726 %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType
6727 %int_531 = OpConstant %int 531
6728 %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
6729 )";
6730
6731 const std::string func_before =
6732 R"(%main = OpFunction %void None %3
6733 %5 = OpLabel
6734 %b = OpVariable %_ptr_Function__ptr_PhysicalStorageBuffer_blockType Function
6735 %16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
6736 %17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16
6737 %21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1
6738 %22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8
6739 OpStore %b %22
6740 %26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0
6741 OpStore %26 %int_531 Aligned 16
6742 OpReturn
6743 OpFunctionEnd
6744 )";
6745
6746 const std::string func_after =
6747 R"(%main = OpFunction %void None %8
6748 %19 = OpLabel
6749 %20 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0
6750 %21 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %20
6751 %22 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %21 %int_1
6752 %23 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %22 Aligned 8
6753 %24 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %23 %int_0
6754 OpStore %24 %int_531 Aligned 16
6755 OpReturn
6756 OpFunctionEnd
6757 )";
6758
6759 SinglePassRunAndCheck<AggressiveDCEPass>(
6760 predefs1 + names_before + predefs2_before + func_before,
6761 predefs1 + names_after + predefs2_after + func_after, true, true);
6762 }
6763
TEST_F(AggressiveDCETest,MultipleFunctionProcessIndependently)6764 TEST_F(AggressiveDCETest, MultipleFunctionProcessIndependently) {
6765 const std::string spirv = R"(
6766 OpCapability Shader
6767 OpMemoryModel Logical GLSL450
6768 OpEntryPoint GLCompute %entryHistogram "entryHistogram" %gl_GlobalInvocationID %gl_LocalInvocationIndex
6769 OpEntryPoint GLCompute %entryAverage "entryAverage" %gl_GlobalInvocationID %gl_LocalInvocationIndex
6770 OpExecutionMode %entryHistogram LocalSize 16 16 1
6771 OpExecutionMode %entryAverage LocalSize 256 1 1
6772 OpSource HLSL 640
6773 OpName %type_RWStructuredBuffer_uint "type.RWStructuredBuffer.uint"
6774 OpName %uHistogram "uHistogram"
6775 OpName %type_ACSBuffer_counter "type.ACSBuffer.counter"
6776 OpMemberName %type_ACSBuffer_counter 0 "counter"
6777 OpName %counter_var_uHistogram "counter.var.uHistogram"
6778 OpName %sharedHistogram "sharedHistogram"
6779 OpName %entryHistogram "entryHistogram"
6780 OpName %param_var_id "param.var.id"
6781 OpName %param_var_idx "param.var.idx"
6782 OpName %entryAverage "entryAverage"
6783 OpName %param_var_id_0 "param.var.id"
6784 OpName %param_var_idx_0 "param.var.idx"
6785 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
6786 OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
6787 OpDecorate %uHistogram DescriptorSet 0
6788 OpDecorate %uHistogram Binding 0
6789 OpDecorate %counter_var_uHistogram DescriptorSet 0
6790 OpDecorate %counter_var_uHistogram Binding 1
6791 OpDecorate %_runtimearr_uint ArrayStride 4
6792 OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0
6793 OpDecorate %type_RWStructuredBuffer_uint BufferBlock
6794 OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0
6795 OpDecorate %type_ACSBuffer_counter BufferBlock
6796 %uint = OpTypeInt 32 0
6797 %uint_0 = OpConstant %uint 0
6798 %uint_1 = OpConstant %uint 1
6799 %uint_2 = OpConstant %uint 2
6800 %uint_4 = OpConstant %uint 4
6801 %uint_8 = OpConstant %uint 8
6802 %uint_16 = OpConstant %uint 16
6803 %uint_32 = OpConstant %uint 32
6804 %uint_64 = OpConstant %uint 64
6805 %uint_128 = OpConstant %uint 128
6806 %uint_256 = OpConstant %uint 256
6807 %uint_512 = OpConstant %uint 512
6808 %uint_254 = OpConstant %uint 254
6809 %uint_255 = OpConstant %uint 255
6810 %int = OpTypeInt 32 1
6811 %int_0 = OpConstant %int 0
6812 %_runtimearr_uint = OpTypeRuntimeArray %uint
6813 %type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint
6814 %_ptr_Uniform_type_RWStructuredBuffer_uint = OpTypePointer Uniform %type_RWStructuredBuffer_uint
6815 %type_ACSBuffer_counter = OpTypeStruct %int
6816 %_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter
6817 %_arr_uint_uint_256 = OpTypeArray %uint %uint_256
6818 %_ptr_Workgroup__arr_uint_uint_256 = OpTypePointer Workgroup %_arr_uint_uint_256
6819 %v3uint = OpTypeVector %uint 3
6820 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
6821 %_ptr_Input_uint = OpTypePointer Input %uint
6822 %void = OpTypeVoid
6823 %49 = OpTypeFunction %void
6824 %_ptr_Function_v3uint = OpTypePointer Function %v3uint
6825 %_ptr_Function_uint = OpTypePointer Function %uint
6826 %52 = OpTypeFunction %void %_ptr_Function_v3uint %_ptr_Function_uint
6827 %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
6828 %uint_264 = OpConstant %uint 264
6829 %bool = OpTypeBool
6830 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
6831 %uHistogram = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
6832 %counter_var_uHistogram = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
6833 %sharedHistogram = OpVariable %_ptr_Workgroup__arr_uint_uint_256 Workgroup
6834 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
6835 %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
6836 %entryHistogram = OpFunction %void None %49
6837 %57 = OpLabel
6838 %param_var_id = OpVariable %_ptr_Function_v3uint Function
6839 %param_var_idx = OpVariable %_ptr_Function_uint Function
6840 %58 = OpLoad %v3uint %gl_GlobalInvocationID
6841 %59 = OpLoad %uint %gl_LocalInvocationIndex
6842 %79 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %int_0
6843 %80 = OpAtomicIAdd %uint %79 %uint_1 %uint_0 %uint_1
6844 OpReturn
6845 OpFunctionEnd
6846 %entryAverage = OpFunction %void None %49
6847 %63 = OpLabel
6848 %param_var_id_0 = OpVariable %_ptr_Function_v3uint Function
6849 %param_var_idx_0 = OpVariable %_ptr_Function_uint Function
6850 %64 = OpLoad %v3uint %gl_GlobalInvocationID
6851 %65 = OpLoad %uint %gl_LocalInvocationIndex
6852 OpStore %param_var_idx_0 %65
6853 %83 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6854 OpStore %83 %uint_0
6855
6856 ; CHECK: [[ieq:%\w+]] = OpIEqual
6857 ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
6858 ; CHECK-NEXT: OpBranchConditional [[ieq]] [[not_elim:%\w+]] [[merge]]
6859 ; CHECK-NEXT: [[not_elim]] = OpLabel
6860 ; CHECK: [[merge]] = OpLabel
6861
6862 OpControlBarrier %uint_2 %uint_2 %uint_264
6863 %85 = OpIEqual %bool %65 %uint_0
6864 OpSelectionMerge %89 None
6865 OpBranchConditional %85 %86 %89
6866 %86 = OpLabel
6867 %88 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6868 OpStore %88 %uint_1
6869 OpBranch %89
6870 %89 = OpLabel
6871 OpControlBarrier %uint_2 %uint_2 %uint_264
6872 %91 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65
6873 %92 = OpLoad %uint %91
6874 %94 = OpAccessChain %_ptr_Uniform_uint %uHistogram %int_0 %65
6875 OpStore %94 %92
6876 OpReturn
6877 OpFunctionEnd
6878 )";
6879
6880 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3);
6881
6882 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
6883 }
6884
TEST_F(AggressiveDCETest,DebugInfoKeepInFunctionElimStoreVar)6885 TEST_F(AggressiveDCETest, DebugInfoKeepInFunctionElimStoreVar) {
6886 // Verify that dead local variable tc and store eliminated but all
6887 // in-function debuginfo kept.
6888 //
6889 // The SPIR-V has been inlined and local single store eliminated
6890 //
6891 // Texture2D g_tColor;
6892 // SamplerState g_sAniso;
6893 //
6894 // struct PS_INPUT {
6895 // float2 vTextureCoords : TEXCOORD2;
6896 // };
6897 //
6898 // struct PS_OUTPUT {
6899 // float4 vColor : SV_Target0;
6900 // };
6901 //
6902 // PS_OUTPUT MainPs(PS_INPUT i) {
6903 // PS_OUTPUT ps_output;
6904 // float2 tc = i.vTextureCoords.xy;
6905 // ps_output.vColor = g_tColor.Sample(g_sAniso, tc);
6906 // return ps_output;
6907 // }
6908
6909 const std::string text = R"(
6910 OpCapability Shader
6911 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
6912 OpMemoryModel Logical GLSL450
6913 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
6914 OpExecutionMode %MainPs OriginUpperLeft
6915 %7 = OpString "foo.frag"
6916 %8 = OpString "PS_OUTPUT"
6917 %9 = OpString "float"
6918 %10 = OpString "vColor"
6919 %11 = OpString "PS_INPUT"
6920 %12 = OpString "vTextureCoords"
6921 %13 = OpString "@type.2d.image"
6922 %14 = OpString "type.2d.image"
6923 %15 = OpString "Texture2D.TemplateParam"
6924 %16 = OpString "src.MainPs"
6925 %17 = OpString "tc"
6926 %18 = OpString "ps_output"
6927 %19 = OpString "i"
6928 %20 = OpString "@type.sampler"
6929 %21 = OpString "type.sampler"
6930 %22 = OpString "g_sAniso"
6931 %23 = OpString "g_tColor"
6932 OpName %type_2d_image "type.2d.image"
6933 OpName %g_tColor "g_tColor"
6934 OpName %type_sampler "type.sampler"
6935 OpName %g_sAniso "g_sAniso"
6936 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
6937 OpName %out_var_SV_Target0 "out.var.SV_Target0"
6938 OpName %MainPs "MainPs"
6939 OpName %PS_INPUT "PS_INPUT"
6940 OpMemberName %PS_INPUT 0 "vTextureCoords"
6941 OpName %param_var_i "param.var.i"
6942 OpName %PS_OUTPUT "PS_OUTPUT"
6943 OpMemberName %PS_OUTPUT 0 "vColor"
6944 OpName %type_sampled_image "type.sampled.image"
6945 OpDecorate %in_var_TEXCOORD2 Location 0
6946 OpDecorate %out_var_SV_Target0 Location 0
6947 OpDecorate %g_tColor DescriptorSet 0
6948 OpDecorate %g_tColor Binding 0
6949 OpDecorate %g_sAniso DescriptorSet 0
6950 OpDecorate %g_sAniso Binding 1
6951 %int = OpTypeInt 32 1
6952 %int_0 = OpConstant %int 0
6953 %uint = OpTypeInt 32 0
6954 %uint_32 = OpConstant %uint 32
6955 %float = OpTypeFloat 32
6956 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
6957 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
6958 %type_sampler = OpTypeSampler
6959 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
6960 %v2float = OpTypeVector %float 2
6961 %_ptr_Input_v2float = OpTypePointer Input %v2float
6962 %v4float = OpTypeVector %float 4
6963 %_ptr_Output_v4float = OpTypePointer Output %v4float
6964 %void = OpTypeVoid
6965 %uint_128 = OpConstant %uint 128
6966 %uint_0 = OpConstant %uint 0
6967 %uint_64 = OpConstant %uint 64
6968 %45 = OpTypeFunction %void
6969 %PS_INPUT = OpTypeStruct %v2float
6970 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
6971 %PS_OUTPUT = OpTypeStruct %v4float
6972 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
6973 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
6974 %_ptr_Function_v2float = OpTypePointer Function %v2float
6975 %type_sampled_image = OpTypeSampledImage %type_2d_image
6976 %_ptr_Function_v4float = OpTypePointer Function %v4float
6977 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
6978 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
6979 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
6980 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
6981 %51 = OpExtInst %void %1 DebugInfoNone
6982 %52 = OpExtInst %void %1 DebugExpression
6983 %53 = OpExtInst %void %1 DebugOperation Deref
6984 %54 = OpExtInst %void %1 DebugExpression %53
6985 %55 = OpExtInst %void %1 DebugSource %7
6986 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL
6987 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58
6988 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float
6989 %60 = OpExtInst %void %1 DebugTypeVector %59 4
6990 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
6991 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62
6992 %63 = OpExtInst %void %1 DebugTypeVector %59 2
6993 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
6994 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate
6995 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0
6996 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65
6997 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61
6998 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51
6999 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68
7000 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal
7001 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal
7002 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1
7003 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate
7004 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition
7005 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition
7006 %MainPs = OpFunction %void None %45
7007 %76 = OpLabel
7008 %107 = OpExtInst %void %1 DebugScope %69
7009 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69
7010 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
7011 %79 = OpVariable %_ptr_Function_v2float Function
7012 %108 = OpExtInst %void %1 DebugNoScope
7013 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope
7014 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
7015 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7016 %82 = OpLoad %v2float %in_var_TEXCOORD2
7017 %83 = OpCompositeConstruct %PS_INPUT %82
7018 OpStore %param_var_i %83
7019 %109 = OpExtInst %void %1 DebugScope %68
7020 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
7021 %110 = OpExtInst %void %1 DebugScope %69
7022 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
7023 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %68
7024 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
7025 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69
7026 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %71 %78 %52
7027 OpLine %7 19 17
7028 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7029 %89 = OpLoad %v2float %88
7030 OpLine %7 19 12
7031 OpStore %79 %89
7032 ;CHECK-NOT: OpStore %79 %89
7033 OpLine %7 19 12
7034 %106 = OpExtInst %void %1 DebugValue %70 %89 %52
7035 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugValue %70 %89 %52
7036 OpLine %7 20 26
7037 %91 = OpLoad %type_2d_image %g_tColor
7038 OpLine %7 20 46
7039 %92 = OpLoad %type_sampler %g_sAniso
7040 OpLine %7 20 26
7041 %94 = OpSampledImage %type_sampled_image %91 %92
7042 %95 = OpImageSampleImplicitLod %v4float %94 %89 None
7043 OpLine %7 20 5
7044 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
7045 OpStore %96 %95
7046 OpLine %7 21 12
7047 %97 = OpLoad %PS_OUTPUT %78
7048 OpLine %7 21 5
7049 OpStore %81 %97
7050 %111 = OpExtInst %void %1 DebugNoScope
7051 ;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope
7052 %100 = OpCompositeExtract %v4float %97 0
7053 OpStore %out_var_SV_Target0 %100
7054 OpReturn
7055 OpFunctionEnd
7056 )";
7057
7058 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7059 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7060 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7061 }
7062
TEST_F(AggressiveDCETest,DebugInfoDeclareKeepsStore)7063 TEST_F(AggressiveDCETest, DebugInfoDeclareKeepsStore) {
7064 // Verify that local variable tc and its store are kept by DebugDeclare.
7065 //
7066 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
7067 // has just been inlined.
7068
7069 const std::string text = R"(
7070 OpCapability Shader
7071 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7072 OpMemoryModel Logical GLSL450
7073 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
7074 OpExecutionMode %MainPs OriginUpperLeft
7075 %20 = OpString "foo.frag"
7076 %24 = OpString "PS_OUTPUT"
7077 %28 = OpString "float"
7078 %31 = OpString "vColor"
7079 %33 = OpString "PS_INPUT"
7080 %38 = OpString "vTextureCoords"
7081 %40 = OpString "@type.2d.image"
7082 %41 = OpString "type.2d.image"
7083 %43 = OpString "Texture2D.TemplateParam"
7084 %47 = OpString "src.MainPs"
7085 %51 = OpString "tc"
7086 %53 = OpString "ps_output"
7087 %56 = OpString "i"
7088 %58 = OpString "@type.sampler"
7089 %59 = OpString "type.sampler"
7090 %61 = OpString "g_sAniso"
7091 %63 = OpString "g_tColor"
7092 OpName %type_2d_image "type.2d.image"
7093 OpName %g_tColor "g_tColor"
7094 OpName %type_sampler "type.sampler"
7095 OpName %g_sAniso "g_sAniso"
7096 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
7097 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7098 OpName %MainPs "MainPs"
7099 OpName %PS_INPUT "PS_INPUT"
7100 OpMemberName %PS_INPUT 0 "vTextureCoords"
7101 OpName %param_var_i "param.var.i"
7102 OpName %PS_OUTPUT "PS_OUTPUT"
7103 OpMemberName %PS_OUTPUT 0 "vColor"
7104 OpName %type_sampled_image "type.sampled.image"
7105 OpDecorate %in_var_TEXCOORD2 Location 0
7106 OpDecorate %out_var_SV_Target0 Location 0
7107 OpDecorate %g_tColor DescriptorSet 0
7108 OpDecorate %g_tColor Binding 0
7109 OpDecorate %g_sAniso DescriptorSet 0
7110 OpDecorate %g_sAniso Binding 1
7111 %int = OpTypeInt 32 1
7112 %int_0 = OpConstant %int 0
7113 %uint = OpTypeInt 32 0
7114 %uint_32 = OpConstant %uint 32
7115 %float = OpTypeFloat 32
7116 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7117 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7118 %type_sampler = OpTypeSampler
7119 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7120 %v2float = OpTypeVector %float 2
7121 %_ptr_Input_v2float = OpTypePointer Input %v2float
7122 %v4float = OpTypeVector %float 4
7123 %_ptr_Output_v4float = OpTypePointer Output %v4float
7124 %void = OpTypeVoid
7125 %uint_128 = OpConstant %uint 128
7126 %uint_0 = OpConstant %uint 0
7127 %uint_64 = OpConstant %uint 64
7128 %65 = OpTypeFunction %void
7129 %PS_INPUT = OpTypeStruct %v2float
7130 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7131 %PS_OUTPUT = OpTypeStruct %v4float
7132 %75 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7133 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7134 %_ptr_Function_v2float = OpTypePointer Function %v2float
7135 %type_sampled_image = OpTypeSampledImage %type_2d_image
7136 %_ptr_Function_v4float = OpTypePointer Function %v4float
7137 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7138 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7139 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7140 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7141 %39 = OpExtInst %void %1 DebugInfoNone
7142 %55 = OpExtInst %void %1 DebugExpression
7143 %22 = OpExtInst %void %1 DebugSource %20
7144 %23 = OpExtInst %void %1 DebugCompilationUnit 1 4 %22 HLSL
7145 %26 = OpExtInst %void %1 DebugTypeComposite %24 Structure %22 10 1 %23 %24 %uint_128 FlagIsProtected|FlagIsPrivate %27
7146 %29 = OpExtInst %void %1 DebugTypeBasic %28 %uint_32 Float
7147 %30 = OpExtInst %void %1 DebugTypeVector %29 4
7148 %27 = OpExtInst %void %1 DebugTypeMember %31 %30 %22 12 5 %26 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7149 %35 = OpExtInst %void %1 DebugTypeComposite %33 Structure %22 5 1 %23 %33 %uint_64 FlagIsProtected|FlagIsPrivate %36
7150 %37 = OpExtInst %void %1 DebugTypeVector %29 2
7151 %36 = OpExtInst %void %1 DebugTypeMember %38 %37 %22 7 5 %35 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7152 %42 = OpExtInst %void %1 DebugTypeComposite %40 Class %22 0 0 %23 %41 %39 FlagIsProtected|FlagIsPrivate
7153 %44 = OpExtInst %void %1 DebugTypeTemplateParameter %43 %29 %39 %22 0 0
7154 %45 = OpExtInst %void %1 DebugTypeTemplate %42 %44
7155 %46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %26 %35
7156 %48 = OpExtInst %void %1 DebugFunction %47 %46 %22 15 1 %23 %47 FlagIsProtected|FlagIsPrivate 16 %39
7157 %50 = OpExtInst %void %1 DebugLexicalBlock %22 16 1 %48
7158 %52 = OpExtInst %void %1 DebugLocalVariable %51 %37 %22 19 12 %50 FlagIsLocal
7159 %54 = OpExtInst %void %1 DebugLocalVariable %53 %26 %22 17 15 %50 FlagIsLocal
7160 %57 = OpExtInst %void %1 DebugLocalVariable %56 %35 %22 15 29 %48 FlagIsLocal 1
7161 %60 = OpExtInst %void %1 DebugTypeComposite %58 Structure %22 0 0 %23 %59 %39 FlagIsProtected|FlagIsPrivate
7162 %62 = OpExtInst %void %1 DebugGlobalVariable %61 %60 %22 3 14 %23 %61 %g_sAniso FlagIsDefinition
7163 %64 = OpExtInst %void %1 DebugGlobalVariable %63 %42 %22 1 11 %23 %63 %g_tColor FlagIsDefinition
7164 %MainPs = OpFunction %void None %65
7165 %66 = OpLabel
7166 %114 = OpExtInst %void %1 DebugScope %50
7167 %98 = OpVariable %_ptr_Function_PS_OUTPUT Function
7168 %99 = OpVariable %_ptr_Function_v2float Function
7169 %115 = OpExtInst %void %1 DebugNoScope
7170 %100 = OpVariable %_ptr_Function_PS_OUTPUT Function
7171 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7172 %70 = OpLoad %v2float %in_var_TEXCOORD2
7173 %71 = OpCompositeConstruct %PS_INPUT %70
7174 OpStore %param_var_i %71
7175 %116 = OpExtInst %void %1 DebugScope %48
7176 %102 = OpExtInst %void %1 DebugDeclare %57 %param_var_i %55
7177 %117 = OpExtInst %void %1 DebugScope %50
7178 %103 = OpExtInst %void %1 DebugDeclare %54 %98 %55
7179 OpLine %20 19 17
7180 %104 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7181 %105 = OpLoad %v2float %104
7182 OpLine %20 19 12
7183 OpStore %99 %105
7184 ;CHECK: OpStore %99 %105
7185 %106 = OpExtInst %void %1 DebugDeclare %52 %99 %55
7186 OpLine %20 20 26
7187 %107 = OpLoad %type_2d_image %g_tColor
7188 OpLine %20 20 46
7189 %108 = OpLoad %type_sampler %g_sAniso
7190 OpLine %20 20 26
7191 %110 = OpSampledImage %type_sampled_image %107 %108
7192 %111 = OpImageSampleImplicitLod %v4float %110 %105 None
7193 OpLine %20 20 5
7194 %112 = OpAccessChain %_ptr_Function_v4float %98 %int_0
7195 OpStore %112 %111
7196 OpLine %20 21 12
7197 %113 = OpLoad %PS_OUTPUT %98
7198 OpLine %20 21 5
7199 OpStore %100 %113
7200 %118 = OpExtInst %void %1 DebugNoScope
7201 %73 = OpLoad %PS_OUTPUT %100
7202 %74 = OpCompositeExtract %v4float %73 0
7203 OpStore %out_var_SV_Target0 %74
7204 OpReturn
7205 OpFunctionEnd
7206 )";
7207
7208 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7209 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7210 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7211 }
7212
TEST_F(AggressiveDCETest,DebugInfoValueDerefKeepsStore)7213 TEST_F(AggressiveDCETest, DebugInfoValueDerefKeepsStore) {
7214 // Verify that local variable tc and its store are kept by DebugValue with
7215 // Deref.
7216 //
7217 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
7218 // has just been inlined and edited to replace the DebugDeclare with the
7219 // DebugValue/Deref.
7220
7221 const std::string text = R"(
7222 OpCapability Shader
7223 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7224 OpMemoryModel Logical GLSL450
7225 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
7226 OpExecutionMode %MainPs OriginUpperLeft
7227 %7 = OpString "foo.frag"
7228 %8 = OpString "PS_OUTPUT"
7229 %9 = OpString "float"
7230 %10 = OpString "vColor"
7231 %11 = OpString "PS_INPUT"
7232 %12 = OpString "vTextureCoords"
7233 %13 = OpString "@type.2d.image"
7234 %14 = OpString "type.2d.image"
7235 %15 = OpString "Texture2D.TemplateParam"
7236 %16 = OpString "src.MainPs"
7237 %17 = OpString "tc"
7238 %18 = OpString "ps_output"
7239 %19 = OpString "i"
7240 %20 = OpString "@type.sampler"
7241 %21 = OpString "type.sampler"
7242 %22 = OpString "g_sAniso"
7243 %23 = OpString "g_tColor"
7244 OpName %type_2d_image "type.2d.image"
7245 OpName %g_tColor "g_tColor"
7246 OpName %type_sampler "type.sampler"
7247 OpName %g_sAniso "g_sAniso"
7248 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
7249 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7250 OpName %MainPs "MainPs"
7251 OpName %PS_INPUT "PS_INPUT"
7252 OpMemberName %PS_INPUT 0 "vTextureCoords"
7253 OpName %param_var_i "param.var.i"
7254 OpName %PS_OUTPUT "PS_OUTPUT"
7255 OpMemberName %PS_OUTPUT 0 "vColor"
7256 OpName %type_sampled_image "type.sampled.image"
7257 OpDecorate %in_var_TEXCOORD2 Location 0
7258 OpDecorate %out_var_SV_Target0 Location 0
7259 OpDecorate %g_tColor DescriptorSet 0
7260 OpDecorate %g_tColor Binding 0
7261 OpDecorate %g_sAniso DescriptorSet 0
7262 OpDecorate %g_sAniso Binding 1
7263 %int = OpTypeInt 32 1
7264 %int_0 = OpConstant %int 0
7265 %uint = OpTypeInt 32 0
7266 %uint_32 = OpConstant %uint 32
7267 %float = OpTypeFloat 32
7268 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7269 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7270 %type_sampler = OpTypeSampler
7271 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7272 %v2float = OpTypeVector %float 2
7273 %_ptr_Input_v2float = OpTypePointer Input %v2float
7274 %v4float = OpTypeVector %float 4
7275 %_ptr_Output_v4float = OpTypePointer Output %v4float
7276 %void = OpTypeVoid
7277 %uint_128 = OpConstant %uint 128
7278 %uint_0 = OpConstant %uint 0
7279 %uint_64 = OpConstant %uint 64
7280 %45 = OpTypeFunction %void
7281 %PS_INPUT = OpTypeStruct %v2float
7282 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7283 %PS_OUTPUT = OpTypeStruct %v4float
7284 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7285 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7286 %_ptr_Function_v2float = OpTypePointer Function %v2float
7287 %type_sampled_image = OpTypeSampledImage %type_2d_image
7288 %_ptr_Function_v4float = OpTypePointer Function %v4float
7289 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7290 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7291 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7292 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7293 %51 = OpExtInst %void %1 DebugInfoNone
7294 %52 = OpExtInst %void %1 DebugExpression
7295 %53 = OpExtInst %void %1 DebugOperation Deref
7296 %54 = OpExtInst %void %1 DebugExpression %53
7297 %55 = OpExtInst %void %1 DebugSource %7
7298 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL
7299 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58
7300 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float
7301 %60 = OpExtInst %void %1 DebugTypeVector %59 4
7302 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7303 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62
7304 %63 = OpExtInst %void %1 DebugTypeVector %59 2
7305 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7306 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate
7307 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0
7308 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65
7309 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61
7310 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51
7311 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68
7312 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal
7313 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal
7314 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1
7315 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate
7316 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition
7317 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition
7318 %MainPs = OpFunction %void None %45
7319 %76 = OpLabel
7320 %101 = OpExtInst %void %1 DebugScope %69
7321 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
7322 %79 = OpVariable %_ptr_Function_v2float Function
7323 %102 = OpExtInst %void %1 DebugNoScope
7324 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
7325 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7326 %82 = OpLoad %v2float %in_var_TEXCOORD2
7327 %83 = OpCompositeConstruct %PS_INPUT %82
7328 OpStore %param_var_i %83
7329 %103 = OpExtInst %void %1 DebugScope %68
7330 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
7331 %104 = OpExtInst %void %1 DebugScope %69
7332 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
7333 OpLine %7 19 17
7334 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7335 %89 = OpLoad %v2float %88
7336 OpLine %7 19 12
7337 OpStore %79 %89
7338 ;CHECK: OpStore %79 %89
7339 %90 = OpExtInst %void %1 DebugValue %70 %79 %54
7340 OpLine %7 20 26
7341 %91 = OpLoad %type_2d_image %g_tColor
7342 OpLine %7 20 46
7343 %92 = OpLoad %type_sampler %g_sAniso
7344 OpLine %7 20 26
7345 %94 = OpSampledImage %type_sampled_image %91 %92
7346 %95 = OpImageSampleImplicitLod %v4float %94 %89 None
7347 OpLine %7 20 5
7348 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
7349 OpStore %96 %95
7350 OpLine %7 21 12
7351 %97 = OpLoad %PS_OUTPUT %78
7352 OpLine %7 21 5
7353 OpStore %81 %97
7354 %105 = OpExtInst %void %1 DebugNoScope
7355 %99 = OpLoad %PS_OUTPUT %81
7356 %100 = OpCompositeExtract %v4float %99 0
7357 OpStore %out_var_SV_Target0 %100
7358 OpReturn
7359 OpFunctionEnd
7360 )";
7361
7362 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7363 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7364 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7365 }
7366
TEST_F(AggressiveDCETest,DebugInfoElimUnusedTextureKeepGlobalVariable)7367 TEST_F(AggressiveDCETest, DebugInfoElimUnusedTextureKeepGlobalVariable) {
7368 // Verify that unused texture g_tColor2 is eliminated but its
7369 // DebugGlobalVariable is retained but with DebugInfoNone for its Variable.
7370 //
7371 // Same shader source as DebugInfoInFunctionKeepStoreVarElim but with unused
7372 // g_tColor2 added.
7373
7374 const std::string text = R"(
7375 OpCapability Shader
7376 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7377 OpMemoryModel Logical GLSL450
7378 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_tColor2 %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
7379 OpExecutionMode %MainPs OriginUpperLeft
7380 %21 = OpString "foo6.frag"
7381 %25 = OpString "PS_OUTPUT"
7382 %29 = OpString "float"
7383 %32 = OpString "vColor"
7384 %34 = OpString "PS_INPUT"
7385 %39 = OpString "vTextureCoords"
7386 %41 = OpString "@type.2d.image"
7387 %42 = OpString "type.2d.image"
7388 %44 = OpString "Texture2D.TemplateParam"
7389 %48 = OpString "src.MainPs"
7390 %52 = OpString "tc"
7391 %54 = OpString "ps_output"
7392 %57 = OpString "i"
7393 %59 = OpString "@type.sampler"
7394 %60 = OpString "type.sampler"
7395 %62 = OpString "g_sAniso"
7396 %64 = OpString "g_tColor2"
7397 %66 = OpString "g_tColor"
7398 OpName %type_2d_image "type.2d.image"
7399 OpName %g_tColor "g_tColor"
7400 OpName %g_tColor2 "g_tColor2"
7401 OpName %type_sampler "type.sampler"
7402 OpName %g_sAniso "g_sAniso"
7403 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
7404 OpName %out_var_SV_Target0 "out.var.SV_Target0"
7405 OpName %MainPs "MainPs"
7406 OpName %PS_INPUT "PS_INPUT"
7407 OpMemberName %PS_INPUT 0 "vTextureCoords"
7408 OpName %param_var_i "param.var.i"
7409 OpName %PS_OUTPUT "PS_OUTPUT"
7410 OpMemberName %PS_OUTPUT 0 "vColor"
7411 OpName %type_sampled_image "type.sampled.image"
7412 OpDecorate %in_var_TEXCOORD2 Location 0
7413 OpDecorate %out_var_SV_Target0 Location 0
7414 OpDecorate %g_tColor DescriptorSet 0
7415 OpDecorate %g_tColor Binding 0
7416 OpDecorate %g_tColor2 DescriptorSet 0
7417 OpDecorate %g_tColor2 Binding 1
7418 OpDecorate %g_sAniso DescriptorSet 0
7419 OpDecorate %g_sAniso Binding 2
7420 %int = OpTypeInt 32 1
7421 %int_0 = OpConstant %int 0
7422 %uint = OpTypeInt 32 0
7423 %uint_32 = OpConstant %uint 32
7424 %float = OpTypeFloat 32
7425 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7426 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7427 %type_sampler = OpTypeSampler
7428 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7429 %v2float = OpTypeVector %float 2
7430 %_ptr_Input_v2float = OpTypePointer Input %v2float
7431 %v4float = OpTypeVector %float 4
7432 %_ptr_Output_v4float = OpTypePointer Output %v4float
7433 %void = OpTypeVoid
7434 %uint_128 = OpConstant %uint 128
7435 %uint_0 = OpConstant %uint 0
7436 %uint_64 = OpConstant %uint 64
7437 %68 = OpTypeFunction %void
7438 %PS_INPUT = OpTypeStruct %v2float
7439 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
7440 %PS_OUTPUT = OpTypeStruct %v4float
7441 %78 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
7442 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
7443 %_ptr_Function_v2float = OpTypePointer Function %v2float
7444 %type_sampled_image = OpTypeSampledImage %type_2d_image
7445 %_ptr_Function_v4float = OpTypePointer Function %v4float
7446 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7447 %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7448 ;CHECK-NOT: %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7449 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7450 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
7451 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
7452 %40 = OpExtInst %void %1 DebugInfoNone
7453 %56 = OpExtInst %void %1 DebugExpression
7454 %23 = OpExtInst %void %1 DebugSource %21
7455 %24 = OpExtInst %void %1 DebugCompilationUnit 1 4 %23 HLSL
7456 %27 = OpExtInst %void %1 DebugTypeComposite %25 Structure %23 11 1 %24 %25 %uint_128 FlagIsProtected|FlagIsPrivate %28
7457 %30 = OpExtInst %void %1 DebugTypeBasic %29 %uint_32 Float
7458 %31 = OpExtInst %void %1 DebugTypeVector %30 4
7459 %28 = OpExtInst %void %1 DebugTypeMember %32 %31 %23 13 5 %27 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
7460 %36 = OpExtInst %void %1 DebugTypeComposite %34 Structure %23 6 1 %24 %34 %uint_64 FlagIsProtected|FlagIsPrivate %37
7461 %38 = OpExtInst %void %1 DebugTypeVector %30 2
7462 %37 = OpExtInst %void %1 DebugTypeMember %39 %38 %23 8 5 %36 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
7463 %43 = OpExtInst %void %1 DebugTypeComposite %41 Class %23 0 0 %24 %42 %40 FlagIsProtected|FlagIsPrivate
7464 %45 = OpExtInst %void %1 DebugTypeTemplateParameter %44 %30 %40 %23 0 0
7465 %46 = OpExtInst %void %1 DebugTypeTemplate %43 %45
7466 %47 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %27 %36
7467 %49 = OpExtInst %void %1 DebugFunction %48 %47 %23 16 1 %24 %48 FlagIsProtected|FlagIsPrivate 17 %40
7468 %51 = OpExtInst %void %1 DebugLexicalBlock %23 17 1 %49
7469 %53 = OpExtInst %void %1 DebugLocalVariable %52 %38 %23 20 12 %51 FlagIsLocal
7470 %55 = OpExtInst %void %1 DebugLocalVariable %54 %27 %23 18 15 %51 FlagIsLocal
7471 %58 = OpExtInst %void %1 DebugLocalVariable %57 %36 %23 16 29 %49 FlagIsLocal 1
7472 %61 = OpExtInst %void %1 DebugTypeComposite %59 Structure %23 0 0 %24 %60 %40 FlagIsProtected|FlagIsPrivate
7473 %63 = OpExtInst %void %1 DebugGlobalVariable %62 %61 %23 4 14 %24 %62 %g_sAniso FlagIsDefinition
7474 %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition
7475 ;CHECK-NOT: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition
7476 ;CHECK: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %40 FlagIsDefinition
7477 %67 = OpExtInst %void %1 DebugGlobalVariable %66 %43 %23 1 11 %24 %66 %g_tColor FlagIsDefinition
7478 %MainPs = OpFunction %void None %68
7479 %69 = OpLabel
7480 %117 = OpExtInst %void %1 DebugScope %51
7481 %101 = OpVariable %_ptr_Function_PS_OUTPUT Function
7482 %102 = OpVariable %_ptr_Function_v2float Function
7483 %118 = OpExtInst %void %1 DebugNoScope
7484 %103 = OpVariable %_ptr_Function_PS_OUTPUT Function
7485 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
7486 %73 = OpLoad %v2float %in_var_TEXCOORD2
7487 %74 = OpCompositeConstruct %PS_INPUT %73
7488 OpStore %param_var_i %74
7489 %119 = OpExtInst %void %1 DebugScope %49
7490 %105 = OpExtInst %void %1 DebugDeclare %58 %param_var_i %56
7491 %120 = OpExtInst %void %1 DebugScope %51
7492 %106 = OpExtInst %void %1 DebugDeclare %55 %101 %56
7493 OpLine %21 20 17
7494 %107 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
7495 %108 = OpLoad %v2float %107
7496 OpLine %21 20 12
7497 OpStore %102 %108
7498 %109 = OpExtInst %void %1 DebugDeclare %53 %102 %56
7499 OpLine %21 21 26
7500 %110 = OpLoad %type_2d_image %g_tColor
7501 OpLine %21 21 46
7502 %111 = OpLoad %type_sampler %g_sAniso
7503 OpLine %21 21 57
7504 %112 = OpLoad %v2float %102
7505 OpLine %21 21 26
7506 %113 = OpSampledImage %type_sampled_image %110 %111
7507 %114 = OpImageSampleImplicitLod %v4float %113 %112 None
7508 OpLine %21 21 5
7509 %115 = OpAccessChain %_ptr_Function_v4float %101 %int_0
7510 OpStore %115 %114
7511 OpLine %21 22 12
7512 %116 = OpLoad %PS_OUTPUT %101
7513 OpLine %21 22 5
7514 OpStore %103 %116
7515 %121 = OpExtInst %void %1 DebugNoScope
7516 %76 = OpLoad %PS_OUTPUT %103
7517 %77 = OpCompositeExtract %v4float %76 0
7518 OpStore %out_var_SV_Target0 %77
7519 OpReturn
7520 OpFunctionEnd
7521 )";
7522
7523 SetTargetEnv(SPV_ENV_VULKAN_1_2);
7524 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7525 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7526 }
7527
TEST_F(AggressiveDCETest,KeepDebugScopeParent)7528 TEST_F(AggressiveDCETest, KeepDebugScopeParent) {
7529 // Verify that local variable tc and its store are kept by DebugDeclare.
7530 //
7531 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V
7532 // has just been inlined.
7533
7534 const std::string text = R"(
7535 OpCapability Shader
7536 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
7537 OpMemoryModel Logical GLSL450
7538 OpEntryPoint Fragment %main "main" %out_var_SV_TARGET0
7539 OpExecutionMode %main OriginUpperLeft
7540 %11 = OpString "float"
7541 %16 = OpString "t.hlsl"
7542 %19 = OpString "src.main"
7543 OpName %out_var_SV_TARGET0 "out.var.SV_TARGET0"
7544 OpName %main "main"
7545 OpDecorate %out_var_SV_TARGET0 Location 0
7546 %float = OpTypeFloat 32
7547 %float_0 = OpConstant %float 0
7548 %v4float = OpTypeVector %float 4
7549 %7 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
7550 %uint = OpTypeInt 32 0
7551 %uint_32 = OpConstant %uint 32
7552 %_ptr_Output_v4float = OpTypePointer Output %v4float
7553 %void = OpTypeVoid
7554 %23 = OpTypeFunction %void
7555 %26 = OpTypeFunction %v4float
7556 %out_var_SV_TARGET0 = OpVariable %_ptr_Output_v4float Output
7557 %_ptr_Function_v4float = OpTypePointer Function %v4float
7558 %33 = OpExtInst %void %1 DebugInfoNone
7559 %13 = OpExtInst %void %1 DebugTypeBasic %11 %uint_32 Float
7560 %14 = OpExtInst %void %1 DebugTypeVector %13 4
7561 %15 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %14
7562 %17 = OpExtInst %void %1 DebugSource %16
7563 %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL
7564 %20 = OpExtInst %void %1 DebugFunction %19 %15 %17 1 1 %18 %19 FlagIsProtected|FlagIsPrivate 2 %33
7565 %22 = OpExtInst %void %1 DebugLexicalBlock %17 2 1 %20
7566 %main = OpFunction %void None %23
7567 %24 = OpLabel
7568 %31 = OpVariable %_ptr_Function_v4float Function
7569 ; CHECK: [[block:%\w+]] = OpExtInst %void %1 DebugLexicalBlock
7570 ; CHECK: DebugScope [[block]]
7571 %34 = OpExtInst %void %1 DebugScope %22
7572 OpLine %16 3 5
7573 OpStore %31 %7
7574 OpStore %out_var_SV_TARGET0 %7
7575 %35 = OpExtInst %void %1 DebugNoScope
7576 OpReturn
7577 OpFunctionEnd
7578 )";
7579
7580 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7581 SinglePassRunAndMatch<AggressiveDCEPass>(text, true);
7582 }
7583
7584 // TODO(greg-lunarg): Add tests to verify handling of these cases:
7585 //
7586 // Check that logical addressing required
7587 // Check that function calls inhibit optimization
7588 // Others?
7589
7590 } // namespace
7591 } // namespace opt
7592 } // namespace spvtools
7593