1 // Copyright (c) 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 
17 #include "test/opt/pass_fixture.h"
18 #include "test/opt/pass_utils.h"
19 
20 namespace spvtools {
21 namespace opt {
22 namespace {
23 
24 using VectorDCETest = PassTest<::testing::Test>;
25 
TEST_F(VectorDCETest,InsertAfterInsertElim)26 TEST_F(VectorDCETest, InsertAfterInsertElim) {
27   // With two insertions to the same offset, the first is dead.
28   //
29   // Note: The SPIR-V assembly has had store/load elimination
30   // performed to allow the inserts and extracts to directly
31   // reference each other.
32   //
33   // #version 450
34   //
35   // layout (location=0) in float In0;
36   // layout (location=1) in float In1;
37   // layout (location=2) in vec2 In2;
38   // layout (location=0) out vec4 OutColor;
39   //
40   // void main()
41   // {
42   //     vec2 v = In2;
43   //     v.x = In0 + In1; // dead
44   //     v.x = 0.0;
45   //     OutColor = v.xyxy;
46   // }
47 
48   const std::string before_predefs =
49       R"(OpCapability Shader
50 %1 = OpExtInstImport "GLSL.std.450"
51 OpMemoryModel Logical GLSL450
52 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
53 OpExecutionMode %main OriginUpperLeft
54 OpSource GLSL 450
55 OpName %main "main"
56 OpName %In2 "In2"
57 OpName %In0 "In0"
58 OpName %In1 "In1"
59 OpName %OutColor "OutColor"
60 OpName %_Globals_ "_Globals_"
61 OpMemberName %_Globals_ 0 "g_b"
62 OpMemberName %_Globals_ 1 "g_n"
63 OpName %_ ""
64 OpDecorate %In2 Location 2
65 OpDecorate %In0 Location 0
66 OpDecorate %In1 Location 1
67 OpDecorate %OutColor Location 0
68 OpMemberDecorate %_Globals_ 0 Offset 0
69 OpMemberDecorate %_Globals_ 1 Offset 4
70 OpDecorate %_Globals_ Block
71 OpDecorate %_ DescriptorSet 0
72 OpDecorate %_ Binding 0
73 %void = OpTypeVoid
74 %11 = OpTypeFunction %void
75 %float = OpTypeFloat 32
76 %v2float = OpTypeVector %float 2
77 %_ptr_Function_v2float = OpTypePointer Function %v2float
78 %_ptr_Input_v2float = OpTypePointer Input %v2float
79 %In2 = OpVariable %_ptr_Input_v2float Input
80 %_ptr_Input_float = OpTypePointer Input %float
81 %In0 = OpVariable %_ptr_Input_float Input
82 %In1 = OpVariable %_ptr_Input_float Input
83 %uint = OpTypeInt 32 0
84 %_ptr_Function_float = OpTypePointer Function %float
85 %float_0 = OpConstant %float 0
86 %v4float = OpTypeVector %float 4
87 %_ptr_Output_v4float = OpTypePointer Output %v4float
88 %OutColor = OpVariable %_ptr_Output_v4float Output
89 %int = OpTypeInt 32 1
90 %_Globals_ = OpTypeStruct %uint %int
91 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
92 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
93 )";
94 
95   const std::string after_predefs =
96       R"(OpCapability Shader
97 %1 = OpExtInstImport "GLSL.std.450"
98 OpMemoryModel Logical GLSL450
99 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
100 OpExecutionMode %main OriginUpperLeft
101 OpSource GLSL 450
102 OpName %main "main"
103 OpName %In2 "In2"
104 OpName %In0 "In0"
105 OpName %In1 "In1"
106 OpName %OutColor "OutColor"
107 OpName %_Globals_ "_Globals_"
108 OpMemberName %_Globals_ 0 "g_b"
109 OpMemberName %_Globals_ 1 "g_n"
110 OpName %_ ""
111 OpDecorate %In2 Location 2
112 OpDecorate %In0 Location 0
113 OpDecorate %In1 Location 1
114 OpDecorate %OutColor Location 0
115 OpMemberDecorate %_Globals_ 0 Offset 0
116 OpMemberDecorate %_Globals_ 1 Offset 4
117 OpDecorate %_Globals_ Block
118 OpDecorate %_ DescriptorSet 0
119 OpDecorate %_ Binding 0
120 %void = OpTypeVoid
121 %10 = OpTypeFunction %void
122 %float = OpTypeFloat 32
123 %v2float = OpTypeVector %float 2
124 %_ptr_Function_v2float = OpTypePointer Function %v2float
125 %_ptr_Input_v2float = OpTypePointer Input %v2float
126 %In2 = OpVariable %_ptr_Input_v2float Input
127 %_ptr_Input_float = OpTypePointer Input %float
128 %In0 = OpVariable %_ptr_Input_float Input
129 %In1 = OpVariable %_ptr_Input_float Input
130 %uint = OpTypeInt 32 0
131 %_ptr_Function_float = OpTypePointer Function %float
132 %float_0 = OpConstant %float 0
133 %v4float = OpTypeVector %float 4
134 %_ptr_Output_v4float = OpTypePointer Output %v4float
135 %OutColor = OpVariable %_ptr_Output_v4float Output
136 %int = OpTypeInt 32 1
137 %_Globals_ = OpTypeStruct %uint %int
138 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
139 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
140 )";
141 
142   const std::string before =
143       R"(%main = OpFunction %void None %11
144 %25 = OpLabel
145 %26 = OpLoad %v2float %In2
146 %27 = OpLoad %float %In0
147 %28 = OpLoad %float %In1
148 %29 = OpFAdd %float %27 %28
149 %35 = OpCompositeInsert %v2float %29 %26 0
150 %37 = OpCompositeInsert %v2float %float_0 %35 0
151 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
152 OpStore %OutColor %33
153 OpReturn
154 OpFunctionEnd
155 )";
156 
157   const std::string after =
158       R"(%main = OpFunction %void None %10
159 %23 = OpLabel
160 %24 = OpLoad %v2float %In2
161 %25 = OpLoad %float %In0
162 %26 = OpLoad %float %In1
163 %27 = OpFAdd %float %25 %26
164 %28 = OpCompositeInsert %v2float %27 %24 0
165 %29 = OpCompositeInsert %v2float %float_0 %24 0
166 %30 = OpVectorShuffle %v4float %29 %29 0 1 0 1
167 OpStore %OutColor %30
168 OpReturn
169 OpFunctionEnd
170 )";
171 
172   SinglePassRunAndCheck<VectorDCE>(before_predefs + before,
173                                    after_predefs + after, true, true);
174 }
175 
TEST_F(VectorDCETest,DeadInsertInChainWithPhi)176 TEST_F(VectorDCETest, DeadInsertInChainWithPhi) {
177   // Dead insert eliminated with phi in insertion chain.
178   //
179   // Note: The SPIR-V assembly has had store/load elimination
180   // performed to allow the inserts and extracts to directly
181   // reference each other.
182   //
183   // #version 450
184   //
185   // layout (location=0) in vec4 In0;
186   // layout (location=1) in float In1;
187   // layout (location=2) in float In2;
188   // layout (location=0) out vec4 OutColor;
189   //
190   // layout(std140, binding = 0 ) uniform _Globals_
191   // {
192   //     bool g_b;
193   // };
194   //
195   // void main()
196   // {
197   //     vec4 v = In0;
198   //     v.z = In1 + In2;
199   //     if (g_b) v.w = 1.0;
200   //     OutColor = vec4(v.x,v.y,0.0,v.w);
201   // }
202 
203   const std::string before_predefs =
204       R"(OpCapability Shader
205 %1 = OpExtInstImport "GLSL.std.450"
206 OpMemoryModel Logical GLSL450
207 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
208 OpExecutionMode %main OriginUpperLeft
209 OpSource GLSL 450
210 OpName %main "main"
211 OpName %In0 "In0"
212 OpName %In1 "In1"
213 OpName %In2 "In2"
214 OpName %_Globals_ "_Globals_"
215 OpMemberName %_Globals_ 0 "g_b"
216 OpName %_ ""
217 OpName %OutColor "OutColor"
218 OpDecorate %In0 Location 0
219 OpDecorate %In1 Location 1
220 OpDecorate %In2 Location 2
221 OpMemberDecorate %_Globals_ 0 Offset 0
222 OpDecorate %_Globals_ Block
223 OpDecorate %_ DescriptorSet 0
224 OpDecorate %_ Binding 0
225 OpDecorate %OutColor Location 0
226 %void = OpTypeVoid
227 %11 = OpTypeFunction %void
228 %float = OpTypeFloat 32
229 %v4float = OpTypeVector %float 4
230 %_ptr_Function_v4float = OpTypePointer Function %v4float
231 %_ptr_Input_v4float = OpTypePointer Input %v4float
232 %In0 = OpVariable %_ptr_Input_v4float Input
233 %_ptr_Input_float = OpTypePointer Input %float
234 %In1 = OpVariable %_ptr_Input_float Input
235 %In2 = OpVariable %_ptr_Input_float Input
236 %uint = OpTypeInt 32 0
237 %_ptr_Function_float = OpTypePointer Function %float
238 %_Globals_ = OpTypeStruct %uint
239 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
240 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
241 %int = OpTypeInt 32 1
242 %int_0 = OpConstant %int 0
243 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
244 %bool = OpTypeBool
245 %uint_0 = OpConstant %uint 0
246 %float_1 = OpConstant %float 1
247 %_ptr_Output_v4float = OpTypePointer Output %v4float
248 %OutColor = OpVariable %_ptr_Output_v4float Output
249 %float_0 = OpConstant %float 0
250 )";
251 
252   const std::string after_predefs =
253       R"(OpCapability Shader
254 %1 = OpExtInstImport "GLSL.std.450"
255 OpMemoryModel Logical GLSL450
256 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
257 OpExecutionMode %main OriginUpperLeft
258 OpSource GLSL 450
259 OpName %main "main"
260 OpName %In0 "In0"
261 OpName %In1 "In1"
262 OpName %In2 "In2"
263 OpName %_Globals_ "_Globals_"
264 OpMemberName %_Globals_ 0 "g_b"
265 OpName %_ ""
266 OpName %OutColor "OutColor"
267 OpDecorate %In0 Location 0
268 OpDecorate %In1 Location 1
269 OpDecorate %In2 Location 2
270 OpMemberDecorate %_Globals_ 0 Offset 0
271 OpDecorate %_Globals_ Block
272 OpDecorate %_ DescriptorSet 0
273 OpDecorate %_ Binding 0
274 OpDecorate %OutColor Location 0
275 %void = OpTypeVoid
276 %10 = OpTypeFunction %void
277 %float = OpTypeFloat 32
278 %v4float = OpTypeVector %float 4
279 %_ptr_Function_v4float = OpTypePointer Function %v4float
280 %_ptr_Input_v4float = OpTypePointer Input %v4float
281 %In0 = OpVariable %_ptr_Input_v4float Input
282 %_ptr_Input_float = OpTypePointer Input %float
283 %In1 = OpVariable %_ptr_Input_float Input
284 %In2 = OpVariable %_ptr_Input_float Input
285 %uint = OpTypeInt 32 0
286 %_ptr_Function_float = OpTypePointer Function %float
287 %_Globals_ = OpTypeStruct %uint
288 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
289 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
290 %int = OpTypeInt 32 1
291 %int_0 = OpConstant %int 0
292 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
293 %bool = OpTypeBool
294 %uint_0 = OpConstant %uint 0
295 %float_1 = OpConstant %float 1
296 %_ptr_Output_v4float = OpTypePointer Output %v4float
297 %OutColor = OpVariable %_ptr_Output_v4float Output
298 %float_0 = OpConstant %float 0
299 )";
300 
301   const std::string before =
302       R"(%main = OpFunction %void None %11
303 %31 = OpLabel
304 %32 = OpLoad %v4float %In0
305 %33 = OpLoad %float %In1
306 %34 = OpLoad %float %In2
307 %35 = OpFAdd %float %33 %34
308 %51 = OpCompositeInsert %v4float %35 %32 2
309 %37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
310 %38 = OpLoad %uint %37
311 %39 = OpINotEqual %bool %38 %uint_0
312 OpSelectionMerge %40 None
313 OpBranchConditional %39 %41 %40
314 %41 = OpLabel
315 %53 = OpCompositeInsert %v4float %float_1 %51 3
316 OpBranch %40
317 %40 = OpLabel
318 %60 = OpPhi %v4float %51 %31 %53 %41
319 %55 = OpCompositeExtract %float %60 0
320 %57 = OpCompositeExtract %float %60 1
321 %59 = OpCompositeExtract %float %60 3
322 %49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59
323 OpStore %OutColor %49
324 OpReturn
325 OpFunctionEnd
326 )";
327 
328   const std::string after =
329       R"(%main = OpFunction %void None %10
330 %27 = OpLabel
331 %28 = OpLoad %v4float %In0
332 %29 = OpLoad %float %In1
333 %30 = OpLoad %float %In2
334 %31 = OpFAdd %float %29 %30
335 %32 = OpCompositeInsert %v4float %31 %28 2
336 %33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
337 %34 = OpLoad %uint %33
338 %35 = OpINotEqual %bool %34 %uint_0
339 OpSelectionMerge %36 None
340 OpBranchConditional %35 %37 %36
341 %37 = OpLabel
342 %38 = OpCompositeInsert %v4float %float_1 %28 3
343 OpBranch %36
344 %36 = OpLabel
345 %39 = OpPhi %v4float %28 %27 %38 %37
346 %40 = OpCompositeExtract %float %39 0
347 %41 = OpCompositeExtract %float %39 1
348 %42 = OpCompositeExtract %float %39 3
349 %43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42
350 OpStore %OutColor %43
351 OpReturn
352 OpFunctionEnd
353 )";
354 
355   SinglePassRunAndCheck<VectorDCE>(before_predefs + before,
356                                    after_predefs + after, true, true);
357 }
358 
TEST_F(VectorDCETest,DeadInsertWithScalars)359 TEST_F(VectorDCETest, DeadInsertWithScalars) {
360   // Dead insert which requires two passes to eliminate
361   //
362   // Note: The SPIR-V assembly has had store/load elimination
363   // performed to allow the inserts and extracts to directly
364   // reference each other.
365   //
366   // #version 450
367   //
368   // layout (location=0) in vec4 In0;
369   // layout (location=1) in float In1;
370   // layout (location=2) in float In2;
371   // layout (location=0) out vec4 OutColor;
372   //
373   // layout(std140, binding = 0 ) uniform _Globals_
374   // {
375   //     bool g_b;
376   //     bool g_b2;
377   // };
378   //
379   // void main()
380   // {
381   //     vec4 v1, v2;
382   //     v1 = In0;
383   //     v1.y = In1 + In2; // dead, second pass
384   //     if (g_b) v1.x = 1.0;
385   //     v2.x = v1.x;
386   //     v2.y = v1.y; // dead, first pass
387   //     if (g_b2) v2.x = 0.0;
388   //     OutColor = vec4(v2.x,v2.x,0.0,1.0);
389   // }
390 
391   const std::string before_predefs =
392       R"(OpCapability Shader
393 %1 = OpExtInstImport "GLSL.std.450"
394 OpMemoryModel Logical GLSL450
395 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
396 OpExecutionMode %main OriginUpperLeft
397 OpSource GLSL 450
398 OpName %main "main"
399 OpName %In0 "In0"
400 OpName %In1 "In1"
401 OpName %In2 "In2"
402 OpName %_Globals_ "_Globals_"
403 OpMemberName %_Globals_ 0 "g_b"
404 OpMemberName %_Globals_ 1 "g_b2"
405 OpName %_ ""
406 OpName %OutColor "OutColor"
407 OpDecorate %In0 Location 0
408 OpDecorate %In1 Location 1
409 OpDecorate %In2 Location 2
410 OpMemberDecorate %_Globals_ 0 Offset 0
411 OpMemberDecorate %_Globals_ 1 Offset 4
412 OpDecorate %_Globals_ Block
413 OpDecorate %_ DescriptorSet 0
414 OpDecorate %_ Binding 0
415 OpDecorate %OutColor Location 0
416 %void = OpTypeVoid
417 %10 = OpTypeFunction %void
418 %float = OpTypeFloat 32
419 %v4float = OpTypeVector %float 4
420 %_ptr_Function_v4float = OpTypePointer Function %v4float
421 %_ptr_Input_v4float = OpTypePointer Input %v4float
422 %In0 = OpVariable %_ptr_Input_v4float Input
423 %_ptr_Input_float = OpTypePointer Input %float
424 %In1 = OpVariable %_ptr_Input_float Input
425 %In2 = OpVariable %_ptr_Input_float Input
426 %uint = OpTypeInt 32 0
427 %_Globals_ = OpTypeStruct %uint %uint
428 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
429 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
430 %int = OpTypeInt 32 1
431 %int_0 = OpConstant %int 0
432 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
433 %bool = OpTypeBool
434 %uint_0 = OpConstant %uint 0
435 %float_1 = OpConstant %float 1
436 %int_1 = OpConstant %int 1
437 %float_0 = OpConstant %float 0
438 %_ptr_Output_v4float = OpTypePointer Output %v4float
439 %OutColor = OpVariable %_ptr_Output_v4float Output
440 %27 = OpUndef %v4float
441 )";
442 
443   const std::string after_predefs =
444       R"(OpCapability Shader
445 %1 = OpExtInstImport "GLSL.std.450"
446 OpMemoryModel Logical GLSL450
447 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
448 OpExecutionMode %main OriginUpperLeft
449 OpSource GLSL 450
450 OpName %main "main"
451 OpName %In0 "In0"
452 OpName %In1 "In1"
453 OpName %In2 "In2"
454 OpName %_Globals_ "_Globals_"
455 OpMemberName %_Globals_ 0 "g_b"
456 OpMemberName %_Globals_ 1 "g_b2"
457 OpName %_ ""
458 OpName %OutColor "OutColor"
459 OpDecorate %In0 Location 0
460 OpDecorate %In1 Location 1
461 OpDecorate %In2 Location 2
462 OpMemberDecorate %_Globals_ 0 Offset 0
463 OpMemberDecorate %_Globals_ 1 Offset 4
464 OpDecorate %_Globals_ Block
465 OpDecorate %_ DescriptorSet 0
466 OpDecorate %_ Binding 0
467 OpDecorate %OutColor Location 0
468 %void = OpTypeVoid
469 %10 = OpTypeFunction %void
470 %float = OpTypeFloat 32
471 %v4float = OpTypeVector %float 4
472 %_ptr_Function_v4float = OpTypePointer Function %v4float
473 %_ptr_Input_v4float = OpTypePointer Input %v4float
474 %In0 = OpVariable %_ptr_Input_v4float Input
475 %_ptr_Input_float = OpTypePointer Input %float
476 %In1 = OpVariable %_ptr_Input_float Input
477 %In2 = OpVariable %_ptr_Input_float Input
478 %uint = OpTypeInt 32 0
479 %_Globals_ = OpTypeStruct %uint %uint
480 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
481 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
482 %int = OpTypeInt 32 1
483 %int_0 = OpConstant %int 0
484 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
485 %bool = OpTypeBool
486 %uint_0 = OpConstant %uint 0
487 %float_1 = OpConstant %float 1
488 %int_1 = OpConstant %int 1
489 %float_0 = OpConstant %float 0
490 %_ptr_Output_v4float = OpTypePointer Output %v4float
491 %OutColor = OpVariable %_ptr_Output_v4float Output
492 %27 = OpUndef %v4float
493 )";
494 
495   const std::string before =
496       R"(%main = OpFunction %void None %10
497 %28 = OpLabel
498 %29 = OpLoad %v4float %In0
499 %30 = OpLoad %float %In1
500 %31 = OpLoad %float %In2
501 %32 = OpFAdd %float %30 %31
502 %33 = OpCompositeInsert %v4float %32 %29 1
503 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
504 %35 = OpLoad %uint %34
505 %36 = OpINotEqual %bool %35 %uint_0
506 OpSelectionMerge %37 None
507 OpBranchConditional %36 %38 %37
508 %38 = OpLabel
509 %39 = OpCompositeInsert %v4float %float_1 %33 0
510 OpBranch %37
511 %37 = OpLabel
512 %40 = OpPhi %v4float %33 %28 %39 %38
513 %41 = OpCompositeExtract %float %40 0
514 %42 = OpCompositeInsert %v4float %41 %27 0
515 %43 = OpCompositeExtract %float %40 1
516 %44 = OpCompositeInsert %v4float %43 %42 1
517 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
518 %46 = OpLoad %uint %45
519 %47 = OpINotEqual %bool %46 %uint_0
520 OpSelectionMerge %48 None
521 OpBranchConditional %47 %49 %48
522 %49 = OpLabel
523 %50 = OpCompositeInsert %v4float %float_0 %44 0
524 OpBranch %48
525 %48 = OpLabel
526 %51 = OpPhi %v4float %44 %37 %50 %49
527 %52 = OpCompositeExtract %float %51 0
528 %53 = OpCompositeExtract %float %51 0
529 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
530 OpStore %OutColor %54
531 OpReturn
532 OpFunctionEnd
533 )";
534 
535   const std::string after =
536       R"(%main = OpFunction %void None %10
537 %28 = OpLabel
538 %29 = OpLoad %v4float %In0
539 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
540 %35 = OpLoad %uint %34
541 %36 = OpINotEqual %bool %35 %uint_0
542 OpSelectionMerge %37 None
543 OpBranchConditional %36 %38 %37
544 %38 = OpLabel
545 %39 = OpCompositeInsert %v4float %float_1 %29 0
546 OpBranch %37
547 %37 = OpLabel
548 %40 = OpPhi %v4float %29 %28 %39 %38
549 %41 = OpCompositeExtract %float %40 0
550 %42 = OpCompositeInsert %v4float %41 %27 0
551 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
552 %46 = OpLoad %uint %45
553 %47 = OpINotEqual %bool %46 %uint_0
554 OpSelectionMerge %48 None
555 OpBranchConditional %47 %49 %48
556 %49 = OpLabel
557 %50 = OpCompositeInsert %v4float %float_0 %42 0
558 OpBranch %48
559 %48 = OpLabel
560 %51 = OpPhi %v4float %42 %37 %50 %49
561 %52 = OpCompositeExtract %float %51 0
562 %53 = OpCompositeExtract %float %51 0
563 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
564 OpStore %OutColor %54
565 OpReturn
566 OpFunctionEnd
567 )";
568 
569   SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
570                                             after_predefs + after, true, true);
571 }
572 
TEST_F(VectorDCETest,InsertObjectLive)573 TEST_F(VectorDCETest, InsertObjectLive) {
574   // Make sure that the object being inserted in an OpCompositeInsert
575   // is not removed when it is uses later on.
576   const std::string before =
577       R"(OpCapability Shader
578 %1 = OpExtInstImport "GLSL.std.450"
579 OpMemoryModel Logical GLSL450
580 OpEntryPoint Fragment %main "main" %In0 %In1 %OutColor
581 OpExecutionMode %main OriginUpperLeft
582 OpSource GLSL 450
583 OpName %main "main"
584 OpName %In0 "In0"
585 OpName %In1 "In1"
586 OpName %OutColor "OutColor"
587 OpDecorate %In0 Location 0
588 OpDecorate %In1 Location 1
589 OpDecorate %OutColor Location 0
590 %void = OpTypeVoid
591 %10 = OpTypeFunction %void
592 %float = OpTypeFloat 32
593 %v4float = OpTypeVector %float 4
594 %_ptr_Input_v4float = OpTypePointer Input %v4float
595 %In0 = OpVariable %_ptr_Input_v4float Input
596 %_ptr_Input_float = OpTypePointer Input %float
597 %In1 = OpVariable %_ptr_Input_float Input
598 %_ptr_Output_v4float = OpTypePointer Output %v4float
599 %OutColor = OpVariable %_ptr_Output_v4float Output
600 %main = OpFunction %void None %10
601 %28 = OpLabel
602 %29 = OpLoad %v4float %In0
603 %30 = OpLoad %float %In1
604 %33 = OpCompositeInsert %v4float %30 %29 1
605 OpStore %OutColor %33
606 OpReturn
607 OpFunctionEnd
608 )";
609 
610   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
611   SinglePassRunAndCheck<DeadInsertElimPass>(before, before, true, true);
612 }
613 
TEST_F(VectorDCETest,DeadInsertInCycle)614 TEST_F(VectorDCETest, DeadInsertInCycle) {
615   // Dead insert in chain with cycle. Demonstrates analysis can handle
616   // cycles in chains going through scalars intermediate values.
617   //
618   // Note: The SPIR-V assembly has had store/load elimination
619   // performed to allow the inserts and extracts to directly
620   // reference each other.
621   //
622   // #version 450
623   //
624   // layout (location=0) in vec4 In0;
625   // layout (location=1) in float In1;
626   // layout (location=2) in float In2;
627   // layout (location=0) out vec4 OutColor;
628   //
629   // layout(std140, binding = 0 ) uniform _Globals_
630   // {
631   //     int g_n  ;
632   // };
633   //
634   // void main()
635   // {
636   //     vec2 v = vec2(0.0, 1.0);
637   //     for (int i = 0; i < g_n; i++) {
638   //       v.x = v.x + 1;
639   //       v.y = v.y * 0.9; // dead
640   //     }
641   //     OutColor = vec4(v.x);
642   // }
643 
644   const std::string assembly =
645       R"(
646 ; CHECK: [[init_val:%\w+]] = OpConstantComposite %v2float %float_0 %float_1
647 ; CHECK: [[undef:%\w+]] = OpUndef %v2float
648 ; CHECK: OpFunction
649 ; CHECK: [[entry_lab:%\w+]] = OpLabel
650 ; CHECK: [[loop_header:%\w+]] = OpLabel
651 ; CHECK: OpPhi %v2float [[init_val]] [[entry_lab]] [[x_insert:%\w+]] {{%\w+}}
652 ; CHECK: [[x_insert:%\w+]] = OpCompositeInsert %v2float %43 [[undef]] 0
653 OpCapability Shader
654 %1 = OpExtInstImport "GLSL.std.450"
655 OpMemoryModel Logical GLSL450
656 OpEntryPoint Fragment %main "main" %OutColor %In0 %In1 %In2
657 OpExecutionMode %main OriginUpperLeft
658 OpSource GLSL 450
659 OpName %main "main"
660 OpName %_Globals_ "_Globals_"
661 OpMemberName %_Globals_ 0 "g_n"
662 OpName %_ ""
663 OpName %OutColor "OutColor"
664 OpName %In0 "In0"
665 OpName %In1 "In1"
666 OpName %In2 "In2"
667 OpMemberDecorate %_Globals_ 0 Offset 0
668 OpDecorate %_Globals_ Block
669 OpDecorate %_ DescriptorSet 0
670 OpDecorate %_ Binding 0
671 OpDecorate %OutColor Location 0
672 OpDecorate %In0 Location 0
673 OpDecorate %In1 Location 1
674 OpDecorate %In2 Location 2
675 %void = OpTypeVoid
676 %10 = OpTypeFunction %void
677 %float = OpTypeFloat 32
678 %v2float = OpTypeVector %float 2
679 %_ptr_Function_v2float = OpTypePointer Function %v2float
680 %float_0 = OpConstant %float 0
681 %float_1 = OpConstant %float 1
682 %16 = OpConstantComposite %v2float %float_0 %float_1
683 %int = OpTypeInt 32 1
684 %_ptr_Function_int = OpTypePointer Function %int
685 %int_0 = OpConstant %int 0
686 %_Globals_ = OpTypeStruct %int
687 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
688 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
689 %_ptr_Uniform_int = OpTypePointer Uniform %int
690 %bool = OpTypeBool
691 %float_0_75 = OpConstant %float 0.75
692 %int_1 = OpConstant %int 1
693 %v4float = OpTypeVector %float 4
694 %_ptr_Output_v4float = OpTypePointer Output %v4float
695 %OutColor = OpVariable %_ptr_Output_v4float Output
696 %_ptr_Input_v4float = OpTypePointer Input %v4float
697 %In0 = OpVariable %_ptr_Input_v4float Input
698 %_ptr_Input_float = OpTypePointer Input %float
699 %In1 = OpVariable %_ptr_Input_float Input
700 %In2 = OpVariable %_ptr_Input_float Input
701 %main = OpFunction %void None %10
702 %29 = OpLabel
703 OpBranch %30
704 %30 = OpLabel
705 %31 = OpPhi %v2float %16 %29 %32 %33
706 %34 = OpPhi %int %int_0 %29 %35 %33
707 OpLoopMerge %36 %33 None
708 OpBranch %37
709 %37 = OpLabel
710 %38 = OpAccessChain %_ptr_Uniform_int %_ %int_0
711 %39 = OpLoad %int %38
712 %40 = OpSLessThan %bool %34 %39
713 OpBranchConditional %40 %41 %36
714 %41 = OpLabel
715 %42 = OpCompositeExtract %float %31 0
716 %43 = OpFAdd %float %42 %float_1
717 %44 = OpCompositeInsert %v2float %43 %31 0
718 %45 = OpCompositeExtract %float %44 1
719 %46 = OpFMul %float %45 %float_0_75
720 %32 = OpCompositeInsert %v2float %46 %44 1
721 OpBranch %33
722 %33 = OpLabel
723 %35 = OpIAdd %int %34 %int_1
724 OpBranch %30
725 %36 = OpLabel
726 %47 = OpCompositeExtract %float %31 0
727 %48 = OpCompositeConstruct %v4float %47 %47 %47 %47
728 OpStore %OutColor %48
729 OpReturn
730 OpFunctionEnd
731 )";
732 
733   SinglePassRunAndMatch<VectorDCE>(assembly, true);
734 }
735 
TEST_F(VectorDCETest,DeadLoadFeedingCompositeConstruct)736 TEST_F(VectorDCETest, DeadLoadFeedingCompositeConstruct) {
737   // Detach the loads feeding the CompositeConstruct for the unused elements.
738   // TODO: Implement the rewrite for CompositeConstruct.
739 
740   const std::string assembly =
741       R"(
742 ; CHECK: [[undef:%\w+]] = OpUndef %float
743 ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Input_float %In0 %uint_2
744 ; CHECK: [[load:%\w+]] = OpLoad %float [[ac]]
745 ; CHECK: OpCompositeConstruct %v3float [[load]] [[undef]] [[undef]]
746 OpCapability Shader
747 %1 = OpExtInstImport "GLSL.std.450"
748 OpMemoryModel Logical GLSL450
749 OpEntryPoint Fragment %main "main" %In0 %OutColor
750 OpExecutionMode %main OriginUpperLeft
751 OpSource GLSL 450
752 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
753 OpSourceExtension "GL_GOOGLE_include_directive"
754 OpName %main "main"
755 OpName %In0 "In0"
756 OpName %OutColor "OutColor"
757 OpDecorate %In0 Location 0
758 OpDecorate %OutColor Location 0
759 %void = OpTypeVoid
760 %6 = OpTypeFunction %void
761 %float = OpTypeFloat 32
762 %v4float = OpTypeVector %float 4
763 %_ptr_Input_v4float = OpTypePointer Input %v4float
764 %In0 = OpVariable %_ptr_Input_v4float Input
765 %uint = OpTypeInt 32 0
766 %uint_0 = OpConstant %uint 0
767 %_ptr_Input_float = OpTypePointer Input %float
768 %uint_1 = OpConstant %uint 1
769 %uint_2 = OpConstant %uint 2
770 %v3float = OpTypeVector %float 3
771 %int = OpTypeInt 32 1
772 %int_0 = OpConstant %int 0
773 %int_20 = OpConstant %int 20
774 %bool = OpTypeBool
775 %float_1 = OpConstant %float 1
776 %int_1 = OpConstant %int 1
777 %_ptr_Output_v4float = OpTypePointer Output %v4float
778 %OutColor = OpVariable %_ptr_Output_v4float Output
779 %23 = OpUndef %v3float
780 %main = OpFunction %void None %6
781 %24 = OpLabel
782 %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
783 %26 = OpLoad %float %25
784 %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
785 %28 = OpLoad %float %27
786 %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
787 %30 = OpLoad %float %29
788 %31 = OpCompositeConstruct %v3float %30 %28 %26
789 OpBranch %32
790 %32 = OpLabel
791 %33 = OpPhi %v3float %31 %24 %34 %35
792 %36 = OpPhi %int %int_0 %24 %37 %35
793 OpLoopMerge %38 %35 None
794 OpBranch %39
795 %39 = OpLabel
796 %40 = OpSLessThan %bool %36 %int_20
797 OpBranchConditional %40 %41 %38
798 %41 = OpLabel
799 %42 = OpCompositeExtract %float %33 0
800 %43 = OpFAdd %float %42 %float_1
801 %34 = OpCompositeInsert %v3float %43 %33 0
802 OpBranch %35
803 %35 = OpLabel
804 %37 = OpIAdd %int %36 %int_1
805 OpBranch %32
806 %38 = OpLabel
807 %44 = OpCompositeExtract %float %33 0
808 %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
809 OpStore %OutColor %45
810 OpReturn
811 OpFunctionEnd
812 )";
813 
814   SinglePassRunAndMatch<VectorDCE>(assembly, true);
815 }
816 
TEST_F(VectorDCETest,DeadLoadFeedingVectorShuffle)817 TEST_F(VectorDCETest, DeadLoadFeedingVectorShuffle) {
818   // Detach the loads feeding the CompositeConstruct for the unused elements.
819   // TODO: Implement the rewrite for CompositeConstruct.
820 
821   const std::string assembly =
822       R"(
823 ; MemPass Type2Undef does not reuse and already existing undef.
824 ; CHECK: {{%\w+}} = OpUndef %v3float
825 ; CHECK: [[undef:%\w+]] = OpUndef %v3float
826 ; CHECK: OpFunction
827 ; CHECK: OpVectorShuffle %v3float {{%\w+}} [[undef]] 0 4 5
828                OpCapability Shader
829           %1 = OpExtInstImport "GLSL.std.450"
830                OpMemoryModel Logical GLSL450
831                OpEntryPoint Fragment %main "main" %In0 %OutColor
832                OpExecutionMode %main OriginUpperLeft
833                OpSource GLSL 450
834                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
835                OpSourceExtension "GL_GOOGLE_include_directive"
836                OpName %main "main"
837                OpName %In0 "In0"
838                OpName %OutColor "OutColor"
839                OpDecorate %In0 Location 0
840                OpDecorate %OutColor Location 0
841        %void = OpTypeVoid
842           %6 = OpTypeFunction %void
843       %float = OpTypeFloat 32
844     %v4float = OpTypeVector %float 4
845 %_ptr_Input_v4float = OpTypePointer Input %v4float
846         %In0 = OpVariable %_ptr_Input_v4float Input
847        %uint = OpTypeInt 32 0
848      %uint_0 = OpConstant %uint 0
849 %_ptr_Input_float = OpTypePointer Input %float
850      %uint_1 = OpConstant %uint 1
851      %uint_2 = OpConstant %uint 2
852     %v3float = OpTypeVector %float 3
853         %int = OpTypeInt 32 1
854       %int_0 = OpConstant %int 0
855      %int_20 = OpConstant %int 20
856        %bool = OpTypeBool
857     %float_1 = OpConstant %float 1
858     %vec_const = OpConstantComposite %v3float %float_1 %float_1 %float_1
859       %int_1 = OpConstant %int 1
860 %_ptr_Output_v4float = OpTypePointer Output %v4float
861    %OutColor = OpVariable %_ptr_Output_v4float Output
862          %23 = OpUndef %v3float
863        %main = OpFunction %void None %6
864          %24 = OpLabel
865          %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
866          %26 = OpLoad %float %25
867          %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
868          %28 = OpLoad %float %27
869          %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
870          %30 = OpLoad %float %29
871          %31 = OpCompositeConstruct %v3float %30 %28 %26
872          %sh = OpVectorShuffle %v3float %vec_const %31 0 4 5
873                OpBranch %32
874          %32 = OpLabel
875          %33 = OpPhi %v3float %sh %24 %34 %35
876          %36 = OpPhi %int %int_0 %24 %37 %35
877                OpLoopMerge %38 %35 None
878                OpBranch %39
879          %39 = OpLabel
880          %40 = OpSLessThan %bool %36 %int_20
881                OpBranchConditional %40 %41 %38
882          %41 = OpLabel
883          %42 = OpCompositeExtract %float %33 0
884          %43 = OpFAdd %float %42 %float_1
885          %34 = OpCompositeInsert %v3float %43 %33 0
886                OpBranch %35
887          %35 = OpLabel
888          %37 = OpIAdd %int %36 %int_1
889                OpBranch %32
890          %38 = OpLabel
891          %44 = OpCompositeExtract %float %33 0
892          %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
893                OpStore %OutColor %45
894                OpReturn
895                OpFunctionEnd
896 )";
897 
898   SinglePassRunAndMatch<VectorDCE>(assembly, true);
899 }
900 
TEST_F(VectorDCETest,DeadInstThroughShuffle)901 TEST_F(VectorDCETest, DeadInstThroughShuffle) {
902   // Dead insert in chain with cycle. Demonstrates analysis can handle
903   // cycles in chains.
904   //
905   // Note: The SPIR-V assembly has had store/load elimination
906   // performed to allow the inserts and extracts to directly
907   // reference each other.
908   //
909   // #version 450
910   //
911   // layout (location=0) out vec4 OutColor;
912   //
913   // void main()
914   // {
915   //     vec2 v;
916   //     v.x = 0.0;
917   //     v.y = 0.1; // dead
918   //     for (int i = 0; i < 20; i++) {
919   //       v.x = v.x + 1;
920   //       v = v * 0.9;
921   //     }
922   //     OutColor = vec4(v.x);
923   // }
924 
925   const std::string assembly =
926       R"(
927 ; CHECK: OpFunction
928 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
929 ; CHECK: OpFunctionEnd
930                OpCapability Shader
931           %1 = OpExtInstImport "GLSL.std.450"
932                OpMemoryModel Logical GLSL450
933                OpEntryPoint Fragment %main "main" %OutColor
934                OpExecutionMode %main OriginUpperLeft
935                OpSource GLSL 450
936                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
937                OpSourceExtension "GL_GOOGLE_include_directive"
938                OpName %main "main"
939                OpName %OutColor "OutColor"
940                OpDecorate %OutColor Location 0
941        %void = OpTypeVoid
942           %3 = OpTypeFunction %void
943       %float = OpTypeFloat 32
944     %v2float = OpTypeVector %float 2
945     %float_0 = OpConstant %float 0
946 %float_0_100000001 = OpConstant %float 0.100000001
947         %int = OpTypeInt 32 1
948       %int_0 = OpConstant %int 0
949      %int_20 = OpConstant %int 20
950        %bool = OpTypeBool
951     %float_1 = OpConstant %float 1
952 %float_0_899999976 = OpConstant %float 0.899999976
953       %int_1 = OpConstant %int 1
954     %v4float = OpTypeVector %float 4
955 %_ptr_Output_v4float = OpTypePointer Output %v4float
956    %OutColor = OpVariable %_ptr_Output_v4float Output
957          %58 = OpUndef %v2float
958        %main = OpFunction %void None %3
959           %5 = OpLabel
960          %49 = OpCompositeInsert %v2float %float_0 %58 0
961          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
962                OpBranch %22
963          %22 = OpLabel
964          %60 = OpPhi %v2float %51 %5 %38 %25
965          %59 = OpPhi %int %int_0 %5 %41 %25
966                OpLoopMerge %24 %25 None
967                OpBranch %26
968          %26 = OpLabel
969          %30 = OpSLessThan %bool %59 %int_20
970                OpBranchConditional %30 %23 %24
971          %23 = OpLabel
972          %53 = OpCompositeExtract %float %60 0
973          %34 = OpFAdd %float %53 %float_1
974          %55 = OpCompositeInsert %v2float %34 %60 0
975          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
976                OpBranch %25
977          %25 = OpLabel
978          %41 = OpIAdd %int %59 %int_1
979                OpBranch %22
980          %24 = OpLabel
981          %57 = OpCompositeExtract %float %60 0
982          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
983                OpStore %OutColor %47
984                OpReturn
985                OpFunctionEnd
986 )";
987 
988   SinglePassRunAndMatch<VectorDCE>(assembly, true);
989 }
990 
TEST_F(VectorDCETest,DeadInsertThroughOtherInst)991 TEST_F(VectorDCETest, DeadInsertThroughOtherInst) {
992   // Dead insert in chain with cycle. Demonstrates analysis can handle
993   // cycles in chains.
994   //
995   // Note: The SPIR-V assembly has had store/load elimination
996   // performed to allow the inserts and extracts to directly
997   // reference each other.
998   //
999   // #version 450
1000   //
1001   // layout (location=0) out vec4 OutColor;
1002   //
1003   // void main()
1004   // {
1005   //     vec2 v;
1006   //     v.x = 0.0;
1007   //     v.y = 0.1; // dead
1008   //     for (int i = 0; i < 20; i++) {
1009   //       v.x = v.x + 1;
1010   //       v = v * 0.9;
1011   //     }
1012   //     OutColor = vec4(v.x);
1013   // }
1014 
1015   const std::string assembly =
1016       R"(
1017 ; CHECK: OpFunction
1018 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
1019 ; CHECK: OpFunctionEnd
1020                OpCapability Shader
1021           %1 = OpExtInstImport "GLSL.std.450"
1022                OpMemoryModel Logical GLSL450
1023                OpEntryPoint Fragment %main "main" %OutColor
1024                OpExecutionMode %main OriginUpperLeft
1025                OpSource GLSL 450
1026                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
1027                OpSourceExtension "GL_GOOGLE_include_directive"
1028                OpName %main "main"
1029                OpName %OutColor "OutColor"
1030                OpDecorate %OutColor Location 0
1031        %void = OpTypeVoid
1032           %3 = OpTypeFunction %void
1033       %float = OpTypeFloat 32
1034     %v2float = OpTypeVector %float 2
1035     %float_0 = OpConstant %float 0
1036 %float_0_100000001 = OpConstant %float 0.100000001
1037         %int = OpTypeInt 32 1
1038       %int_0 = OpConstant %int 0
1039      %int_20 = OpConstant %int 20
1040        %bool = OpTypeBool
1041     %float_1 = OpConstant %float 1
1042 %float_0_899999976 = OpConstant %float 0.899999976
1043       %int_1 = OpConstant %int 1
1044     %v4float = OpTypeVector %float 4
1045 %_ptr_Output_v4float = OpTypePointer Output %v4float
1046    %OutColor = OpVariable %_ptr_Output_v4float Output
1047          %58 = OpUndef %v2float
1048        %main = OpFunction %void None %3
1049           %5 = OpLabel
1050          %49 = OpCompositeInsert %v2float %float_0 %58 0
1051          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
1052                OpBranch %22
1053          %22 = OpLabel
1054          %60 = OpPhi %v2float %51 %5 %38 %25
1055          %59 = OpPhi %int %int_0 %5 %41 %25
1056                OpLoopMerge %24 %25 None
1057                OpBranch %26
1058          %26 = OpLabel
1059          %30 = OpSLessThan %bool %59 %int_20
1060                OpBranchConditional %30 %23 %24
1061          %23 = OpLabel
1062          %53 = OpCompositeExtract %float %60 0
1063          %34 = OpFAdd %float %53 %float_1
1064          %55 = OpCompositeInsert %v2float %34 %60 0
1065          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
1066                OpBranch %25
1067          %25 = OpLabel
1068          %41 = OpIAdd %int %59 %int_1
1069                OpBranch %22
1070          %24 = OpLabel
1071          %57 = OpCompositeExtract %float %60 0
1072          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
1073                OpStore %OutColor %47
1074                OpReturn
1075                OpFunctionEnd
1076 )";
1077 
1078   SinglePassRunAndMatch<VectorDCE>(assembly, true);
1079 }
1080 
TEST_F(VectorDCETest,VectorIntoCompositeConstruct)1081 TEST_F(VectorDCETest, VectorIntoCompositeConstruct) {
1082   const std::string text = R"(OpCapability Linkage
1083 OpCapability Shader
1084 OpMemoryModel Logical GLSL450
1085 OpEntryPoint Fragment %1 "EntryPoint_Main" %2 %3
1086 OpExecutionMode %1 OriginUpperLeft
1087 OpDecorate %2 Location 0
1088 OpDecorate %_struct_4 Block
1089 OpDecorate %3 Location 0
1090 %float = OpTypeFloat 32
1091 %v2float = OpTypeVector %float 2
1092 %_ptr_Function_v2float = OpTypePointer Function %v2float
1093 %v4float = OpTypeVector %float 4
1094 %_ptr_Function_v4float = OpTypePointer Function %v4float
1095 %mat4v4float = OpTypeMatrix %v4float 4
1096 %_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
1097 %v3float = OpTypeVector %float 3
1098 %_ptr_Function_v3float = OpTypePointer Function %v3float
1099 %_struct_14 = OpTypeStruct %v2float %mat4v4float %v3float %v2float %v4float
1100 %_ptr_Function__struct_14 = OpTypePointer Function %_struct_14
1101 %void = OpTypeVoid
1102 %int = OpTypeInt 32 1
1103 %int_2 = OpConstant %int 2
1104 %int_1 = OpConstant %int 1
1105 %int_4 = OpConstant %int 4
1106 %int_0 = OpConstant %int 0
1107 %int_3 = OpConstant %int 3
1108 %float_0 = OpConstant %float 0
1109 %float_1 = OpConstant %float 1
1110 %_ptr_Input_v2float = OpTypePointer Input %v2float
1111 %2 = OpVariable %_ptr_Input_v2float Input
1112 %_ptr_Output_v2float = OpTypePointer Output %v2float
1113 %_struct_4 = OpTypeStruct %v2float
1114 %_ptr_Output__struct_4 = OpTypePointer Output %_struct_4
1115 %3 = OpVariable %_ptr_Output__struct_4 Output
1116 %28 = OpTypeFunction %void
1117 %29 = OpConstantComposite %v2float %float_0 %float_0
1118 %30 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1119 %31 = OpConstantComposite %mat4v4float %30 %30 %30 %30
1120 %32 = OpConstantComposite %v3float %float_0 %float_0 %float_0
1121 %1 = OpFunction %void None %28
1122 %33 = OpLabel
1123 %34 = OpVariable %_ptr_Function_v4float Function
1124 %35 = OpVariable %_ptr_Function__struct_14 Function
1125 %36 = OpAccessChain %_ptr_Function_v2float %35 %int_0
1126 OpStore %36 %29
1127 %37 = OpAccessChain %_ptr_Function_mat4v4float %35 %int_1
1128 OpStore %37 %31
1129 %38 = OpAccessChain %_ptr_Function_v3float %35 %int_2
1130 OpStore %38 %32
1131 %39 = OpAccessChain %_ptr_Function_v2float %35 %int_3
1132 OpStore %39 %29
1133 %40 = OpAccessChain %_ptr_Function_v4float %35 %int_4
1134 OpStore %40 %30
1135 %41 = OpLoad %v2float %2
1136 OpStore %36 %41
1137 %42 = OpLoad %v3float %38
1138 %43 = OpCompositeConstruct %v4float %42 %float_1
1139 %44 = OpLoad %mat4v4float %37
1140 %45 = OpVectorTimesMatrix %v4float %43 %44
1141 OpStore %34 %45
1142 OpCopyMemory %40 %34
1143 OpCopyMemory %36 %39
1144 %46 = OpAccessChain %_ptr_Output_v2float %3 %int_0
1145 %47 = OpLoad %v2float %36
1146 OpStore %46 %47
1147 OpReturn
1148 OpFunctionEnd
1149 )";
1150 
1151   SinglePassRunAndCheck<DeadInsertElimPass>(text, text, true, true);
1152 }
1153 
1154 }  // namespace
1155 }  // namespace opt
1156 }  // namespace spvtools
1157