• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 %55 = OpUndef %v4float
494 )";
495 
496   const std::string before =
497       R"(%main = OpFunction %void None %10
498 %28 = OpLabel
499 %29 = OpLoad %v4float %In0
500 %30 = OpLoad %float %In1
501 %31 = OpLoad %float %In2
502 %32 = OpFAdd %float %30 %31
503 %33 = OpCompositeInsert %v4float %32 %29 1
504 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
505 %35 = OpLoad %uint %34
506 %36 = OpINotEqual %bool %35 %uint_0
507 OpSelectionMerge %37 None
508 OpBranchConditional %36 %38 %37
509 %38 = OpLabel
510 %39 = OpCompositeInsert %v4float %float_1 %33 0
511 OpBranch %37
512 %37 = OpLabel
513 %40 = OpPhi %v4float %33 %28 %39 %38
514 %41 = OpCompositeExtract %float %40 0
515 %42 = OpCompositeInsert %v4float %41 %27 0
516 %43 = OpCompositeExtract %float %40 1
517 %44 = OpCompositeInsert %v4float %43 %42 1
518 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
519 %46 = OpLoad %uint %45
520 %47 = OpINotEqual %bool %46 %uint_0
521 OpSelectionMerge %48 None
522 OpBranchConditional %47 %49 %48
523 %49 = OpLabel
524 %50 = OpCompositeInsert %v4float %float_0 %44 0
525 OpBranch %48
526 %48 = OpLabel
527 %51 = OpPhi %v4float %44 %37 %50 %49
528 %52 = OpCompositeExtract %float %51 0
529 %53 = OpCompositeExtract %float %51 0
530 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
531 OpStore %OutColor %54
532 OpReturn
533 OpFunctionEnd
534 )";
535 
536   const std::string after =
537       R"(%main = OpFunction %void None %10
538 %28 = OpLabel
539 %29 = OpLoad %v4float %In0
540 %30 = OpLoad %float %In1
541 %31 = OpLoad %float %In2
542 %32 = OpFAdd %float %30 %31
543 %33 = OpCompositeInsert %v4float %32 %29 1
544 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
545 %35 = OpLoad %uint %34
546 %36 = OpINotEqual %bool %35 %uint_0
547 OpSelectionMerge %37 None
548 OpBranchConditional %36 %38 %37
549 %38 = OpLabel
550 %39 = OpCompositeInsert %v4float %float_1 %55 0
551 OpBranch %37
552 %37 = OpLabel
553 %40 = OpPhi %v4float %29 %28 %39 %38
554 %41 = OpCompositeExtract %float %40 0
555 %42 = OpCompositeInsert %v4float %41 %55 0
556 %43 = OpCompositeExtract %float %40 1
557 %44 = OpCompositeInsert %v4float %43 %42 1
558 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
559 %46 = OpLoad %uint %45
560 %47 = OpINotEqual %bool %46 %uint_0
561 OpSelectionMerge %48 None
562 OpBranchConditional %47 %49 %48
563 %49 = OpLabel
564 %50 = OpCompositeInsert %v4float %float_0 %55 0
565 OpBranch %48
566 %48 = OpLabel
567 %51 = OpPhi %v4float %42 %37 %50 %49
568 %52 = OpCompositeExtract %float %51 0
569 %53 = OpCompositeExtract %float %51 0
570 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
571 OpStore %OutColor %54
572 OpReturn
573 OpFunctionEnd
574 )";
575 
576   SinglePassRunAndCheck<VectorDCE>(before_predefs + before,
577                                    after_predefs + after, true, true);
578 }
579 
TEST_F(VectorDCETest,InsertObjectLive)580 TEST_F(VectorDCETest, InsertObjectLive) {
581   // Make sure that the object being inserted in an OpCompositeInsert
582   // is not removed when it is uses later on.
583   const std::string before =
584       R"(OpCapability Shader
585 %1 = OpExtInstImport "GLSL.std.450"
586 OpMemoryModel Logical GLSL450
587 OpEntryPoint Fragment %main "main" %In0 %In1 %OutColor
588 OpExecutionMode %main OriginUpperLeft
589 OpSource GLSL 450
590 OpName %main "main"
591 OpName %In0 "In0"
592 OpName %In1 "In1"
593 OpName %OutColor "OutColor"
594 OpDecorate %In0 Location 0
595 OpDecorate %In1 Location 1
596 OpDecorate %OutColor Location 0
597 %void = OpTypeVoid
598 %10 = OpTypeFunction %void
599 %float = OpTypeFloat 32
600 %v4float = OpTypeVector %float 4
601 %_ptr_Input_v4float = OpTypePointer Input %v4float
602 %In0 = OpVariable %_ptr_Input_v4float Input
603 %_ptr_Input_float = OpTypePointer Input %float
604 %In1 = OpVariable %_ptr_Input_float Input
605 %_ptr_Output_v4float = OpTypePointer Output %v4float
606 %OutColor = OpVariable %_ptr_Output_v4float Output
607 %main = OpFunction %void None %10
608 %28 = OpLabel
609 %29 = OpLoad %v4float %In0
610 %30 = OpLoad %float %In1
611 %33 = OpCompositeInsert %v4float %30 %29 1
612 OpStore %OutColor %33
613 OpReturn
614 OpFunctionEnd
615 )";
616 
617   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
618   SinglePassRunAndCheck<VectorDCE>(before, before, true, true);
619 }
620 
TEST_F(VectorDCETest,DeadInsertInCycle)621 TEST_F(VectorDCETest, DeadInsertInCycle) {
622   // Dead insert in chain with cycle. Demonstrates analysis can handle
623   // cycles in chains going through scalars intermediate values.
624   //
625   // Note: The SPIR-V assembly has had store/load elimination
626   // performed to allow the inserts and extracts to directly
627   // reference each other.
628   //
629   // #version 450
630   //
631   // layout (location=0) in vec4 In0;
632   // layout (location=1) in float In1;
633   // layout (location=2) in float In2;
634   // layout (location=0) out vec4 OutColor;
635   //
636   // layout(std140, binding = 0 ) uniform _Globals_
637   // {
638   //     int g_n  ;
639   // };
640   //
641   // void main()
642   // {
643   //     vec2 v = vec2(0.0, 1.0);
644   //     for (int i = 0; i < g_n; i++) {
645   //       v.x = v.x + 1;
646   //       v.y = v.y * 0.9; // dead
647   //     }
648   //     OutColor = vec4(v.x);
649   // }
650 
651   const std::string assembly =
652       R"(
653 ; CHECK: [[init_val:%\w+]] = OpConstantComposite %v2float %float_0 %float_1
654 ; CHECK: [[undef:%\w+]] = OpUndef %v2float
655 ; CHECK: OpFunction
656 ; CHECK: [[entry_lab:%\w+]] = OpLabel
657 ; CHECK: [[loop_header:%\w+]] = OpLabel
658 ; CHECK: OpPhi %v2float [[init_val]] [[entry_lab]] [[x_insert:%\w+]] {{%\w+}}
659 ; CHECK: [[x_insert:%\w+]] = OpCompositeInsert %v2float %43 [[undef]] 0
660 OpCapability Shader
661 %1 = OpExtInstImport "GLSL.std.450"
662 OpMemoryModel Logical GLSL450
663 OpEntryPoint Fragment %main "main" %OutColor %In0 %In1 %In2
664 OpExecutionMode %main OriginUpperLeft
665 OpSource GLSL 450
666 OpName %main "main"
667 OpName %_Globals_ "_Globals_"
668 OpMemberName %_Globals_ 0 "g_n"
669 OpName %_ ""
670 OpName %OutColor "OutColor"
671 OpName %In0 "In0"
672 OpName %In1 "In1"
673 OpName %In2 "In2"
674 OpMemberDecorate %_Globals_ 0 Offset 0
675 OpDecorate %_Globals_ Block
676 OpDecorate %_ DescriptorSet 0
677 OpDecorate %_ Binding 0
678 OpDecorate %OutColor Location 0
679 OpDecorate %In0 Location 0
680 OpDecorate %In1 Location 1
681 OpDecorate %In2 Location 2
682 %void = OpTypeVoid
683 %10 = OpTypeFunction %void
684 %float = OpTypeFloat 32
685 %v2float = OpTypeVector %float 2
686 %_ptr_Function_v2float = OpTypePointer Function %v2float
687 %float_0 = OpConstant %float 0
688 %float_1 = OpConstant %float 1
689 %16 = OpConstantComposite %v2float %float_0 %float_1
690 %int = OpTypeInt 32 1
691 %_ptr_Function_int = OpTypePointer Function %int
692 %int_0 = OpConstant %int 0
693 %_Globals_ = OpTypeStruct %int
694 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
695 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
696 %_ptr_Uniform_int = OpTypePointer Uniform %int
697 %bool = OpTypeBool
698 %float_0_75 = OpConstant %float 0.75
699 %int_1 = OpConstant %int 1
700 %v4float = OpTypeVector %float 4
701 %_ptr_Output_v4float = OpTypePointer Output %v4float
702 %OutColor = OpVariable %_ptr_Output_v4float Output
703 %_ptr_Input_v4float = OpTypePointer Input %v4float
704 %In0 = OpVariable %_ptr_Input_v4float Input
705 %_ptr_Input_float = OpTypePointer Input %float
706 %In1 = OpVariable %_ptr_Input_float Input
707 %In2 = OpVariable %_ptr_Input_float Input
708 %main = OpFunction %void None %10
709 %29 = OpLabel
710 OpBranch %30
711 %30 = OpLabel
712 %31 = OpPhi %v2float %16 %29 %32 %33
713 %34 = OpPhi %int %int_0 %29 %35 %33
714 OpLoopMerge %36 %33 None
715 OpBranch %37
716 %37 = OpLabel
717 %38 = OpAccessChain %_ptr_Uniform_int %_ %int_0
718 %39 = OpLoad %int %38
719 %40 = OpSLessThan %bool %34 %39
720 OpBranchConditional %40 %41 %36
721 %41 = OpLabel
722 %42 = OpCompositeExtract %float %31 0
723 %43 = OpFAdd %float %42 %float_1
724 %44 = OpCompositeInsert %v2float %43 %31 0
725 %45 = OpCompositeExtract %float %44 1
726 %46 = OpFMul %float %45 %float_0_75
727 %32 = OpCompositeInsert %v2float %46 %44 1
728 OpBranch %33
729 %33 = OpLabel
730 %35 = OpIAdd %int %34 %int_1
731 OpBranch %30
732 %36 = OpLabel
733 %47 = OpCompositeExtract %float %31 0
734 %48 = OpCompositeConstruct %v4float %47 %47 %47 %47
735 OpStore %OutColor %48
736 OpReturn
737 OpFunctionEnd
738 )";
739 
740   SinglePassRunAndMatch<VectorDCE>(assembly, true);
741 }
742 
TEST_F(VectorDCETest,DeadLoadFeedingCompositeConstruct)743 TEST_F(VectorDCETest, DeadLoadFeedingCompositeConstruct) {
744   // Detach the loads feeding the CompositeConstruct for the unused elements.
745   // TODO: Implement the rewrite for CompositeConstruct.
746 
747   const std::string assembly =
748       R"(
749 ; CHECK: [[undef:%\w+]] = OpUndef %float
750 ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Input_float %In0 %uint_2
751 ; CHECK: [[load:%\w+]] = OpLoad %float [[ac]]
752 ; CHECK: OpCompositeConstruct %v3float [[load]] [[undef]] [[undef]]
753 OpCapability Shader
754 %1 = OpExtInstImport "GLSL.std.450"
755 OpMemoryModel Logical GLSL450
756 OpEntryPoint Fragment %main "main" %In0 %OutColor
757 OpExecutionMode %main OriginUpperLeft
758 OpSource GLSL 450
759 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
760 OpSourceExtension "GL_GOOGLE_include_directive"
761 OpName %main "main"
762 OpName %In0 "In0"
763 OpName %OutColor "OutColor"
764 OpDecorate %In0 Location 0
765 OpDecorate %OutColor Location 0
766 %void = OpTypeVoid
767 %6 = OpTypeFunction %void
768 %float = OpTypeFloat 32
769 %v4float = OpTypeVector %float 4
770 %_ptr_Input_v4float = OpTypePointer Input %v4float
771 %In0 = OpVariable %_ptr_Input_v4float Input
772 %uint = OpTypeInt 32 0
773 %uint_0 = OpConstant %uint 0
774 %_ptr_Input_float = OpTypePointer Input %float
775 %uint_1 = OpConstant %uint 1
776 %uint_2 = OpConstant %uint 2
777 %v3float = OpTypeVector %float 3
778 %int = OpTypeInt 32 1
779 %int_0 = OpConstant %int 0
780 %int_20 = OpConstant %int 20
781 %bool = OpTypeBool
782 %float_1 = OpConstant %float 1
783 %int_1 = OpConstant %int 1
784 %_ptr_Output_v4float = OpTypePointer Output %v4float
785 %OutColor = OpVariable %_ptr_Output_v4float Output
786 %23 = OpUndef %v3float
787 %main = OpFunction %void None %6
788 %24 = OpLabel
789 %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
790 %26 = OpLoad %float %25
791 %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
792 %28 = OpLoad %float %27
793 %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
794 %30 = OpLoad %float %29
795 %31 = OpCompositeConstruct %v3float %30 %28 %26
796 OpBranch %32
797 %32 = OpLabel
798 %33 = OpPhi %v3float %31 %24 %34 %35
799 %36 = OpPhi %int %int_0 %24 %37 %35
800 OpLoopMerge %38 %35 None
801 OpBranch %39
802 %39 = OpLabel
803 %40 = OpSLessThan %bool %36 %int_20
804 OpBranchConditional %40 %41 %38
805 %41 = OpLabel
806 %42 = OpCompositeExtract %float %33 0
807 %43 = OpFAdd %float %42 %float_1
808 %34 = OpCompositeInsert %v3float %43 %33 0
809 OpBranch %35
810 %35 = OpLabel
811 %37 = OpIAdd %int %36 %int_1
812 OpBranch %32
813 %38 = OpLabel
814 %44 = OpCompositeExtract %float %33 0
815 %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
816 OpStore %OutColor %45
817 OpReturn
818 OpFunctionEnd
819 )";
820 
821   SinglePassRunAndMatch<VectorDCE>(assembly, true);
822 }
823 
TEST_F(VectorDCETest,DeadLoadFeedingVectorShuffle)824 TEST_F(VectorDCETest, DeadLoadFeedingVectorShuffle) {
825   // Detach the loads feeding the CompositeConstruct for the unused elements.
826   // TODO: Implement the rewrite for CompositeConstruct.
827 
828   const std::string assembly =
829       R"(
830 ; MemPass Type2Undef does not reuse and already existing undef.
831 ; CHECK: {{%\w+}} = OpUndef %v3float
832 ; CHECK: [[undef:%\w+]] = OpUndef %v3float
833 ; CHECK: OpFunction
834 ; CHECK: OpVectorShuffle %v3float {{%\w+}} [[undef]] 0 4 5
835                OpCapability Shader
836           %1 = OpExtInstImport "GLSL.std.450"
837                OpMemoryModel Logical GLSL450
838                OpEntryPoint Fragment %main "main" %In0 %OutColor
839                OpExecutionMode %main OriginUpperLeft
840                OpSource GLSL 450
841                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
842                OpSourceExtension "GL_GOOGLE_include_directive"
843                OpName %main "main"
844                OpName %In0 "In0"
845                OpName %OutColor "OutColor"
846                OpDecorate %In0 Location 0
847                OpDecorate %OutColor Location 0
848        %void = OpTypeVoid
849           %6 = OpTypeFunction %void
850       %float = OpTypeFloat 32
851     %v4float = OpTypeVector %float 4
852 %_ptr_Input_v4float = OpTypePointer Input %v4float
853         %In0 = OpVariable %_ptr_Input_v4float Input
854        %uint = OpTypeInt 32 0
855      %uint_0 = OpConstant %uint 0
856 %_ptr_Input_float = OpTypePointer Input %float
857      %uint_1 = OpConstant %uint 1
858      %uint_2 = OpConstant %uint 2
859     %v3float = OpTypeVector %float 3
860         %int = OpTypeInt 32 1
861       %int_0 = OpConstant %int 0
862      %int_20 = OpConstant %int 20
863        %bool = OpTypeBool
864     %float_1 = OpConstant %float 1
865     %vec_const = OpConstantComposite %v3float %float_1 %float_1 %float_1
866       %int_1 = OpConstant %int 1
867 %_ptr_Output_v4float = OpTypePointer Output %v4float
868    %OutColor = OpVariable %_ptr_Output_v4float Output
869          %23 = OpUndef %v3float
870        %main = OpFunction %void None %6
871          %24 = OpLabel
872          %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
873          %26 = OpLoad %float %25
874          %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
875          %28 = OpLoad %float %27
876          %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
877          %30 = OpLoad %float %29
878          %31 = OpCompositeConstruct %v3float %30 %28 %26
879          %sh = OpVectorShuffle %v3float %vec_const %31 0 4 5
880                OpBranch %32
881          %32 = OpLabel
882          %33 = OpPhi %v3float %sh %24 %34 %35
883          %36 = OpPhi %int %int_0 %24 %37 %35
884                OpLoopMerge %38 %35 None
885                OpBranch %39
886          %39 = OpLabel
887          %40 = OpSLessThan %bool %36 %int_20
888                OpBranchConditional %40 %41 %38
889          %41 = OpLabel
890          %42 = OpCompositeExtract %float %33 0
891          %43 = OpFAdd %float %42 %float_1
892          %34 = OpCompositeInsert %v3float %43 %33 0
893                OpBranch %35
894          %35 = OpLabel
895          %37 = OpIAdd %int %36 %int_1
896                OpBranch %32
897          %38 = OpLabel
898          %44 = OpCompositeExtract %float %33 0
899          %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
900                OpStore %OutColor %45
901                OpReturn
902                OpFunctionEnd
903 )";
904 
905   SinglePassRunAndMatch<VectorDCE>(assembly, true);
906 }
907 
TEST_F(VectorDCETest,DeadInstThroughShuffle)908 TEST_F(VectorDCETest, DeadInstThroughShuffle) {
909   // Dead insert in chain with cycle. Demonstrates analysis can handle
910   // cycles in chains.
911   //
912   // Note: The SPIR-V assembly has had store/load elimination
913   // performed to allow the inserts and extracts to directly
914   // reference each other.
915   //
916   // #version 450
917   //
918   // layout (location=0) out vec4 OutColor;
919   //
920   // void main()
921   // {
922   //     vec2 v;
923   //     v.x = 0.0;
924   //     v.y = 0.1; // dead
925   //     for (int i = 0; i < 20; i++) {
926   //       v.x = v.x + 1;
927   //       v = v * 0.9;
928   //     }
929   //     OutColor = vec4(v.x);
930   // }
931 
932   const std::string assembly =
933       R"(
934 ; CHECK: OpFunction
935 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
936 ; CHECK: OpFunctionEnd
937                OpCapability Shader
938           %1 = OpExtInstImport "GLSL.std.450"
939                OpMemoryModel Logical GLSL450
940                OpEntryPoint Fragment %main "main" %OutColor
941                OpExecutionMode %main OriginUpperLeft
942                OpSource GLSL 450
943                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
944                OpSourceExtension "GL_GOOGLE_include_directive"
945                OpName %main "main"
946                OpName %OutColor "OutColor"
947                OpDecorate %OutColor Location 0
948        %void = OpTypeVoid
949           %3 = OpTypeFunction %void
950       %float = OpTypeFloat 32
951     %v2float = OpTypeVector %float 2
952     %float_0 = OpConstant %float 0
953 %float_0_100000001 = OpConstant %float 0.100000001
954         %int = OpTypeInt 32 1
955       %int_0 = OpConstant %int 0
956      %int_20 = OpConstant %int 20
957        %bool = OpTypeBool
958     %float_1 = OpConstant %float 1
959 %float_0_899999976 = OpConstant %float 0.899999976
960       %int_1 = OpConstant %int 1
961     %v4float = OpTypeVector %float 4
962 %_ptr_Output_v4float = OpTypePointer Output %v4float
963    %OutColor = OpVariable %_ptr_Output_v4float Output
964          %58 = OpUndef %v2float
965        %main = OpFunction %void None %3
966           %5 = OpLabel
967          %49 = OpCompositeInsert %v2float %float_0 %58 0
968          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
969                OpBranch %22
970          %22 = OpLabel
971          %60 = OpPhi %v2float %51 %5 %38 %25
972          %59 = OpPhi %int %int_0 %5 %41 %25
973                OpLoopMerge %24 %25 None
974                OpBranch %26
975          %26 = OpLabel
976          %30 = OpSLessThan %bool %59 %int_20
977                OpBranchConditional %30 %23 %24
978          %23 = OpLabel
979          %53 = OpCompositeExtract %float %60 0
980          %34 = OpFAdd %float %53 %float_1
981          %55 = OpCompositeInsert %v2float %34 %60 0
982          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
983                OpBranch %25
984          %25 = OpLabel
985          %41 = OpIAdd %int %59 %int_1
986                OpBranch %22
987          %24 = OpLabel
988          %57 = OpCompositeExtract %float %60 0
989          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
990                OpStore %OutColor %47
991                OpReturn
992                OpFunctionEnd
993 )";
994 
995   SinglePassRunAndMatch<VectorDCE>(assembly, true);
996 }
997 
TEST_F(VectorDCETest,DeadInsertThroughOtherInst)998 TEST_F(VectorDCETest, DeadInsertThroughOtherInst) {
999   // Dead insert in chain with cycle. Demonstrates analysis can handle
1000   // cycles in chains.
1001   //
1002   // Note: The SPIR-V assembly has had store/load elimination
1003   // performed to allow the inserts and extracts to directly
1004   // reference each other.
1005   //
1006   // #version 450
1007   //
1008   // layout (location=0) out vec4 OutColor;
1009   //
1010   // void main()
1011   // {
1012   //     vec2 v;
1013   //     v.x = 0.0;
1014   //     v.y = 0.1; // dead
1015   //     for (int i = 0; i < 20; i++) {
1016   //       v.x = v.x + 1;
1017   //       v = v * 0.9;
1018   //     }
1019   //     OutColor = vec4(v.x);
1020   // }
1021 
1022   const std::string assembly =
1023       R"(
1024 ; CHECK: OpFunction
1025 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
1026 ; CHECK: OpFunctionEnd
1027                OpCapability Shader
1028           %1 = OpExtInstImport "GLSL.std.450"
1029                OpMemoryModel Logical GLSL450
1030                OpEntryPoint Fragment %main "main" %OutColor
1031                OpExecutionMode %main OriginUpperLeft
1032                OpSource GLSL 450
1033                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
1034                OpSourceExtension "GL_GOOGLE_include_directive"
1035                OpName %main "main"
1036                OpName %OutColor "OutColor"
1037                OpDecorate %OutColor Location 0
1038        %void = OpTypeVoid
1039           %3 = OpTypeFunction %void
1040       %float = OpTypeFloat 32
1041     %v2float = OpTypeVector %float 2
1042     %float_0 = OpConstant %float 0
1043 %float_0_100000001 = OpConstant %float 0.100000001
1044         %int = OpTypeInt 32 1
1045       %int_0 = OpConstant %int 0
1046      %int_20 = OpConstant %int 20
1047        %bool = OpTypeBool
1048     %float_1 = OpConstant %float 1
1049 %float_0_899999976 = OpConstant %float 0.899999976
1050       %int_1 = OpConstant %int 1
1051     %v4float = OpTypeVector %float 4
1052 %_ptr_Output_v4float = OpTypePointer Output %v4float
1053    %OutColor = OpVariable %_ptr_Output_v4float Output
1054          %58 = OpUndef %v2float
1055        %main = OpFunction %void None %3
1056           %5 = OpLabel
1057          %49 = OpCompositeInsert %v2float %float_0 %58 0
1058          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
1059                OpBranch %22
1060          %22 = OpLabel
1061          %60 = OpPhi %v2float %51 %5 %38 %25
1062          %59 = OpPhi %int %int_0 %5 %41 %25
1063                OpLoopMerge %24 %25 None
1064                OpBranch %26
1065          %26 = OpLabel
1066          %30 = OpSLessThan %bool %59 %int_20
1067                OpBranchConditional %30 %23 %24
1068          %23 = OpLabel
1069          %53 = OpCompositeExtract %float %60 0
1070          %34 = OpFAdd %float %53 %float_1
1071          %55 = OpCompositeInsert %v2float %34 %60 0
1072          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
1073                OpBranch %25
1074          %25 = OpLabel
1075          %41 = OpIAdd %int %59 %int_1
1076                OpBranch %22
1077          %24 = OpLabel
1078          %57 = OpCompositeExtract %float %60 0
1079          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
1080                OpStore %OutColor %47
1081                OpReturn
1082                OpFunctionEnd
1083 )";
1084 
1085   SinglePassRunAndMatch<VectorDCE>(assembly, true);
1086 }
1087 
TEST_F(VectorDCETest,VectorIntoCompositeConstruct)1088 TEST_F(VectorDCETest, VectorIntoCompositeConstruct) {
1089   const std::string text = R"(OpCapability Linkage
1090 OpCapability Shader
1091 OpMemoryModel Logical GLSL450
1092 OpEntryPoint Fragment %1 "EntryPoint_Main" %2 %3
1093 OpExecutionMode %1 OriginUpperLeft
1094 OpDecorate %2 Location 0
1095 OpDecorate %_struct_4 Block
1096 OpDecorate %3 Location 0
1097 %float = OpTypeFloat 32
1098 %v2float = OpTypeVector %float 2
1099 %_ptr_Function_v2float = OpTypePointer Function %v2float
1100 %v4float = OpTypeVector %float 4
1101 %_ptr_Function_v4float = OpTypePointer Function %v4float
1102 %mat4v4float = OpTypeMatrix %v4float 4
1103 %_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
1104 %v3float = OpTypeVector %float 3
1105 %_ptr_Function_v3float = OpTypePointer Function %v3float
1106 %_struct_14 = OpTypeStruct %v2float %mat4v4float %v3float %v2float %v4float
1107 %_ptr_Function__struct_14 = OpTypePointer Function %_struct_14
1108 %void = OpTypeVoid
1109 %int = OpTypeInt 32 1
1110 %int_2 = OpConstant %int 2
1111 %int_1 = OpConstant %int 1
1112 %int_4 = OpConstant %int 4
1113 %int_0 = OpConstant %int 0
1114 %int_3 = OpConstant %int 3
1115 %float_0 = OpConstant %float 0
1116 %float_1 = OpConstant %float 1
1117 %_ptr_Input_v2float = OpTypePointer Input %v2float
1118 %2 = OpVariable %_ptr_Input_v2float Input
1119 %_ptr_Output_v2float = OpTypePointer Output %v2float
1120 %_struct_4 = OpTypeStruct %v2float
1121 %_ptr_Output__struct_4 = OpTypePointer Output %_struct_4
1122 %3 = OpVariable %_ptr_Output__struct_4 Output
1123 %28 = OpTypeFunction %void
1124 %29 = OpConstantComposite %v2float %float_0 %float_0
1125 %30 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1126 %31 = OpConstantComposite %mat4v4float %30 %30 %30 %30
1127 %32 = OpConstantComposite %v3float %float_0 %float_0 %float_0
1128 %1 = OpFunction %void None %28
1129 %33 = OpLabel
1130 %34 = OpVariable %_ptr_Function_v4float Function
1131 %35 = OpVariable %_ptr_Function__struct_14 Function
1132 %36 = OpAccessChain %_ptr_Function_v2float %35 %int_0
1133 OpStore %36 %29
1134 %37 = OpAccessChain %_ptr_Function_mat4v4float %35 %int_1
1135 OpStore %37 %31
1136 %38 = OpAccessChain %_ptr_Function_v3float %35 %int_2
1137 OpStore %38 %32
1138 %39 = OpAccessChain %_ptr_Function_v2float %35 %int_3
1139 OpStore %39 %29
1140 %40 = OpAccessChain %_ptr_Function_v4float %35 %int_4
1141 OpStore %40 %30
1142 %41 = OpLoad %v2float %2
1143 OpStore %36 %41
1144 %42 = OpLoad %v3float %38
1145 %43 = OpCompositeConstruct %v4float %42 %float_1
1146 %44 = OpLoad %mat4v4float %37
1147 %45 = OpVectorTimesMatrix %v4float %43 %44
1148 OpStore %34 %45
1149 OpCopyMemory %40 %34
1150 OpCopyMemory %36 %39
1151 %46 = OpAccessChain %_ptr_Output_v2float %3 %int_0
1152 %47 = OpLoad %v2float %36
1153 OpStore %46 %47
1154 OpReturn
1155 OpFunctionEnd
1156 )";
1157 
1158   SinglePassRunAndCheck<VectorDCE>(text, text, true, true);
1159 }
1160 
TEST_F(VectorDCETest,NotAffectedByDebugValue)1161 TEST_F(VectorDCETest, NotAffectedByDebugValue) {
1162   // It tests that an OpenCL.DebugInfo.100 DebugValue instruction does
1163   // not change the vector DCE pass result. If the composite used for
1164   // the value of DebugValue is killed, the DebugValue must be killed as well.
1165   const std::string text = R"(
1166 OpCapability Shader
1167 %1 = OpExtInstImport "GLSL.std.450"
1168 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
1169 OpMemoryModel Logical GLSL450
1170 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
1171 OpExecutionMode %main OriginUpperLeft
1172 OpSource GLSL 450
1173 %file_name = OpString "test"
1174 %float_name = OpString "float"
1175 %main_name = OpString "main"
1176 %f_name = OpString "f"
1177 OpName %main "main"
1178 OpName %In2 "In2"
1179 OpName %In0 "In0"
1180 OpName %In1 "In1"
1181 OpName %OutColor "OutColor"
1182 OpName %_Globals_ "_Globals_"
1183 OpMemberName %_Globals_ 0 "g_b"
1184 OpMemberName %_Globals_ 1 "g_n"
1185 OpName %_ ""
1186 OpDecorate %In2 Location 2
1187 OpDecorate %In0 Location 0
1188 OpDecorate %In1 Location 1
1189 OpDecorate %OutColor Location 0
1190 OpMemberDecorate %_Globals_ 0 Offset 0
1191 OpMemberDecorate %_Globals_ 1 Offset 4
1192 OpDecorate %_Globals_ Block
1193 OpDecorate %_ DescriptorSet 0
1194 OpDecorate %_ Binding 0
1195 %void = OpTypeVoid
1196 %11 = OpTypeFunction %void
1197 %float = OpTypeFloat 32
1198 %v2float = OpTypeVector %float 2
1199 %_ptr_Function_v2float = OpTypePointer Function %v2float
1200 %_ptr_Input_v2float = OpTypePointer Input %v2float
1201 %In2 = OpVariable %_ptr_Input_v2float Input
1202 %_ptr_Input_float = OpTypePointer Input %float
1203 %In0 = OpVariable %_ptr_Input_float Input
1204 %In1 = OpVariable %_ptr_Input_float Input
1205 %uint = OpTypeInt 32 0
1206 %uint_32 = OpConstant %uint 32
1207 %_ptr_Function_float = OpTypePointer Function %float
1208 %float_0 = OpConstant %float 0
1209 %v4float = OpTypeVector %float 4
1210 %_ptr_Output_v4float = OpTypePointer Output %v4float
1211 %OutColor = OpVariable %_ptr_Output_v4float Output
1212 %int = OpTypeInt 32 1
1213 %_Globals_ = OpTypeStruct %uint %int
1214 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
1215 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
1216 %null_expr = OpExtInst %void %ext DebugExpression
1217 %src = OpExtInst %void %ext DebugSource %file_name
1218 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
1219 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
1220 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
1221 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
1222 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
1223 %main = OpFunction %void None %11
1224 %25 = OpLabel
1225 %s = OpExtInst %void %ext DebugScope %dbg_main
1226 
1227 ; CHECK: [[in2:%\w+]] = OpLoad %v2float %In2
1228 %26 = OpLoad %v2float %In2
1229 %27 = OpLoad %float %In0
1230 %28 = OpLoad %float %In1
1231 %29 = OpFAdd %float %27 %28
1232 
1233 ; CHECK:      OpCompositeInsert %v2float {{%\w+}} [[in2]] 0
1234 ; CHECK-NEXT: OpCompositeInsert %v2float {{%\w+}} [[in2]] 0
1235 ; CHECK-NOT:  DebugValue
1236 %35 = OpCompositeInsert %v2float %29 %26 0
1237 %value = OpExtInst %void %ext DebugValue %dbg_f %35 %null_expr
1238 %37 = OpCompositeInsert %v2float %float_0 %35 0
1239 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
1240 OpStore %OutColor %33
1241 OpReturn
1242 OpFunctionEnd
1243 )";
1244 
1245   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1246                         SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
1247   SinglePassRunAndMatch<VectorDCE>(text, true);
1248 }
1249 
TEST_F(VectorDCETest,RemoveDebugValueUsesKilledInstr)1250 TEST_F(VectorDCETest, RemoveDebugValueUsesKilledInstr) {
1251   // It tests that the vector DCE pass removes the OpenCL.DebugInfo.100
1252   // DebugValue instruction using a killed instruction.
1253   const std::string text = R"(
1254 OpCapability Shader
1255 %1 = OpExtInstImport "GLSL.std.450"
1256 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
1257 OpMemoryModel Logical GLSL450
1258 OpEntryPoint Fragment %main "main" %In0 %OutColor
1259 OpExecutionMode %main OriginUpperLeft
1260 OpSource GLSL 450
1261 %file_name = OpString "test"
1262 %float_name = OpString "float"
1263 %main_name = OpString "main"
1264 %f_name = OpString "f"
1265 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
1266 OpSourceExtension "GL_GOOGLE_include_directive"
1267 OpName %main "main"
1268 OpName %In0 "In0"
1269 OpName %OutColor "OutColor"
1270 OpDecorate %In0 Location 0
1271 OpDecorate %OutColor Location 0
1272 %void = OpTypeVoid
1273 %6 = OpTypeFunction %void
1274 %float = OpTypeFloat 32
1275 %v4float = OpTypeVector %float 4
1276 %_ptr_Input_v4float = OpTypePointer Input %v4float
1277 %In0 = OpVariable %_ptr_Input_v4float Input
1278 %uint = OpTypeInt 32 0
1279 %uint_0 = OpConstant %uint 0
1280 %uint_32 = OpConstant %uint 32
1281 %_ptr_Input_float = OpTypePointer Input %float
1282 %uint_1 = OpConstant %uint 1
1283 %uint_2 = OpConstant %uint 2
1284 %v3float = OpTypeVector %float 3
1285 %int = OpTypeInt 32 1
1286 %int_0 = OpConstant %int 0
1287 %int_20 = OpConstant %int 20
1288 %bool = OpTypeBool
1289 %float_1 = OpConstant %float 1
1290 %int_1 = OpConstant %int 1
1291 %_ptr_Output_v4float = OpTypePointer Output %v4float
1292 %OutColor = OpVariable %_ptr_Output_v4float Output
1293 %23 = OpUndef %v3float
1294 %null_expr = OpExtInst %void %ext DebugExpression
1295 %src = OpExtInst %void %ext DebugSource %file_name
1296 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
1297 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
1298 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf
1299 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
1300 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
1301 %main = OpFunction %void None %6
1302 %24 = OpLabel
1303 %s0 = OpExtInst %void %ext DebugScope %dbg_main
1304 %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
1305 %26 = OpLoad %float %25
1306 %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
1307 %28 = OpLoad %float %27
1308 
1309 ; CHECK:     [[undef:%\w+]] = OpUndef %float
1310 ; CHECK-NOT: DebugValue
1311 %value = OpExtInst %void %ext DebugValue %dbg_f %28 %null_expr
1312 %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
1313 %30 = OpLoad %float %29
1314 
1315 ; CHECK:      [[composite:%\w+]] = OpCompositeConstruct %v3float {{%\w+}} [[undef]] [[undef]]
1316 ; CHECK-NEXT: DebugValue {{%\w+}} [[composite]]
1317 %31 = OpCompositeConstruct %v3float %30 %28 %26
1318 %value_live = OpExtInst %void %ext DebugValue %dbg_f %31 %null_expr
1319 OpBranch %32
1320 %32 = OpLabel
1321 %s1 = OpExtInst %void %ext DebugScope %dbg_main
1322 %33 = OpPhi %v3float %31 %24 %34 %35
1323 %36 = OpPhi %int %int_0 %24 %37 %35
1324 OpLoopMerge %38 %35 None
1325 OpBranch %39
1326 %39 = OpLabel
1327 %s2 = OpExtInst %void %ext DebugScope %dbg_main
1328 %40 = OpSLessThan %bool %36 %int_20
1329 OpBranchConditional %40 %41 %38
1330 %41 = OpLabel
1331 %s3 = OpExtInst %void %ext DebugScope %dbg_main
1332 %42 = OpCompositeExtract %float %33 0
1333 %43 = OpFAdd %float %42 %float_1
1334 %34 = OpCompositeInsert %v3float %43 %33 0
1335 OpBranch %35
1336 %35 = OpLabel
1337 %s4 = OpExtInst %void %ext DebugScope %dbg_main
1338 %37 = OpIAdd %int %36 %int_1
1339 OpBranch %32
1340 %38 = OpLabel
1341 %s5 = OpExtInst %void %ext DebugScope %dbg_main
1342 %44 = OpCompositeExtract %float %33 0
1343 %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
1344 OpStore %OutColor %45
1345 OpReturn
1346 OpFunctionEnd
1347 )";
1348 
1349   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1350                         SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
1351   SinglePassRunAndMatch<VectorDCE>(text, true);
1352 }
1353 
1354 }  // namespace
1355 }  // namespace opt
1356 }  // namespace spvtools
1357