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 
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20 
21 namespace spvtools {
22 namespace opt {
23 namespace {
24 
25 using DeadInsertElimTest = PassTest<::testing::Test>;
26 
TEST_F(DeadInsertElimTest,InsertAfterInsertElim)27 TEST_F(DeadInsertElimTest, InsertAfterInsertElim) {
28   // With two insertions to the same offset, the first is dead.
29   //
30   // Note: The SPIR-V assembly has had store/load elimination
31   // performed to allow the inserts and extracts to directly
32   // reference each other.
33   //
34   // #version 450
35   //
36   // layout (location=0) in float In0;
37   // layout (location=1) in float In1;
38   // layout (location=2) in vec2 In2;
39   // layout (location=0) out vec4 OutColor;
40   //
41   // void main()
42   // {
43   //     vec2 v = In2;
44   //     v.x = In0 + In1; // dead
45   //     v.x = 0.0;
46   //     OutColor = v.xyxy;
47   // }
48 
49   const std::string before_predefs =
50       R"(OpCapability Shader
51 %1 = OpExtInstImport "GLSL.std.450"
52 OpMemoryModel Logical GLSL450
53 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
54 OpExecutionMode %main OriginUpperLeft
55 OpSource GLSL 450
56 OpName %main "main"
57 OpName %In2 "In2"
58 OpName %In0 "In0"
59 OpName %In1 "In1"
60 OpName %OutColor "OutColor"
61 OpName %_Globals_ "_Globals_"
62 OpMemberName %_Globals_ 0 "g_b"
63 OpMemberName %_Globals_ 1 "g_n"
64 OpName %_ ""
65 OpDecorate %In2 Location 2
66 OpDecorate %In0 Location 0
67 OpDecorate %In1 Location 1
68 OpDecorate %OutColor Location 0
69 OpMemberDecorate %_Globals_ 0 Offset 0
70 OpMemberDecorate %_Globals_ 1 Offset 4
71 OpDecorate %_Globals_ Block
72 OpDecorate %_ DescriptorSet 0
73 OpDecorate %_ Binding 0
74 %void = OpTypeVoid
75 %11 = OpTypeFunction %void
76 %float = OpTypeFloat 32
77 %v2float = OpTypeVector %float 2
78 %_ptr_Function_v2float = OpTypePointer Function %v2float
79 %_ptr_Input_v2float = OpTypePointer Input %v2float
80 %In2 = OpVariable %_ptr_Input_v2float Input
81 %_ptr_Input_float = OpTypePointer Input %float
82 %In0 = OpVariable %_ptr_Input_float Input
83 %In1 = OpVariable %_ptr_Input_float Input
84 %uint = OpTypeInt 32 0
85 %_ptr_Function_float = OpTypePointer Function %float
86 %float_0 = OpConstant %float 0
87 %v4float = OpTypeVector %float 4
88 %_ptr_Output_v4float = OpTypePointer Output %v4float
89 %OutColor = OpVariable %_ptr_Output_v4float Output
90 %int = OpTypeInt 32 1
91 %_Globals_ = OpTypeStruct %uint %int
92 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
93 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
94 )";
95 
96   const std::string after_predefs =
97       R"(OpCapability Shader
98 %1 = OpExtInstImport "GLSL.std.450"
99 OpMemoryModel Logical GLSL450
100 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
101 OpExecutionMode %main OriginUpperLeft
102 OpSource GLSL 450
103 OpName %main "main"
104 OpName %In2 "In2"
105 OpName %In0 "In0"
106 OpName %In1 "In1"
107 OpName %OutColor "OutColor"
108 OpName %_Globals_ "_Globals_"
109 OpMemberName %_Globals_ 0 "g_b"
110 OpMemberName %_Globals_ 1 "g_n"
111 OpName %_ ""
112 OpDecorate %In2 Location 2
113 OpDecorate %In0 Location 0
114 OpDecorate %In1 Location 1
115 OpDecorate %OutColor Location 0
116 OpMemberDecorate %_Globals_ 0 Offset 0
117 OpMemberDecorate %_Globals_ 1 Offset 4
118 OpDecorate %_Globals_ Block
119 OpDecorate %_ DescriptorSet 0
120 OpDecorate %_ Binding 0
121 %void = OpTypeVoid
122 %10 = OpTypeFunction %void
123 %float = OpTypeFloat 32
124 %v2float = OpTypeVector %float 2
125 %_ptr_Function_v2float = OpTypePointer Function %v2float
126 %_ptr_Input_v2float = OpTypePointer Input %v2float
127 %In2 = OpVariable %_ptr_Input_v2float Input
128 %_ptr_Input_float = OpTypePointer Input %float
129 %In0 = OpVariable %_ptr_Input_float Input
130 %In1 = OpVariable %_ptr_Input_float Input
131 %uint = OpTypeInt 32 0
132 %_ptr_Function_float = OpTypePointer Function %float
133 %float_0 = OpConstant %float 0
134 %v4float = OpTypeVector %float 4
135 %_ptr_Output_v4float = OpTypePointer Output %v4float
136 %OutColor = OpVariable %_ptr_Output_v4float Output
137 %int = OpTypeInt 32 1
138 %_Globals_ = OpTypeStruct %uint %int
139 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
140 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
141 )";
142 
143   const std::string before =
144       R"(%main = OpFunction %void None %11
145 %25 = OpLabel
146 %26 = OpLoad %v2float %In2
147 %27 = OpLoad %float %In0
148 %28 = OpLoad %float %In1
149 %29 = OpFAdd %float %27 %28
150 %35 = OpCompositeInsert %v2float %29 %26 0
151 %37 = OpCompositeInsert %v2float %float_0 %35 0
152 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
153 OpStore %OutColor %33
154 OpReturn
155 OpFunctionEnd
156 )";
157 
158   const std::string after =
159       R"(%main = OpFunction %void None %10
160 %23 = OpLabel
161 %24 = OpLoad %v2float %In2
162 %29 = OpCompositeInsert %v2float %float_0 %24 0
163 %30 = OpVectorShuffle %v4float %29 %29 0 1 0 1
164 OpStore %OutColor %30
165 OpReturn
166 OpFunctionEnd
167 )";
168 
169   SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
170                                             after_predefs + after, true, true);
171 }
172 
TEST_F(DeadInsertElimTest,DeadInsertForLinkage)173 TEST_F(DeadInsertElimTest, DeadInsertForLinkage) {
174   const std::string before =
175       R"(OpCapability Shader
176 OpCapability Linkage
177 OpMemoryModel Logical GLSL450
178 OpSource HLSL 630
179 OpName %main "main"
180 OpName %BaseColor "BaseColor"
181 OpName %bb_entry "bb.entry"
182 OpName %v "v"
183 OpDecorate %main LinkageAttributes "main" Export
184 %int = OpTypeInt 32 1
185 %int_1 = OpConstant %int 1
186 %uint = OpTypeInt 32 0
187 %uint_0 = OpConstant %uint 0
188 %int_0 = OpConstant %int 0
189 %float = OpTypeFloat 32
190 %float_0 = OpConstant %float 0
191 %v2float = OpTypeVector %float 2
192 %_ptr_Function_v2float = OpTypePointer Function %v2float
193 %14 = OpTypeFunction %v2float %_ptr_Function_v2float
194 %_ptr_Function_float = OpTypePointer Function %float
195 %main = OpFunction %v2float None %14
196 %BaseColor = OpFunctionParameter %_ptr_Function_v2float
197 %bb_entry = OpLabel
198 %v = OpVariable %_ptr_Function_v2float Function
199 %16 = OpLoad %v2float %v
200 %17 = OpAccessChain %_ptr_Function_float %BaseColor %int_1
201 %18 = OpLoad %float %17
202 %19 = OpCompositeInsert %v2float %18 %16 0
203 %20 = OpCompositeInsert %v2float %float_0 %19 0
204 OpReturnValue %20
205 OpFunctionEnd
206 )";
207   const std::string after =
208       R"(OpCapability Shader
209 OpCapability Linkage
210 OpMemoryModel Logical GLSL450
211 OpSource HLSL 630
212 OpName %main "main"
213 OpName %BaseColor "BaseColor"
214 OpName %bb_entry "bb.entry"
215 OpName %v "v"
216 OpDecorate %main LinkageAttributes "main" Export
217 %int = OpTypeInt 32 1
218 %uint = OpTypeInt 32 0
219 %uint_0 = OpConstant %uint 0
220 %int_0 = OpConstant %int 0
221 %float = OpTypeFloat 32
222 %float_0 = OpConstant %float 0
223 %v2float = OpTypeVector %float 2
224 %_ptr_Function_v2float = OpTypePointer Function %v2float
225 %14 = OpTypeFunction %v2float %_ptr_Function_v2float
226 %_ptr_Function_float = OpTypePointer Function %float
227 %main = OpFunction %v2float None %14
228 %BaseColor = OpFunctionParameter %_ptr_Function_v2float
229 %bb_entry = OpLabel
230 %v = OpVariable %_ptr_Function_v2float Function
231 %16 = OpLoad %v2float %v
232 %20 = OpCompositeInsert %v2float %float_0 %16 0
233 OpReturnValue %20
234 OpFunctionEnd
235 )";
236   SinglePassRunAndCheck<DeadInsertElimPass>(before, after, true, true);
237 }
238 
TEST_F(DeadInsertElimTest,DeadInsertInChainWithPhi)239 TEST_F(DeadInsertElimTest, DeadInsertInChainWithPhi) {
240   // Dead insert eliminated with phi in insertion chain.
241   //
242   // Note: The SPIR-V assembly has had store/load elimination
243   // performed to allow the inserts and extracts to directly
244   // reference each other.
245   //
246   // #version 450
247   //
248   // layout (location=0) in vec4 In0;
249   // layout (location=1) in float In1;
250   // layout (location=2) in float In2;
251   // layout (location=0) out vec4 OutColor;
252   //
253   // layout(std140, binding = 0 ) uniform _Globals_
254   // {
255   //     bool g_b;
256   // };
257   //
258   // void main()
259   // {
260   //     vec4 v = In0;
261   //     v.z = In1 + In2;
262   //     if (g_b) v.w = 1.0;
263   //     OutColor = vec4(v.x,v.y,0.0,v.w);
264   // }
265 
266   const std::string before_predefs =
267       R"(OpCapability Shader
268 %1 = OpExtInstImport "GLSL.std.450"
269 OpMemoryModel Logical GLSL450
270 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
271 OpExecutionMode %main OriginUpperLeft
272 OpSource GLSL 450
273 OpName %main "main"
274 OpName %In0 "In0"
275 OpName %In1 "In1"
276 OpName %In2 "In2"
277 OpName %_Globals_ "_Globals_"
278 OpMemberName %_Globals_ 0 "g_b"
279 OpName %_ ""
280 OpName %OutColor "OutColor"
281 OpDecorate %In0 Location 0
282 OpDecorate %In1 Location 1
283 OpDecorate %In2 Location 2
284 OpMemberDecorate %_Globals_ 0 Offset 0
285 OpDecorate %_Globals_ Block
286 OpDecorate %_ DescriptorSet 0
287 OpDecorate %_ Binding 0
288 OpDecorate %OutColor Location 0
289 %void = OpTypeVoid
290 %11 = OpTypeFunction %void
291 %float = OpTypeFloat 32
292 %v4float = OpTypeVector %float 4
293 %_ptr_Function_v4float = OpTypePointer Function %v4float
294 %_ptr_Input_v4float = OpTypePointer Input %v4float
295 %In0 = OpVariable %_ptr_Input_v4float Input
296 %_ptr_Input_float = OpTypePointer Input %float
297 %In1 = OpVariable %_ptr_Input_float Input
298 %In2 = OpVariable %_ptr_Input_float Input
299 %uint = OpTypeInt 32 0
300 %_ptr_Function_float = OpTypePointer Function %float
301 %_Globals_ = OpTypeStruct %uint
302 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
303 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
304 %int = OpTypeInt 32 1
305 %int_0 = OpConstant %int 0
306 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
307 %bool = OpTypeBool
308 %uint_0 = OpConstant %uint 0
309 %float_1 = OpConstant %float 1
310 %_ptr_Output_v4float = OpTypePointer Output %v4float
311 %OutColor = OpVariable %_ptr_Output_v4float Output
312 %float_0 = OpConstant %float 0
313 )";
314 
315   const std::string after_predefs =
316       R"(OpCapability Shader
317 %1 = OpExtInstImport "GLSL.std.450"
318 OpMemoryModel Logical GLSL450
319 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
320 OpExecutionMode %main OriginUpperLeft
321 OpSource GLSL 450
322 OpName %main "main"
323 OpName %In0 "In0"
324 OpName %In1 "In1"
325 OpName %In2 "In2"
326 OpName %_Globals_ "_Globals_"
327 OpMemberName %_Globals_ 0 "g_b"
328 OpName %_ ""
329 OpName %OutColor "OutColor"
330 OpDecorate %In0 Location 0
331 OpDecorate %In1 Location 1
332 OpDecorate %In2 Location 2
333 OpMemberDecorate %_Globals_ 0 Offset 0
334 OpDecorate %_Globals_ Block
335 OpDecorate %_ DescriptorSet 0
336 OpDecorate %_ Binding 0
337 OpDecorate %OutColor Location 0
338 %void = OpTypeVoid
339 %10 = OpTypeFunction %void
340 %float = OpTypeFloat 32
341 %v4float = OpTypeVector %float 4
342 %_ptr_Function_v4float = OpTypePointer Function %v4float
343 %_ptr_Input_v4float = OpTypePointer Input %v4float
344 %In0 = OpVariable %_ptr_Input_v4float Input
345 %_ptr_Input_float = OpTypePointer Input %float
346 %In1 = OpVariable %_ptr_Input_float Input
347 %In2 = OpVariable %_ptr_Input_float Input
348 %uint = OpTypeInt 32 0
349 %_ptr_Function_float = OpTypePointer Function %float
350 %_Globals_ = OpTypeStruct %uint
351 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
352 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
353 %int = OpTypeInt 32 1
354 %int_0 = OpConstant %int 0
355 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
356 %bool = OpTypeBool
357 %uint_0 = OpConstant %uint 0
358 %float_1 = OpConstant %float 1
359 %_ptr_Output_v4float = OpTypePointer Output %v4float
360 %OutColor = OpVariable %_ptr_Output_v4float Output
361 %float_0 = OpConstant %float 0
362 )";
363 
364   const std::string before =
365       R"(%main = OpFunction %void None %11
366 %31 = OpLabel
367 %32 = OpLoad %v4float %In0
368 %33 = OpLoad %float %In1
369 %34 = OpLoad %float %In2
370 %35 = OpFAdd %float %33 %34
371 %51 = OpCompositeInsert %v4float %35 %32 2
372 %37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
373 %38 = OpLoad %uint %37
374 %39 = OpINotEqual %bool %38 %uint_0
375 OpSelectionMerge %40 None
376 OpBranchConditional %39 %41 %40
377 %41 = OpLabel
378 %53 = OpCompositeInsert %v4float %float_1 %51 3
379 OpBranch %40
380 %40 = OpLabel
381 %60 = OpPhi %v4float %51 %31 %53 %41
382 %55 = OpCompositeExtract %float %60 0
383 %57 = OpCompositeExtract %float %60 1
384 %59 = OpCompositeExtract %float %60 3
385 %49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59
386 OpStore %OutColor %49
387 OpReturn
388 OpFunctionEnd
389 )";
390 
391   const std::string after =
392       R"(%main = OpFunction %void None %10
393 %27 = OpLabel
394 %28 = OpLoad %v4float %In0
395 %33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
396 %34 = OpLoad %uint %33
397 %35 = OpINotEqual %bool %34 %uint_0
398 OpSelectionMerge %36 None
399 OpBranchConditional %35 %37 %36
400 %37 = OpLabel
401 %38 = OpCompositeInsert %v4float %float_1 %28 3
402 OpBranch %36
403 %36 = OpLabel
404 %39 = OpPhi %v4float %28 %27 %38 %37
405 %40 = OpCompositeExtract %float %39 0
406 %41 = OpCompositeExtract %float %39 1
407 %42 = OpCompositeExtract %float %39 3
408 %43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42
409 OpStore %OutColor %43
410 OpReturn
411 OpFunctionEnd
412 )";
413 
414   SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
415                                             after_predefs + after, true, true);
416 }
417 
TEST_F(DeadInsertElimTest,DeadInsertTwoPasses)418 TEST_F(DeadInsertElimTest, DeadInsertTwoPasses) {
419   // Dead insert which requires two passes to eliminate
420   //
421   // Note: The SPIR-V assembly has had store/load elimination
422   // performed to allow the inserts and extracts to directly
423   // reference each other.
424   //
425   // #version 450
426   //
427   // layout (location=0) in vec4 In0;
428   // layout (location=1) in float In1;
429   // layout (location=2) in float In2;
430   // layout (location=0) out vec4 OutColor;
431   //
432   // layout(std140, binding = 0 ) uniform _Globals_
433   // {
434   //     bool g_b;
435   //     bool g_b2;
436   // };
437   //
438   // void main()
439   // {
440   //     vec4 v1, v2;
441   //     v1 = In0;
442   //     v1.y = In1 + In2; // dead, second pass
443   //     if (g_b) v1.x = 1.0;
444   //     v2.x = v1.x;
445   //     v2.y = v1.y; // dead, first pass
446   //     if (g_b2) v2.x = 0.0;
447   //     OutColor = vec4(v2.x,v2.x,0.0,1.0);
448   // }
449 
450   const std::string before_predefs =
451       R"(OpCapability Shader
452 %1 = OpExtInstImport "GLSL.std.450"
453 OpMemoryModel Logical GLSL450
454 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
455 OpExecutionMode %main OriginUpperLeft
456 OpSource GLSL 450
457 OpName %main "main"
458 OpName %In0 "In0"
459 OpName %In1 "In1"
460 OpName %In2 "In2"
461 OpName %_Globals_ "_Globals_"
462 OpMemberName %_Globals_ 0 "g_b"
463 OpMemberName %_Globals_ 1 "g_b2"
464 OpName %_ ""
465 OpName %OutColor "OutColor"
466 OpDecorate %In0 Location 0
467 OpDecorate %In1 Location 1
468 OpDecorate %In2 Location 2
469 OpMemberDecorate %_Globals_ 0 Offset 0
470 OpMemberDecorate %_Globals_ 1 Offset 4
471 OpDecorate %_Globals_ Block
472 OpDecorate %_ DescriptorSet 0
473 OpDecorate %_ Binding 0
474 OpDecorate %OutColor Location 0
475 %void = OpTypeVoid
476 %10 = OpTypeFunction %void
477 %float = OpTypeFloat 32
478 %v4float = OpTypeVector %float 4
479 %_ptr_Function_v4float = OpTypePointer Function %v4float
480 %_ptr_Input_v4float = OpTypePointer Input %v4float
481 %In0 = OpVariable %_ptr_Input_v4float Input
482 %_ptr_Input_float = OpTypePointer Input %float
483 %In1 = OpVariable %_ptr_Input_float Input
484 %In2 = OpVariable %_ptr_Input_float Input
485 %uint = OpTypeInt 32 0
486 %_Globals_ = OpTypeStruct %uint %uint
487 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
488 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
489 %int = OpTypeInt 32 1
490 %int_0 = OpConstant %int 0
491 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
492 %bool = OpTypeBool
493 %uint_0 = OpConstant %uint 0
494 %float_1 = OpConstant %float 1
495 %int_1 = OpConstant %int 1
496 %float_0 = OpConstant %float 0
497 %_ptr_Output_v4float = OpTypePointer Output %v4float
498 %OutColor = OpVariable %_ptr_Output_v4float Output
499 %27 = OpUndef %v4float
500 )";
501 
502   const std::string after_predefs =
503       R"(OpCapability Shader
504 %1 = OpExtInstImport "GLSL.std.450"
505 OpMemoryModel Logical GLSL450
506 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
507 OpExecutionMode %main OriginUpperLeft
508 OpSource GLSL 450
509 OpName %main "main"
510 OpName %In0 "In0"
511 OpName %In1 "In1"
512 OpName %In2 "In2"
513 OpName %_Globals_ "_Globals_"
514 OpMemberName %_Globals_ 0 "g_b"
515 OpMemberName %_Globals_ 1 "g_b2"
516 OpName %_ ""
517 OpName %OutColor "OutColor"
518 OpDecorate %In0 Location 0
519 OpDecorate %In1 Location 1
520 OpDecorate %In2 Location 2
521 OpMemberDecorate %_Globals_ 0 Offset 0
522 OpMemberDecorate %_Globals_ 1 Offset 4
523 OpDecorate %_Globals_ Block
524 OpDecorate %_ DescriptorSet 0
525 OpDecorate %_ Binding 0
526 OpDecorate %OutColor Location 0
527 %void = OpTypeVoid
528 %10 = OpTypeFunction %void
529 %float = OpTypeFloat 32
530 %v4float = OpTypeVector %float 4
531 %_ptr_Function_v4float = OpTypePointer Function %v4float
532 %_ptr_Input_v4float = OpTypePointer Input %v4float
533 %In0 = OpVariable %_ptr_Input_v4float Input
534 %_ptr_Input_float = OpTypePointer Input %float
535 %In1 = OpVariable %_ptr_Input_float Input
536 %In2 = OpVariable %_ptr_Input_float Input
537 %uint = OpTypeInt 32 0
538 %_Globals_ = OpTypeStruct %uint %uint
539 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
540 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
541 %int = OpTypeInt 32 1
542 %int_0 = OpConstant %int 0
543 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
544 %bool = OpTypeBool
545 %uint_0 = OpConstant %uint 0
546 %float_1 = OpConstant %float 1
547 %int_1 = OpConstant %int 1
548 %float_0 = OpConstant %float 0
549 %_ptr_Output_v4float = OpTypePointer Output %v4float
550 %OutColor = OpVariable %_ptr_Output_v4float Output
551 %27 = OpUndef %v4float
552 )";
553 
554   const std::string before =
555       R"(%main = OpFunction %void None %10
556 %28 = OpLabel
557 %29 = OpLoad %v4float %In0
558 %30 = OpLoad %float %In1
559 %31 = OpLoad %float %In2
560 %32 = OpFAdd %float %30 %31
561 %33 = OpCompositeInsert %v4float %32 %29 1
562 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
563 %35 = OpLoad %uint %34
564 %36 = OpINotEqual %bool %35 %uint_0
565 OpSelectionMerge %37 None
566 OpBranchConditional %36 %38 %37
567 %38 = OpLabel
568 %39 = OpCompositeInsert %v4float %float_1 %33 0
569 OpBranch %37
570 %37 = OpLabel
571 %40 = OpPhi %v4float %33 %28 %39 %38
572 %41 = OpCompositeExtract %float %40 0
573 %42 = OpCompositeInsert %v4float %41 %27 0
574 %43 = OpCompositeExtract %float %40 1
575 %44 = OpCompositeInsert %v4float %43 %42 1
576 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
577 %46 = OpLoad %uint %45
578 %47 = OpINotEqual %bool %46 %uint_0
579 OpSelectionMerge %48 None
580 OpBranchConditional %47 %49 %48
581 %49 = OpLabel
582 %50 = OpCompositeInsert %v4float %float_0 %44 0
583 OpBranch %48
584 %48 = OpLabel
585 %51 = OpPhi %v4float %44 %37 %50 %49
586 %52 = OpCompositeExtract %float %51 0
587 %53 = OpCompositeExtract %float %51 0
588 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
589 OpStore %OutColor %54
590 OpReturn
591 OpFunctionEnd
592 )";
593 
594   const std::string after =
595       R"(%main = OpFunction %void None %10
596 %28 = OpLabel
597 %29 = OpLoad %v4float %In0
598 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
599 %35 = OpLoad %uint %34
600 %36 = OpINotEqual %bool %35 %uint_0
601 OpSelectionMerge %37 None
602 OpBranchConditional %36 %38 %37
603 %38 = OpLabel
604 %39 = OpCompositeInsert %v4float %float_1 %29 0
605 OpBranch %37
606 %37 = OpLabel
607 %40 = OpPhi %v4float %29 %28 %39 %38
608 %41 = OpCompositeExtract %float %40 0
609 %42 = OpCompositeInsert %v4float %41 %27 0
610 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
611 %46 = OpLoad %uint %45
612 %47 = OpINotEqual %bool %46 %uint_0
613 OpSelectionMerge %48 None
614 OpBranchConditional %47 %49 %48
615 %49 = OpLabel
616 %50 = OpCompositeInsert %v4float %float_0 %42 0
617 OpBranch %48
618 %48 = OpLabel
619 %51 = OpPhi %v4float %42 %37 %50 %49
620 %52 = OpCompositeExtract %float %51 0
621 %53 = OpCompositeExtract %float %51 0
622 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
623 OpStore %OutColor %54
624 OpReturn
625 OpFunctionEnd
626 )";
627 
628   SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
629                                             after_predefs + after, true, true);
630 }
631 
TEST_F(DeadInsertElimTest,DebugInsertAfterInsertElim)632 TEST_F(DeadInsertElimTest, DebugInsertAfterInsertElim) {
633   // With two insertions to the same offset, the first is dead.
634   //
635   // Note: The SPIR-V assembly has had store/load elimination
636   // performed to allow the inserts and extracts to directly
637   // reference each other.
638   //
639   // #version 450
640   //
641   // layout (location=0) in float In0;
642   // layout (location=1) in float In1;
643   // layout (location=2) in vec2 In2;
644   // layout (location=0) out vec4 OutColor;
645   //
646   // void main()
647   // {
648   //     vec2 v = In2;
649   //     v.x = In0 + In1; // dead
650   //     v.x = 0.0;
651   //     OutColor = v.xyxy;
652   // }
653 
654   const std::string text =
655       R"(OpCapability Shader
656 %1 = OpExtInstImport "GLSL.std.450"
657 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
658 OpMemoryModel Logical GLSL450
659 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
660 OpExecutionMode %main OriginUpperLeft
661 OpSource GLSL 450
662 %file_name = OpString "test"
663 %float_name = OpString "float"
664 %main_name = OpString "main"
665 %f_name = OpString "f"
666 OpName %main "main"
667 OpName %In2 "In2"
668 OpName %In0 "In0"
669 OpName %In1 "In1"
670 OpName %OutColor "OutColor"
671 OpName %_Globals_ "_Globals_"
672 OpMemberName %_Globals_ 0 "g_b"
673 OpMemberName %_Globals_ 1 "g_n"
674 OpName %_ ""
675 OpDecorate %In2 Location 2
676 OpDecorate %In0 Location 0
677 OpDecorate %In1 Location 1
678 OpDecorate %OutColor Location 0
679 OpMemberDecorate %_Globals_ 0 Offset 0
680 OpMemberDecorate %_Globals_ 1 Offset 4
681 OpDecorate %_Globals_ Block
682 OpDecorate %_ DescriptorSet 0
683 OpDecorate %_ Binding 0
684 %void = OpTypeVoid
685 %11 = OpTypeFunction %void
686 %float = OpTypeFloat 32
687 %v2float = OpTypeVector %float 2
688 %_ptr_Function_v2float = OpTypePointer Function %v2float
689 %_ptr_Input_v2float = OpTypePointer Input %v2float
690 %In2 = OpVariable %_ptr_Input_v2float Input
691 %_ptr_Input_float = OpTypePointer Input %float
692 %In0 = OpVariable %_ptr_Input_float Input
693 %In1 = OpVariable %_ptr_Input_float Input
694 %uint = OpTypeInt 32 0
695 %uint_32 = OpConstant %uint 32
696 %_ptr_Function_float = OpTypePointer Function %float
697 %float_0 = OpConstant %float 0
698 %v4float = OpTypeVector %float 4
699 %_ptr_Output_v4float = OpTypePointer Output %v4float
700 %OutColor = OpVariable %_ptr_Output_v4float Output
701 %int = OpTypeInt 32 1
702 %_Globals_ = OpTypeStruct %uint %int
703 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
704 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
705 
706 %nullexpr = OpExtInst %void %ext DebugExpression
707 %src = OpExtInst %void %ext DebugSource %file_name
708 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
709 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
710 %dbg_v2f = OpExtInst %void %ext DebugTypeVector %dbg_tf 2
711 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
712 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 0 %main
713 %dbg_foo = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v2f %src 0 0 %dbg_main FlagIsLocal
714 
715 %main = OpFunction %void None %11
716 %25 = OpLabel
717 %26 = OpLoad %v2float %In2
718 %27 = OpLoad %float %In0
719 %28 = OpLoad %float %In1
720 %29 = OpFAdd %float %27 %28
721 
722 ; CHECK:      [[repl:%\w+]] = OpLoad %v2float %In2
723 ; CHECK-NOT:  OpCompositeInsert
724 ; CHECK:      DebugValue {{%\w+}} [[repl:%\w+]]
725 ; CHECK-NEXT: OpCompositeInsert %v2float %float_0 [[repl]] 0
726 %35 = OpCompositeInsert %v2float %29 %26 0
727 %value = OpExtInst %void %ext DebugValue %dbg_foo %35 %nullexpr
728 %37 = OpCompositeInsert %v2float %float_0 %35 0
729 
730 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
731 OpStore %OutColor %33
732 OpReturn
733 OpFunctionEnd
734 )";
735 
736   SinglePassRunAndMatch<DeadInsertElimPass>(text, true);
737 }
738 
739 // TODO(greg-lunarg): Add tests to verify handling of these cases:
740 //
741 
742 }  // namespace
743 }  // namespace opt
744 }  // namespace spvtools
745