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