1 // Copyright (c) 2017 Valve Corporation
2 // Copyright (c) 2017 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <string>
17 
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20 
21 namespace spvtools {
22 namespace opt {
23 namespace {
24 
25 using LocalSingleStoreElimTest = PassTest<::testing::Test>;
26 
TEST_F(LocalSingleStoreElimTest, PositiveAndNegative)27 TEST_F(LocalSingleStoreElimTest, PositiveAndNegative) {
28   // Single store to v is optimized. Multiple store to
29   // f is not optimized.
30   //
31   // #version 140
32   //
33   // in vec4 BaseColor;
34   // in float fi;
35   //
36   // void main()
37   // {
38   //     vec4 v = BaseColor;
39   //     float f = fi;
40   //     if (f < 0)
41   //         f = 0.0;
42   //     gl_FragColor = v + f;
43   // }
44 
45   const std::string predefs =
46       R"(OpCapability Shader
47 %1 = OpExtInstImport "GLSL.std.450"
48 OpMemoryModel Logical GLSL450
49 OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
50 OpExecutionMode %main OriginUpperLeft
51 OpSource GLSL 140
52 OpName %main "main"
53 OpName %v "v"
54 OpName %BaseColor "BaseColor"
55 OpName %f "f"
56 OpName %fi "fi"
57 OpName %gl_FragColor "gl_FragColor"
58 %void = OpTypeVoid
59 %9 = OpTypeFunction %void
60 %float = OpTypeFloat 32
61 %v4float = OpTypeVector %float 4
62 %_ptr_Function_v4float = OpTypePointer Function %v4float
63 %_ptr_Input_v4float = OpTypePointer Input %v4float
64 %BaseColor = OpVariable %_ptr_Input_v4float Input
65 %_ptr_Function_float = OpTypePointer Function %float
66 %_ptr_Input_float = OpTypePointer Input %float
67 %fi = OpVariable %_ptr_Input_float Input
68 %float_0 = OpConstant %float 0
69 %bool = OpTypeBool
70 %_ptr_Output_v4float = OpTypePointer Output %v4float
71 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
72 )";
73 
74   const std::string before =
75       R"(%main = OpFunction %void None %9
76 %19 = OpLabel
77 %v = OpVariable %_ptr_Function_v4float Function
78 %f = OpVariable %_ptr_Function_float Function
79 %20 = OpLoad %v4float %BaseColor
80 OpStore %v %20
81 %21 = OpLoad %float %fi
82 OpStore %f %21
83 %22 = OpLoad %float %f
84 %23 = OpFOrdLessThan %bool %22 %float_0
85 OpSelectionMerge %24 None
86 OpBranchConditional %23 %25 %24
87 %25 = OpLabel
88 OpStore %f %float_0
89 OpBranch %24
90 %24 = OpLabel
91 %26 = OpLoad %v4float %v
92 %27 = OpLoad %float %f
93 %28 = OpCompositeConstruct %v4float %27 %27 %27 %27
94 %29 = OpFAdd %v4float %26 %28
95 OpStore %gl_FragColor %29
96 OpReturn
97 OpFunctionEnd
98 )";
99 
100   const std::string after =
101       R"(%main = OpFunction %void None %9
102 %19 = OpLabel
103 %v = OpVariable %_ptr_Function_v4float Function
104 %f = OpVariable %_ptr_Function_float Function
105 %20 = OpLoad %v4float %BaseColor
106 OpStore %v %20
107 %21 = OpLoad %float %fi
108 OpStore %f %21
109 %22 = OpLoad %float %f
110 %23 = OpFOrdLessThan %bool %22 %float_0
111 OpSelectionMerge %24 None
112 OpBranchConditional %23 %25 %24
113 %25 = OpLabel
114 OpStore %f %float_0
115 OpBranch %24
116 %24 = OpLabel
117 %27 = OpLoad %float %f
118 %28 = OpCompositeConstruct %v4float %27 %27 %27 %27
119 %29 = OpFAdd %v4float %20 %28
120 OpStore %gl_FragColor %29
121 OpReturn
122 OpFunctionEnd
123 )";
124 
125   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
126                                                   predefs + after, true, true);
127 }
128 
TEST_F(LocalSingleStoreElimTest, LSSElimForLinkage)129 TEST_F(LocalSingleStoreElimTest, LSSElimForLinkage) {
130   const std::string predefs =
131       R"(OpCapability Shader
132 OpCapability Linkage
133 %1 = OpExtInstImport "GLSL.std.450"
134 OpMemoryModel Logical GLSL450
135 OpSource HLSL 630
136 OpName %main "main"
137 OpName %v "v"
138 OpName %BaseColor "BaseColor"
139 OpName %f "f"
140 OpName %fi "fi"
141 OpName %gl_FragColor "gl_FragColor"
142 OpDecorate %main LinkageAttributes "main" Export
143 %void = OpTypeVoid
144 %9 = OpTypeFunction %void
145 %float = OpTypeFloat 32
146 %v4float = OpTypeVector %float 4
147 %_ptr_Function_v4float = OpTypePointer Function %v4float
148 %_ptr_Input_v4float = OpTypePointer Input %v4float
149 %BaseColor = OpVariable %_ptr_Input_v4float Input
150 %_ptr_Function_float = OpTypePointer Function %float
151 %_ptr_Input_float = OpTypePointer Input %float
152 %fi = OpVariable %_ptr_Input_float Input
153 %float_0 = OpConstant %float 0
154 %bool = OpTypeBool
155 %_ptr_Output_v4float = OpTypePointer Output %v4float
156 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
157 )";
158 
159   const std::string before =
160       R"(%main = OpFunction %void None %9
161 %19 = OpLabel
162 %v = OpVariable %_ptr_Function_v4float Function
163 %f = OpVariable %_ptr_Function_float Function
164 %20 = OpLoad %v4float %BaseColor
165 OpStore %v %20
166 %21 = OpLoad %float %fi
167 OpStore %f %21
168 %22 = OpLoad %float %f
169 %23 = OpFOrdLessThan %bool %22 %float_0
170 OpSelectionMerge %24 None
171 OpBranchConditional %23 %25 %24
172 %25 = OpLabel
173 OpStore %f %float_0
174 OpBranch %24
175 %24 = OpLabel
176 %26 = OpLoad %v4float %v
177 %27 = OpLoad %float %f
178 %28 = OpCompositeConstruct %v4float %27 %27 %27 %27
179 %29 = OpFAdd %v4float %26 %28
180 OpStore %gl_FragColor %29
181 OpReturn
182 OpFunctionEnd
183 )";
184 
185   const std::string after =
186       R"(%main = OpFunction %void None %9
187 %19 = OpLabel
188 %v = OpVariable %_ptr_Function_v4float Function
189 %f = OpVariable %_ptr_Function_float Function
190 %20 = OpLoad %v4float %BaseColor
191 OpStore %v %20
192 %21 = OpLoad %float %fi
193 OpStore %f %21
194 %22 = OpLoad %float %f
195 %23 = OpFOrdLessThan %bool %22 %float_0
196 OpSelectionMerge %24 None
197 OpBranchConditional %23 %25 %24
198 %25 = OpLabel
199 OpStore %f %float_0
200 OpBranch %24
201 %24 = OpLabel
202 %27 = OpLoad %float %f
203 %28 = OpCompositeConstruct %v4float %27 %27 %27 %27
204 %29 = OpFAdd %v4float %20 %28
205 OpStore %gl_FragColor %29
206 OpReturn
207 OpFunctionEnd
208 )";
209 
210   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
211                                                   predefs + after, true, true);
212 }
213 
TEST_F(LocalSingleStoreElimTest, ThreeStores)214 TEST_F(LocalSingleStoreElimTest, ThreeStores) {
215   // Three stores to multiple loads of v is not optimized.
216 
217   const std::string predefs =
218       R"(OpCapability Shader
219 %1 = OpExtInstImport "GLSL.std.450"
220 OpMemoryModel Logical GLSL450
221 OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
222 OpExecutionMode %main OriginUpperLeft
223 OpSource GLSL 140
224 OpName %main "main"
225 OpName %v "v"
226 OpName %BaseColor "BaseColor"
227 OpName %fi "fi"
228 OpName %r "r"
229 OpName %gl_FragColor "gl_FragColor"
230 %void = OpTypeVoid
231 %9 = OpTypeFunction %void
232 %float = OpTypeFloat 32
233 %v4float = OpTypeVector %float 4
234 %_ptr_Function_v4float = OpTypePointer Function %v4float
235 %_ptr_Input_v4float = OpTypePointer Input %v4float
236 %BaseColor = OpVariable %_ptr_Input_v4float Input
237 %_ptr_Input_float = OpTypePointer Input %float
238 %fi = OpVariable %_ptr_Input_float Input
239 %float_0 = OpConstant %float 0
240 %bool = OpTypeBool
241 %float_1 = OpConstant %float 1
242 %_ptr_Output_v4float = OpTypePointer Output %v4float
243 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
244 )";
245 
246   const std::string before =
247       R"(%main = OpFunction %void None %9
248 %19 = OpLabel
249 %v = OpVariable %_ptr_Function_v4float Function
250 %r = OpVariable %_ptr_Function_v4float Function
251 %20 = OpLoad %v4float %BaseColor
252 OpStore %v %20
253 %21 = OpLoad %float %fi
254 %22 = OpFOrdLessThan %bool %21 %float_0
255 OpSelectionMerge %23 None
256 OpBranchConditional %22 %24 %25
257 %24 = OpLabel
258 %26 = OpLoad %v4float %v
259 OpStore %v %26
260 OpStore %r %26
261 OpBranch %23
262 %25 = OpLabel
263 %27 = OpLoad %v4float %v
264 %28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1
265 OpStore %v %28
266 %29 = OpFSub %v4float %28 %27
267 OpStore %r %29
268 OpBranch %23
269 %23 = OpLabel
270 %30 = OpLoad %v4float %r
271 OpStore %gl_FragColor %30
272 OpReturn
273 OpFunctionEnd
274 )";
275 
276   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
277                                                   predefs + before, true, true);
278 }
279 
TEST_F(LocalSingleStoreElimTest, MultipleLoads)280 TEST_F(LocalSingleStoreElimTest, MultipleLoads) {
281   // Single store to multiple loads of v is optimized.
282   //
283   // #version 140
284   //
285   // in vec4 BaseColor;
286   // in float fi;
287   //
288   // void main()
289   // {
290   //     vec4 v = BaseColor;
291   //     float f = fi;
292   //     if (f < 0)
293   //         f = 0.0;
294   //     gl_FragColor = v + f;
295   // }
296 
297   const std::string predefs =
298       R"(OpCapability Shader
299 %1 = OpExtInstImport "GLSL.std.450"
300 OpMemoryModel Logical GLSL450
301 OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
302 OpExecutionMode %main OriginUpperLeft
303 OpSource GLSL 140
304 OpName %main "main"
305 OpName %v "v"
306 OpName %BaseColor "BaseColor"
307 OpName %fi "fi"
308 OpName %r "r"
309 OpName %gl_FragColor "gl_FragColor"
310 %void = OpTypeVoid
311 %9 = OpTypeFunction %void
312 %float = OpTypeFloat 32
313 %v4float = OpTypeVector %float 4
314 %_ptr_Function_v4float = OpTypePointer Function %v4float
315 %_ptr_Input_v4float = OpTypePointer Input %v4float
316 %BaseColor = OpVariable %_ptr_Input_v4float Input
317 %_ptr_Input_float = OpTypePointer Input %float
318 %fi = OpVariable %_ptr_Input_float Input
319 %float_0 = OpConstant %float 0
320 %bool = OpTypeBool
321 %float_1 = OpConstant %float 1
322 %_ptr_Output_v4float = OpTypePointer Output %v4float
323 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
324 )";
325 
326   const std::string before =
327       R"(%main = OpFunction %void None %9
328 %19 = OpLabel
329 %v = OpVariable %_ptr_Function_v4float Function
330 %r = OpVariable %_ptr_Function_v4float Function
331 %20 = OpLoad %v4float %BaseColor
332 OpStore %v %20
333 %21 = OpLoad %float %fi
334 %22 = OpFOrdLessThan %bool %21 %float_0
335 OpSelectionMerge %23 None
336 OpBranchConditional %22 %24 %25
337 %24 = OpLabel
338 %26 = OpLoad %v4float %v
339 OpStore %r %26
340 OpBranch %23
341 %25 = OpLabel
342 %27 = OpLoad %v4float %v
343 %28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1
344 %29 = OpFSub %v4float %28 %27
345 OpStore %r %29
346 OpBranch %23
347 %23 = OpLabel
348 %30 = OpLoad %v4float %r
349 OpStore %gl_FragColor %30
350 OpReturn
351 OpFunctionEnd
352 )";
353 
354   const std::string after =
355       R"(%main = OpFunction %void None %9
356 %19 = OpLabel
357 %v = OpVariable %_ptr_Function_v4float Function
358 %r = OpVariable %_ptr_Function_v4float Function
359 %20 = OpLoad %v4float %BaseColor
360 OpStore %v %20
361 %21 = OpLoad %float %fi
362 %22 = OpFOrdLessThan %bool %21 %float_0
363 OpSelectionMerge %23 None
364 OpBranchConditional %22 %24 %25
365 %24 = OpLabel
366 OpStore %r %20
367 OpBranch %23
368 %25 = OpLabel
369 %28 = OpCompositeConstruct %v4float %float_1 %float_1 %float_1 %float_1
370 %29 = OpFSub %v4float %28 %20
371 OpStore %r %29
372 OpBranch %23
373 %23 = OpLabel
374 %30 = OpLoad %v4float %r
375 OpStore %gl_FragColor %30
376 OpReturn
377 OpFunctionEnd
378 )";
379 
380   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
381                                                   predefs + after, true, true);
382 }
383 
TEST_F(LocalSingleStoreElimTest, NoStoreElimWithInterveningAccessChainLoad)384 TEST_F(LocalSingleStoreElimTest, NoStoreElimWithInterveningAccessChainLoad) {
385   // Last load of v is eliminated, but access chain load and store of v isn't
386   //
387   // #version 140
388   //
389   // in vec4 BaseColor;
390   //
391   // void main()
392   // {
393   //     vec4 v = BaseColor;
394   //     float f = v[3];
395   //     gl_FragColor = v * f;
396   // }
397 
398   const std::string predefs =
399       R"(OpCapability Shader
400 %1 = OpExtInstImport "GLSL.std.450"
401 OpMemoryModel Logical GLSL450
402 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
403 OpExecutionMode %main OriginUpperLeft
404 OpSource GLSL 140
405 OpName %main "main"
406 OpName %v "v"
407 OpName %BaseColor "BaseColor"
408 OpName %f "f"
409 OpName %gl_FragColor "gl_FragColor"
410 %void = OpTypeVoid
411 %8 = OpTypeFunction %void
412 %float = OpTypeFloat 32
413 %v4float = OpTypeVector %float 4
414 %_ptr_Function_v4float = OpTypePointer Function %v4float
415 %_ptr_Input_v4float = OpTypePointer Input %v4float
416 %BaseColor = OpVariable %_ptr_Input_v4float Input
417 %_ptr_Function_float = OpTypePointer Function %float
418 %uint = OpTypeInt 32 0
419 %uint_3 = OpConstant %uint 3
420 %_ptr_Output_v4float = OpTypePointer Output %v4float
421 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
422 )";
423 
424   const std::string before =
425       R"(%main = OpFunction %void None %8
426 %17 = OpLabel
427 %v = OpVariable %_ptr_Function_v4float Function
428 %f = OpVariable %_ptr_Function_float Function
429 %18 = OpLoad %v4float %BaseColor
430 OpStore %v %18
431 %19 = OpAccessChain %_ptr_Function_float %v %uint_3
432 %20 = OpLoad %float %19
433 OpStore %f %20
434 %21 = OpLoad %v4float %v
435 %22 = OpLoad %float %f
436 %23 = OpVectorTimesScalar %v4float %21 %22
437 OpStore %gl_FragColor %23
438 OpReturn
439 OpFunctionEnd
440 )";
441 
442   const std::string after =
443       R"(%main = OpFunction %void None %8
444 %17 = OpLabel
445 %v = OpVariable %_ptr_Function_v4float Function
446 %f = OpVariable %_ptr_Function_float Function
447 %18 = OpLoad %v4float %BaseColor
448 OpStore %v %18
449 %19 = OpAccessChain %_ptr_Function_float %v %uint_3
450 %20 = OpLoad %float %19
451 OpStore %f %20
452 %23 = OpVectorTimesScalar %v4float %18 %20
453 OpStore %gl_FragColor %23
454 OpReturn
455 OpFunctionEnd
456 )";
457 
458   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
459                                                   predefs + after, true, true);
460 }
461 
TEST_F(LocalSingleStoreElimTest, NoReplaceOfDominatingPartialStore)462 TEST_F(LocalSingleStoreElimTest, NoReplaceOfDominatingPartialStore) {
463   // Note: SPIR-V hand edited to initialize v to vec4(0.0)
464   //
465   // #version 140
466   //
467   // in vec4 BaseColor;
468   //
469   // void main()
470   // {
471   //     vec4 v;
472   //     float v[1] = 1.0;
473   //     gl_FragColor = v;
474   // }
475 
476   const std::string assembly =
477       R"(OpCapability Shader
478 %1 = OpExtInstImport "GLSL.std.450"
479 OpMemoryModel Logical GLSL450
480 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
481 OpExecutionMode %main OriginUpperLeft
482 OpSource GLSL 140
483 OpName %main "main"
484 OpName %v "v"
485 OpName %gl_FragColor "gl_FragColor"
486 OpName %BaseColor "BaseColor"
487 %void = OpTypeVoid
488 %7 = OpTypeFunction %void
489 %float = OpTypeFloat 32
490 %v4float = OpTypeVector %float 4
491 %_ptr_Function_v4float = OpTypePointer Function %v4float
492 %float_0 = OpConstant %float 0
493 %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
494 %float_1 = OpConstant %float 1
495 %uint = OpTypeInt 32 0
496 %uint_1 = OpConstant %uint 1
497 %_ptr_Function_float = OpTypePointer Function %float
498 %_ptr_Output_v4float = OpTypePointer Output %v4float
499 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
500 %_ptr_Input_v4float = OpTypePointer Input %v4float
501 %BaseColor = OpVariable %_ptr_Input_v4float Input
502 %main = OpFunction %void None %7
503 %19 = OpLabel
504 %v = OpVariable %_ptr_Function_v4float Function %12
505 %20 = OpAccessChain %_ptr_Function_float %v %uint_1
506 OpStore %20 %float_1
507 %21 = OpLoad %v4float %v
508 OpStore %gl_FragColor %21
509 OpReturn
510 OpFunctionEnd
511 )";
512 
513   SinglePassRunAndCheck<LocalSingleStoreElimPass>(assembly, assembly, true,
514                                                   true);
515 }
516 
TEST_F(LocalSingleStoreElimTest, ElimIfCopyObjectInFunction)517 TEST_F(LocalSingleStoreElimTest, ElimIfCopyObjectInFunction) {
518   // Note: hand edited to insert OpCopyObject
519   //
520   // #version 140
521   //
522   // in vec4 BaseColor;
523   // in float fi;
524   //
525   // void main()
526   // {
527   //     vec4 v = BaseColor;
528   //     float f = fi;
529   //     if (f < 0)
530   //         f = 0.0;
531   //     gl_FragColor = v + f;
532   // }
533 
534   const std::string predefs =
535       R"(OpCapability Shader
536 %1 = OpExtInstImport "GLSL.std.450"
537 OpMemoryModel Logical GLSL450
538 OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
539 OpExecutionMode %main OriginUpperLeft
540 OpSource GLSL 140
541 OpName %main "main"
542 OpName %v "v"
543 OpName %BaseColor "BaseColor"
544 OpName %f "f"
545 OpName %fi "fi"
546 OpName %gl_FragColor "gl_FragColor"
547 %void = OpTypeVoid
548 %9 = OpTypeFunction %void
549 %float = OpTypeFloat 32
550 %v4float = OpTypeVector %float 4
551 %_ptr_Function_v4float = OpTypePointer Function %v4float
552 %_ptr_Input_v4float = OpTypePointer Input %v4float
553 %BaseColor = OpVariable %_ptr_Input_v4float Input
554 %_ptr_Function_float = OpTypePointer Function %float
555 %_ptr_Input_float = OpTypePointer Input %float
556 %fi = OpVariable %_ptr_Input_float Input
557 %float_0 = OpConstant %float 0
558 %bool = OpTypeBool
559 %_ptr_Output_v4float = OpTypePointer Output %v4float
560 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
561 )";
562 
563   const std::string before =
564       R"(%main = OpFunction %void None %9
565 %19 = OpLabel
566 %v = OpVariable %_ptr_Function_v4float Function
567 %f = OpVariable %_ptr_Function_float Function
568 %20 = OpLoad %v4float %BaseColor
569 OpStore %v %20
570 %21 = OpLoad %float %fi
571 OpStore %f %21
572 %22 = OpLoad %float %f
573 %23 = OpFOrdLessThan %bool %22 %float_0
574 OpSelectionMerge %24 None
575 OpBranchConditional %23 %25 %24
576 %25 = OpLabel
577 OpStore %f %float_0
578 OpBranch %24
579 %24 = OpLabel
580 %26 = OpCopyObject %_ptr_Function_v4float %v
581 %27 = OpLoad %v4float %26
582 %28 = OpLoad %float %f
583 %29 = OpCompositeConstruct %v4float %28 %28 %28 %28
584 %30 = OpFAdd %v4float %27 %29
585 OpStore %gl_FragColor %30
586 OpReturn
587 OpFunctionEnd
588 )";
589 
590   const std::string after =
591       R"(%main = OpFunction %void None %9
592 %19 = OpLabel
593 %v = OpVariable %_ptr_Function_v4float Function
594 %f = OpVariable %_ptr_Function_float Function
595 %20 = OpLoad %v4float %BaseColor
596 OpStore %v %20
597 %21 = OpLoad %float %fi
598 OpStore %f %21
599 %22 = OpLoad %float %f
600 %23 = OpFOrdLessThan %bool %22 %float_0
601 OpSelectionMerge %24 None
602 OpBranchConditional %23 %25 %24
603 %25 = OpLabel
604 OpStore %f %float_0
605 OpBranch %24
606 %24 = OpLabel
607 %26 = OpCopyObject %_ptr_Function_v4float %v
608 %28 = OpLoad %float %f
609 %29 = OpCompositeConstruct %v4float %28 %28 %28 %28
610 %30 = OpFAdd %v4float %20 %29
611 OpStore %gl_FragColor %30
612 OpReturn
613 OpFunctionEnd
614 )";
615 
616   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
617                                                   predefs + after, true, true);
618 }
619 
TEST_F(LocalSingleStoreElimTest, NoOptIfStoreNotDominating)620 TEST_F(LocalSingleStoreElimTest, NoOptIfStoreNotDominating) {
621   // Single store to f not optimized because it does not dominate
622   // the load.
623   //
624   // #version 140
625   //
626   // in vec4 BaseColor;
627   // in float fi;
628   //
629   // void main()
630   // {
631   //     float f;
632   //     if (fi < 0)
633   //         f = 0.5;
634   //     if (fi < 0)
635   //         gl_FragColor = BaseColor * f;
636   //     else
637   //         gl_FragColor = BaseColor;
638   // }
639 
640   const std::string assembly =
641       R"(OpCapability Shader
642 %1 = OpExtInstImport "GLSL.std.450"
643 OpMemoryModel Logical GLSL450
644 OpEntryPoint Fragment %main "main" %fi %gl_FragColor %BaseColor
645 OpExecutionMode %main OriginUpperLeft
646 OpSource GLSL 140
647 OpName %main "main"
648 OpName %fi "fi"
649 OpName %f "f"
650 OpName %gl_FragColor "gl_FragColor"
651 OpName %BaseColor "BaseColor"
652 %void = OpTypeVoid
653 %8 = OpTypeFunction %void
654 %float = OpTypeFloat 32
655 %_ptr_Input_float = OpTypePointer Input %float
656 %fi = OpVariable %_ptr_Input_float Input
657 %float_0 = OpConstant %float 0
658 %bool = OpTypeBool
659 %_ptr_Function_float = OpTypePointer Function %float
660 %float_0_5 = OpConstant %float 0.5
661 %v4float = OpTypeVector %float 4
662 %_ptr_Output_v4float = OpTypePointer Output %v4float
663 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
664 %_ptr_Input_v4float = OpTypePointer Input %v4float
665 %BaseColor = OpVariable %_ptr_Input_v4float Input
666 %main = OpFunction %void None %8
667 %18 = OpLabel
668 %f = OpVariable %_ptr_Function_float Function
669 %19 = OpLoad %float %fi
670 %20 = OpFOrdLessThan %bool %19 %float_0
671 OpSelectionMerge %21 None
672 OpBranchConditional %20 %22 %21
673 %22 = OpLabel
674 OpStore %f %float_0_5
675 OpBranch %21
676 %21 = OpLabel
677 %23 = OpLoad %float %fi
678 %24 = OpFOrdLessThan %bool %23 %float_0
679 OpSelectionMerge %25 None
680 OpBranchConditional %24 %26 %27
681 %26 = OpLabel
682 %28 = OpLoad %v4float %BaseColor
683 %29 = OpLoad %float %f
684 %30 = OpVectorTimesScalar %v4float %28 %29
685 OpStore %gl_FragColor %30
686 OpBranch %25
687 %27 = OpLabel
688 %31 = OpLoad %v4float %BaseColor
689 OpStore %gl_FragColor %31
690 OpBranch %25
691 %25 = OpLabel
692 OpReturn
693 OpFunctionEnd
694 )";
695 
696   SinglePassRunAndCheck<LocalSingleStoreElimPass>(assembly, assembly, true,
697                                                   true);
698 }
699 
TEST_F(LocalSingleStoreElimTest, OptInitializedVariableLikeStore)700 TEST_F(LocalSingleStoreElimTest, OptInitializedVariableLikeStore) {
701   // Initialized variable f is optimized like it was a store.
702   // Note: The SPIR-V was edited to turn the store to f to an
703   // an initialization.
704   //
705   // #version 140
706   //
707   // void main()
708   // {
709   //     float f = 0.0;
710   //     gl_FragColor = vec4(f);
711   // }
712 
713   const std::string predefs =
714       R"(OpCapability Shader
715 %1 = OpExtInstImport "GLSL.std.450"
716 OpMemoryModel Logical GLSL450
717 OpEntryPoint Fragment %main "main" %gl_FragColor
718 OpExecutionMode %main OriginUpperLeft
719 OpSource GLSL 140
720 OpName %main "main"
721 OpName %f "f"
722 OpName %gl_FragColor "gl_FragColor"
723 OpDecorate %gl_FragColor Location 0
724 %void = OpTypeVoid
725 %6 = OpTypeFunction %void
726 %float = OpTypeFloat 32
727 %_ptr_Function_float = OpTypePointer Function %float
728 %float_0 = OpConstant %float 0
729 %v4float = OpTypeVector %float 4
730 %_ptr_Output_v4float = OpTypePointer Output %v4float
731 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
732 )";
733 
734   const std::string before =
735       R"(%main = OpFunction %void None %6
736 %12 = OpLabel
737 %f = OpVariable %_ptr_Function_float Function %float_0
738 %13 = OpLoad %float %f
739 %14 = OpCompositeConstruct %v4float %13 %13 %13 %13
740 OpStore %gl_FragColor %14
741 OpReturn
742 OpFunctionEnd
743 )";
744 
745   const std::string after =
746       R"(%main = OpFunction %void None %6
747 %12 = OpLabel
748 %f = OpVariable %_ptr_Function_float Function %float_0
749 %14 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_0
750 OpStore %gl_FragColor %14
751 OpReturn
752 OpFunctionEnd
753 )";
754 
755   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
756                                                   predefs + after, true, true);
757 }
758 
TEST_F(LocalSingleStoreElimTest, PointerVariable)759 TEST_F(LocalSingleStoreElimTest, PointerVariable) {
760   // Test that checks if a pointer variable is removed.
761 
762   const std::string before =
763       R"(OpCapability Shader
764 OpMemoryModel Logical GLSL450
765 OpEntryPoint Fragment %1 "main" %2
766 OpExecutionMode %1 OriginUpperLeft
767 OpMemberDecorate %_struct_3 0 Offset 0
768 OpDecorate %_runtimearr__struct_3 ArrayStride 16
769 OpMemberDecorate %_struct_5 0 Offset 0
770 OpDecorate %_struct_5 BufferBlock
771 OpMemberDecorate %_struct_6 0 Offset 0
772 OpDecorate %_struct_6 BufferBlock
773 OpDecorate %2 Location 0
774 OpDecorate %7 DescriptorSet 0
775 OpDecorate %7 Binding 0
776 %void = OpTypeVoid
777 %10 = OpTypeFunction %void
778 %int = OpTypeInt 32 1
779 %uint = OpTypeInt 32 0
780 %float = OpTypeFloat 32
781 %v4float = OpTypeVector %float 4
782 %_ptr_Output_v4float = OpTypePointer Output %v4float
783 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
784 %_struct_3 = OpTypeStruct %v4float
785 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
786 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
787 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
788 %_struct_6 = OpTypeStruct %int
789 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
790 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
791 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
792 %int_0 = OpConstant %int 0
793 %uint_0 = OpConstant %uint 0
794 %2 = OpVariable %_ptr_Output_v4float Output
795 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
796 %1 = OpFunction %void None %10
797 %23 = OpLabel
798 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
799 OpStore %24 %7
800 %26 = OpLoad %_ptr_Uniform__struct_5 %24
801 %27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0
802 %28 = OpLoad %v4float %27
803 %29 = OpCopyObject %v4float %28
804 OpStore %2 %28
805 OpReturn
806 OpFunctionEnd
807 )";
808 
809   const std::string after =
810       R"(OpCapability Shader
811 OpMemoryModel Logical GLSL450
812 OpEntryPoint Fragment %1 "main" %2
813 OpExecutionMode %1 OriginUpperLeft
814 OpMemberDecorate %_struct_3 0 Offset 0
815 OpDecorate %_runtimearr__struct_3 ArrayStride 16
816 OpMemberDecorate %_struct_5 0 Offset 0
817 OpDecorate %_struct_5 BufferBlock
818 OpMemberDecorate %_struct_6 0 Offset 0
819 OpDecorate %_struct_6 BufferBlock
820 OpDecorate %2 Location 0
821 OpDecorate %7 DescriptorSet 0
822 OpDecorate %7 Binding 0
823 %void = OpTypeVoid
824 %10 = OpTypeFunction %void
825 %int = OpTypeInt 32 1
826 %uint = OpTypeInt 32 0
827 %float = OpTypeFloat 32
828 %v4float = OpTypeVector %float 4
829 %_ptr_Output_v4float = OpTypePointer Output %v4float
830 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
831 %_struct_3 = OpTypeStruct %v4float
832 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
833 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
834 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
835 %_struct_6 = OpTypeStruct %int
836 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
837 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
838 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
839 %int_0 = OpConstant %int 0
840 %uint_0 = OpConstant %uint 0
841 %2 = OpVariable %_ptr_Output_v4float Output
842 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
843 %1 = OpFunction %void None %10
844 %23 = OpLabel
845 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
846 OpStore %24 %7
847 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
848 %28 = OpLoad %v4float %27
849 %29 = OpCopyObject %v4float %28
850 OpStore %2 %28
851 OpReturn
852 OpFunctionEnd
853 )";
854 
855   // Relax logical pointers to allow pointer allocations.
856   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
857   ValidatorOptions()->relax_logical_pointer = true;
858   SinglePassRunAndCheck<LocalSingleStoreElimPass>(before, after, true, true);
859 }
860 
861 // Test that that an unused OpAccessChain between a store and a use does does
862 // not hinders the replacement of the use.  We need to check this because
863 // local-access-chain-convert does always remove the OpAccessChain instructions
864 // that become dead.
865 
TEST_F(LocalSingleStoreElimTest, StoreElimWithUnusedInterveningAccessChainLoad)866 TEST_F(LocalSingleStoreElimTest,
867        StoreElimWithUnusedInterveningAccessChainLoad) {
868   // Last load of v is eliminated, but access chain load and store of v isn't
869   //
870   // #version 140
871   //
872   // in vec4 BaseColor;
873   //
874   // void main()
875   // {
876   //     vec4 v = BaseColor;
877   //     float f = v[3];
878   //     gl_FragColor = v * f;
879   // }
880 
881   const std::string predefs =
882       R"(OpCapability Shader
883 %1 = OpExtInstImport "GLSL.std.450"
884 OpMemoryModel Logical GLSL450
885 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
886 OpExecutionMode %main OriginUpperLeft
887 OpSource GLSL 140
888 OpName %main "main"
889 OpName %v "v"
890 OpName %BaseColor "BaseColor"
891 OpName %gl_FragColor "gl_FragColor"
892 %void = OpTypeVoid
893 %8 = OpTypeFunction %void
894 %float = OpTypeFloat 32
895 %v4float = OpTypeVector %float 4
896 %_ptr_Function_v4float = OpTypePointer Function %v4float
897 %_ptr_Input_v4float = OpTypePointer Input %v4float
898 %BaseColor = OpVariable %_ptr_Input_v4float Input
899 %_ptr_Function_float = OpTypePointer Function %float
900 %uint = OpTypeInt 32 0
901 %uint_3 = OpConstant %uint 3
902 %_ptr_Output_v4float = OpTypePointer Output %v4float
903 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
904 )";
905 
906   const std::string before =
907       R"(%main = OpFunction %void None %8
908 %17 = OpLabel
909 %v = OpVariable %_ptr_Function_v4float Function
910 %18 = OpLoad %v4float %BaseColor
911 OpStore %v %18
912 %19 = OpAccessChain %_ptr_Function_float %v %uint_3
913 %21 = OpLoad %v4float %v
914 OpStore %gl_FragColor %21
915 OpReturn
916 OpFunctionEnd
917 )";
918 
919   const std::string after =
920       R"(%main = OpFunction %void None %8
921 %17 = OpLabel
922 %v = OpVariable %_ptr_Function_v4float Function
923 %18 = OpLoad %v4float %BaseColor
924 OpStore %v %18
925 %19 = OpAccessChain %_ptr_Function_float %v %uint_3
926 OpStore %gl_FragColor %18
927 OpReturn
928 OpFunctionEnd
929 )";
930 
931   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
932   SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
933                                                   predefs + after, true, true);
934 }
935 
TEST_F(LocalSingleStoreElimTest, VariablePointerTest)936 TEST_F(LocalSingleStoreElimTest, VariablePointerTest) {
937   // Check that the load of the first variable is still used and that the load
938   // of the third variable is propagated.  The first load has to remain because
939   // of the store to the variable pointer.
940   const std::string text = R"(
941 ; CHECK: [[v1:%\w+]] = OpVariable
942 ; CHECK: [[v2:%\w+]] = OpVariable
943 ; CHECK: [[v3:%\w+]] = OpVariable
944 ; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]]
945 ; CHECK: OpIAdd %int [[ld1]] %int_0
946                OpCapability Shader
947                OpCapability VariablePointers
948           %1 = OpExtInstImport "GLSL.std.450"
949                OpMemoryModel Logical GLSL450
950                OpEntryPoint GLCompute %2 "main"
951                OpExecutionMode %2 LocalSize 1 1 1
952                OpSource GLSL 450
953                OpMemberDecorate %_struct_3 0 Offset 0
954                OpMemberDecorate %_struct_3 1 Offset 4
955        %void = OpTypeVoid
956           %5 = OpTypeFunction %void
957         %int = OpTypeInt 32 1
958        %bool = OpTypeBool
959   %_struct_3 = OpTypeStruct %int %int
960 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
961 %_ptr_Function_int = OpTypePointer Function %int
962        %true = OpConstantTrue %bool
963       %int_0 = OpConstant %int 0
964       %int_1 = OpConstant %int 1
965          %13 = OpConstantNull %_struct_3
966           %2 = OpFunction %void None %5
967          %14 = OpLabel
968          %15 = OpVariable %_ptr_Function_int Function
969          %16 = OpVariable %_ptr_Function_int Function
970          %17 = OpVariable %_ptr_Function_int Function
971                OpStore %15 %int_1
972                OpStore %17 %int_0
973                OpSelectionMerge %18 None
974                OpBranchConditional %true %19 %20
975          %19 = OpLabel
976                OpBranch %18
977          %20 = OpLabel
978                OpBranch %18
979          %18 = OpLabel
980          %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20
981                OpStore %21 %int_0
982          %22 = OpLoad %int %15
983          %23 = OpLoad %int %17
984          %24 = OpIAdd %int %22 %23
985                OpReturn
986                OpFunctionEnd
987   )";
988   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
989 }
990 
TEST_F(LocalSingleStoreElimTest, DebugDeclareTest)991 TEST_F(LocalSingleStoreElimTest, DebugDeclareTest) {
992   // If OpenCL.DebugInfo.100 enabled, check that store/load is still
993   // optimized, DebugValue placed after the store and the associated
994   // DebugDeclare is removed.
995   const std::string text = R"(
996                OpCapability Shader
997           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
998                OpMemoryModel Logical GLSL450
999                OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
1000                OpExecutionMode %MainPs OriginUpperLeft
1001          %20 = OpString "foo.frag"
1002          %24 = OpString "PS_OUTPUT"
1003          %28 = OpString "float"
1004          %31 = OpString "vColor"
1005          %33 = OpString "PS_INPUT"
1006          %38 = OpString "vTextureCoords"
1007          %40 = OpString "@type.2d.image"
1008          %41 = OpString "type.2d.image"
1009          %43 = OpString "Texture2D.TemplateParam"
1010          %47 = OpString "src.MainPs"
1011          %51 = OpString "tc"
1012          %53 = OpString "ps_output"
1013          %56 = OpString "i"
1014          %58 = OpString "@type.sampler"
1015          %59 = OpString "type.sampler"
1016          %61 = OpString "g_sAniso"
1017          %63 = OpString "g_tColor"
1018                OpName %type_2d_image "type.2d.image"
1019                OpName %g_tColor "g_tColor"
1020                OpName %type_sampler "type.sampler"
1021                OpName %g_sAniso "g_sAniso"
1022                OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
1023                OpName %out_var_SV_Target0 "out.var.SV_Target0"
1024                OpName %MainPs "MainPs"
1025                OpName %PS_INPUT "PS_INPUT"
1026                OpMemberName %PS_INPUT 0 "vTextureCoords"
1027                OpName %param_var_i "param.var.i"
1028                OpName %PS_OUTPUT "PS_OUTPUT"
1029                OpMemberName %PS_OUTPUT 0 "vColor"
1030                OpName %type_sampled_image "type.sampled.image"
1031                OpDecorate %in_var_TEXCOORD2 Location 0
1032                OpDecorate %out_var_SV_Target0 Location 0
1033                OpDecorate %g_tColor DescriptorSet 0
1034                OpDecorate %g_tColor Binding 0
1035                OpDecorate %g_sAniso DescriptorSet 0
1036                OpDecorate %g_sAniso Binding 1
1037         %int = OpTypeInt 32 1
1038       %int_0 = OpConstant %int 0
1039        %uint = OpTypeInt 32 0
1040     %uint_32 = OpConstant %uint 32
1041       %float = OpTypeFloat 32
1042 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
1043 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
1044 %type_sampler = OpTypeSampler
1045 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
1046     %v2float = OpTypeVector %float 2
1047 %_ptr_Input_v2float = OpTypePointer Input %v2float
1048     %v4float = OpTypeVector %float 4
1049 %_ptr_Output_v4float = OpTypePointer Output %v4float
1050        %void = OpTypeVoid
1051    %uint_128 = OpConstant %uint 128
1052      %uint_0 = OpConstant %uint 0
1053     %uint_64 = OpConstant %uint 64
1054          %65 = OpTypeFunction %void
1055    %PS_INPUT = OpTypeStruct %v2float
1056 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1057   %PS_OUTPUT = OpTypeStruct %v4float
1058          %75 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1059 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1060 %_ptr_Function_v2float = OpTypePointer Function %v2float
1061 %type_sampled_image = OpTypeSampledImage %type_2d_image
1062 %_ptr_Function_v4float = OpTypePointer Function %v4float
1063    %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
1064    %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
1065 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
1066 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
1067          %39 = OpExtInst %void %1 DebugInfoNone
1068          %55 = OpExtInst %void %1 DebugExpression
1069          %22 = OpExtInst %void %1 DebugSource %20
1070          %23 = OpExtInst %void %1 DebugCompilationUnit 1 4 %22 HLSL
1071          %26 = OpExtInst %void %1 DebugTypeComposite %24 Structure %22 10 1 %23 %24 %uint_128 FlagIsProtected|FlagIsPrivate %27
1072          %29 = OpExtInst %void %1 DebugTypeBasic %28 %uint_32 Float
1073          %30 = OpExtInst %void %1 DebugTypeVector %29 4
1074          %27 = OpExtInst %void %1 DebugTypeMember %31 %30 %22 12 5 %26 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1075          %35 = OpExtInst %void %1 DebugTypeComposite %33 Structure %22 5 1 %23 %33 %uint_64 FlagIsProtected|FlagIsPrivate %36
1076          %37 = OpExtInst %void %1 DebugTypeVector %29 2
1077          %36 = OpExtInst %void %1 DebugTypeMember %38 %37 %22 7 5 %35 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
1078          %42 = OpExtInst %void %1 DebugTypeComposite %40 Class %22 0 0 %23 %41 %39 FlagIsProtected|FlagIsPrivate
1079          %44 = OpExtInst %void %1 DebugTypeTemplateParameter %43 %29 %39 %22 0 0
1080          %45 = OpExtInst %void %1 DebugTypeTemplate %42 %44
1081          %46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %26 %35
1082          %48 = OpExtInst %void %1 DebugFunction %47 %46 %22 15 1 %23 %47 FlagIsProtected|FlagIsPrivate 16 %39
1083          %50 = OpExtInst %void %1 DebugLexicalBlock %22 16 1 %48
1084          %52 = OpExtInst %void %1 DebugLocalVariable %51 %37 %22 19 12 %50 FlagIsLocal
1085          %54 = OpExtInst %void %1 DebugLocalVariable %53 %26 %22 17 15 %50 FlagIsLocal
1086          %57 = OpExtInst %void %1 DebugLocalVariable %56 %35 %22 15 29 %48 FlagIsLocal 1
1087          %60 = OpExtInst %void %1 DebugTypeComposite %58 Structure %22 0 0 %23 %59 %39 FlagIsProtected|FlagIsPrivate
1088          %62 = OpExtInst %void %1 DebugGlobalVariable %61 %60 %22 3 14 %23 %61 %g_sAniso FlagIsDefinition
1089          %64 = OpExtInst %void %1 DebugGlobalVariable %63 %42 %22 1 11 %23 %63 %g_tColor FlagIsDefinition
1090      %MainPs = OpFunction %void None %65
1091          %66 = OpLabel
1092         %114 = OpExtInst %void %1 DebugScope %50
1093          %98 = OpVariable %_ptr_Function_PS_OUTPUT Function
1094          %99 = OpVariable %_ptr_Function_v2float Function
1095         %115 = OpExtInst %void %1 DebugNoScope
1096         %100 = OpVariable %_ptr_Function_PS_OUTPUT Function
1097 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
1098          %70 = OpLoad %v2float %in_var_TEXCOORD2
1099          %71 = OpCompositeConstruct %PS_INPUT %70
1100                OpStore %param_var_i %71
1101         %116 = OpExtInst %void %1 DebugScope %48
1102         %102 = OpExtInst %void %1 DebugDeclare %57 %param_var_i %55
1103         %117 = OpExtInst %void %1 DebugScope %50
1104         %103 = OpExtInst %void %1 DebugDeclare %54 %98 %55
1105                OpLine %20 19 17
1106         %104 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
1107         %105 = OpLoad %v2float %104
1108                OpLine %20 19 12
1109                OpStore %99 %105
1110         %106 = OpExtInst %void %1 DebugDeclare %52 %99 %55
1111 ;CHECK-NOT: %106 = OpExtInst %void %1 DebugDeclare %52 %99 %55
1112 ;CHECK:     %119 = OpExtInst %void %1 DebugValue %52 %105 %55
1113                OpLine %20 20 26
1114         %107 = OpLoad %type_2d_image %g_tColor
1115                OpLine %20 20 46
1116         %108 = OpLoad %type_sampler %g_sAniso
1117                OpLine %20 20 57
1118         %109 = OpLoad %v2float %99
1119 ;CHECK-NOT: %109 = OpLoad %v2float %99
1120                OpLine %20 20 26
1121         %110 = OpSampledImage %type_sampled_image %107 %108
1122         %111 = OpImageSampleImplicitLod %v4float %110 %109 None
1123 ;CHECK-NOT: %111 = OpImageSampleImplicitLod %v4float %110 %109 None
1124 ;CHECK:     %111 = OpImageSampleImplicitLod %v4float %110 %105 None
1125                OpLine %20 20 5
1126         %112 = OpAccessChain %_ptr_Function_v4float %98 %int_0
1127                OpStore %112 %111
1128                OpLine %20 21 12
1129         %113 = OpLoad %PS_OUTPUT %98
1130                OpLine %20 21 5
1131                OpStore %100 %113
1132         %118 = OpExtInst %void %1 DebugNoScope
1133          %73 = OpLoad %PS_OUTPUT %100
1134          %74 = OpCompositeExtract %v4float %73 0
1135                OpStore %out_var_SV_Target0 %74
1136                OpReturn
1137                OpFunctionEnd
1138   )";
1139 
1140   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1141   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1142 }
1143 
TEST_F(LocalSingleStoreElimTest, DebugValueTest)1144 TEST_F(LocalSingleStoreElimTest, DebugValueTest) {
1145   // If OpenCL.DebugInfo.100 enabled, check that store/load is still
1146   // optimized, DebugValue placed after the store and the associated
1147   // DebugValue Deref is removed.
1148   const std::string text = R"(
1149                  OpCapability Shader
1150           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1151                OpMemoryModel Logical GLSL450
1152                OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0
1153                OpExecutionMode %MainPs OriginUpperLeft
1154           %7 = OpString "foo.frag"
1155           %8 = OpString "PS_OUTPUT"
1156           %9 = OpString "float"
1157          %10 = OpString "vColor"
1158          %11 = OpString "PS_INPUT"
1159          %12 = OpString "vTextureCoords"
1160          %13 = OpString "@type.2d.image"
1161          %14 = OpString "type.2d.image"
1162          %15 = OpString "Texture2D.TemplateParam"
1163          %16 = OpString "src.MainPs"
1164          %17 = OpString "tc"
1165          %18 = OpString "ps_output"
1166          %19 = OpString "i"
1167          %20 = OpString "@type.sampler"
1168          %21 = OpString "type.sampler"
1169          %22 = OpString "g_sAniso"
1170          %23 = OpString "g_tColor"
1171                OpName %type_2d_image "type.2d.image"
1172                OpName %g_tColor "g_tColor"
1173                OpName %type_sampler "type.sampler"
1174                OpName %g_sAniso "g_sAniso"
1175                OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
1176                OpName %out_var_SV_Target0 "out.var.SV_Target0"
1177                OpName %MainPs "MainPs"
1178                OpName %PS_INPUT "PS_INPUT"
1179                OpMemberName %PS_INPUT 0 "vTextureCoords"
1180                OpName %param_var_i "param.var.i"
1181                OpName %PS_OUTPUT "PS_OUTPUT"
1182                OpMemberName %PS_OUTPUT 0 "vColor"
1183                OpName %type_sampled_image "type.sampled.image"
1184                OpDecorate %in_var_TEXCOORD2 Location 0
1185                OpDecorate %out_var_SV_Target0 Location 0
1186                OpDecorate %g_tColor DescriptorSet 0
1187                OpDecorate %g_tColor Binding 0
1188                OpDecorate %g_sAniso DescriptorSet 0
1189                OpDecorate %g_sAniso Binding 1
1190         %int = OpTypeInt 32 1
1191       %int_0 = OpConstant %int 0
1192        %uint = OpTypeInt 32 0
1193     %uint_32 = OpConstant %uint 32
1194       %float = OpTypeFloat 32
1195 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
1196 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
1197 %type_sampler = OpTypeSampler
1198 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
1199     %v2float = OpTypeVector %float 2
1200 %_ptr_Input_v2float = OpTypePointer Input %v2float
1201     %v4float = OpTypeVector %float 4
1202 %_ptr_Output_v4float = OpTypePointer Output %v4float
1203        %void = OpTypeVoid
1204    %uint_128 = OpConstant %uint 128
1205      %uint_0 = OpConstant %uint 0
1206     %uint_64 = OpConstant %uint 64
1207          %45 = OpTypeFunction %void
1208    %PS_INPUT = OpTypeStruct %v2float
1209 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1210   %PS_OUTPUT = OpTypeStruct %v4float
1211          %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1212 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1213 %_ptr_Function_v2float = OpTypePointer Function %v2float
1214 %type_sampled_image = OpTypeSampledImage %type_2d_image
1215 %_ptr_Function_v4float = OpTypePointer Function %v4float
1216    %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
1217    %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
1218 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
1219 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
1220          %51 = OpExtInst %void %1 DebugInfoNone
1221          %52 = OpExtInst %void %1 DebugExpression
1222          %53 = OpExtInst %void %1 DebugOperation Deref
1223          %54 = OpExtInst %void %1 DebugExpression %53
1224          %55 = OpExtInst %void %1 DebugSource %7
1225          %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL
1226          %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58
1227          %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float
1228          %60 = OpExtInst %void %1 DebugTypeVector %59 4
1229          %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1230          %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62
1231          %63 = OpExtInst %void %1 DebugTypeVector %59 2
1232          %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
1233          %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate
1234          %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0
1235          %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65
1236          %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61
1237          %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51
1238          %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68
1239          %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal
1240          %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal
1241          %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1
1242          %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate
1243          %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition
1244          %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition
1245      %MainPs = OpFunction %void None %45
1246          %76 = OpLabel
1247         %101 = OpExtInst %void %1 DebugScope %69
1248          %78 = OpVariable %_ptr_Function_PS_OUTPUT Function
1249          %79 = OpVariable %_ptr_Function_v2float Function
1250         %102 = OpExtInst %void %1 DebugNoScope
1251          %81 = OpVariable %_ptr_Function_PS_OUTPUT Function
1252 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
1253          %82 = OpLoad %v2float %in_var_TEXCOORD2
1254          %83 = OpCompositeConstruct %PS_INPUT %82
1255                OpStore %param_var_i %83
1256         %103 = OpExtInst %void %1 DebugScope %68
1257          %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52
1258         %104 = OpExtInst %void %1 DebugScope %69
1259          %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52
1260                OpLine %7 19 17
1261          %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
1262          %89 = OpLoad %v2float %88
1263                OpLine %7 19 12
1264                OpStore %79 %89
1265          %90 = OpExtInst %void %1 DebugValue %70 %79 %54
1266 ;CHECK-NOT: %90 = OpExtInst %void %1 DebugValue %70 %79 %54
1267 ;CHECK:    %106 = OpExtInst %void %1 DebugValue %70 %89 %52
1268                OpLine %7 20 26
1269          %91 = OpLoad %type_2d_image %g_tColor
1270                OpLine %7 20 46
1271          %92 = OpLoad %type_sampler %g_sAniso
1272                OpLine %7 20 57
1273          %93 = OpLoad %v2float %79
1274 ;CHECK-NOT: %93 = OpLoad %v2float %79
1275                OpLine %7 20 26
1276          %94 = OpSampledImage %type_sampled_image %91 %92
1277          %95 = OpImageSampleImplicitLod %v4float %94 %93 None
1278 ;CHECK-NOT: %95 = OpImageSampleImplicitLod %v4float %94 %93 None
1279 ;CHECK:     %95 = OpImageSampleImplicitLod %v4float %94 %89 None
1280                OpLine %7 20 5
1281          %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0
1282                OpStore %96 %95
1283                OpLine %7 21 12
1284          %97 = OpLoad %PS_OUTPUT %78
1285                OpLine %7 21 5
1286                OpStore %81 %97
1287         %105 = OpExtInst %void %1 DebugNoScope
1288          %99 = OpLoad %PS_OUTPUT %81
1289         %100 = OpCompositeExtract %v4float %99 0
1290                OpStore %out_var_SV_Target0 %100
1291                OpReturn
1292                OpFunctionEnd
1293   )";
1294 
1295   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1296   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1297 }
1298 
TEST_F(LocalSingleStoreElimTest, UseStoreLineInfoForDebugValueLine)1299 TEST_F(LocalSingleStoreElimTest, UseStoreLineInfoForDebugValueLine) {
1300   // When the store is in the scope of OpenCL.DebugInfo.100 DebugDeclare,
1301   // the OpLine of the added OpenCL.DebugInfo.100 DebugValue must be the
1302   // same with the OpLine of the store.
1303   const std::string text = R"(
1304                OpCapability Shader
1305           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1306                OpMemoryModel Logical GLSL450
1307                OpEntryPoint Vertex %main "main" %in_var_POSITION %in_var_COLOR %gl_Position %out_var_COLOR
1308           %7 = OpString "simple.hlsl"
1309           %8 = OpString "float"
1310           %9 = OpString "VS_OUTPUT"
1311          %10 = OpString "color"
1312          %11 = OpString "pos"
1313          %12 = OpString "main"
1314          %13 = OpString ""
1315          %14 = OpString "vout"
1316                OpName %in_var_POSITION "in.var.POSITION"
1317                OpName %in_var_COLOR "in.var.COLOR"
1318                OpName %out_var_COLOR "out.var.COLOR"
1319                OpName %main "main"
1320                OpName %VS_OUTPUT "VS_OUTPUT"
1321                OpMemberName %VS_OUTPUT 0 "pos"
1322                OpMemberName %VS_OUTPUT 1 "color"
1323                OpDecorate %gl_Position BuiltIn Position
1324                OpDecorate %in_var_POSITION Location 0
1325                OpDecorate %in_var_COLOR Location 1
1326                OpDecorate %out_var_COLOR Location 0
1327         %int = OpTypeInt 32 1
1328       %int_0 = OpConstant %int 0
1329       %int_1 = OpConstant %int 1
1330        %uint = OpTypeInt 32 0
1331     %uint_32 = OpConstant %uint 32
1332       %float = OpTypeFloat 32
1333     %v4float = OpTypeVector %float 4
1334 %_ptr_Input_v4float = OpTypePointer Input %v4float
1335 %_ptr_Output_v4float = OpTypePointer Output %v4float
1336        %void = OpTypeVoid
1337    %uint_256 = OpConstant %uint 256
1338    %uint_128 = OpConstant %uint 128
1339      %uint_0 = OpConstant %uint 0
1340          %36 = OpTypeFunction %void
1341 %_ptr_Function_v4float = OpTypePointer Function %v4float
1342   %VS_OUTPUT = OpTypeStruct %v4float %v4float
1343 %_ptr_Function_VS_OUTPUT = OpTypePointer Function %VS_OUTPUT
1344 %in_var_POSITION = OpVariable %_ptr_Input_v4float Input
1345 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
1346 %gl_Position = OpVariable %_ptr_Output_v4float Output
1347 %out_var_COLOR = OpVariable %_ptr_Output_v4float Output
1348          %85 = OpExtInst %void %1 DebugOperation Deref
1349          %81 = OpExtInst %void %1 DebugInfoNone
1350          %52 = OpExtInst %void %1 DebugExpression
1351          %40 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
1352          %41 = OpExtInst %void %1 DebugTypeVector %40 4
1353          %42 = OpExtInst %void %1 DebugSource %7
1354          %43 = OpExtInst %void %1 DebugCompilationUnit 1 4 %42 HLSL
1355          %44 = OpExtInst %void %1 DebugTypeComposite %9 Structure %42 1 8 %43 %9 %uint_256 FlagIsProtected|FlagIsPrivate %45 %46
1356          %46 = OpExtInst %void %1 DebugTypeMember %10 %41 %42 3 10 %44 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
1357          %45 = OpExtInst %void %1 DebugTypeMember %11 %41 %42 2 10 %44 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1358          %47 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %44 %41 %41
1359          %48 = OpExtInst %void %1 DebugFunction %12 %47 %42 6 1 %43 %13 FlagIsProtected|FlagIsPrivate 7 %81
1360          %49 = OpExtInst %void %1 DebugLexicalBlock %42 7 38 %48
1361          %50 = OpExtInst %void %1 DebugLocalVariable %14 %44 %42 8 13 %49 FlagIsLocal
1362          %84 = OpExtInst %void %1 DebugExpression %85
1363        %main = OpFunction %void None %36
1364          %54 = OpLabel
1365          %91 = OpExtInst %void %1 DebugScope %49
1366                OpLine %7 7 23
1367          %83 = OpVariable %_ptr_Function_v4float Function
1368                OpLine %7 8 13
1369          %87 = OpExtInst %void %1 DebugValue %50 %83 %84 %int_1
1370                OpLine %7 7 23
1371          %82 = OpVariable %_ptr_Function_v4float Function
1372                OpLine %7 8 13
1373          %86 = OpExtInst %void %1 DebugValue %50 %82 %84 %int_0
1374                OpNoLine
1375          %92 = OpExtInst %void %1 DebugNoScope
1376          %55 = OpLoad %v4float %in_var_POSITION
1377          %56 = OpLoad %v4float %in_var_COLOR
1378 ;CHECK:   [[pos:%\w+]] = OpLoad %v4float %in_var_POSITION
1379 ;CHECK: [[color:%\w+]] = OpLoad %v4float %in_var_COLOR
1380 
1381          %94 = OpExtInst %void %1 DebugScope %49
1382                OpLine %7 9 3
1383                OpStore %82 %55
1384 ;CHECK: OpLine [[file:%\w+]] 9 3
1385 ;CHECK: OpStore {{%\w+}} [[pos]]
1386 ;CHECK: {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[vout:%\w+]] [[pos]] [[empty_expr:%\w+]] %int_0
1387 ;CHECK: OpLine [[file]] 10 3
1388 ;CHECK: OpStore {{%\w+}} [[color]]
1389 ;CHECK: {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[vout]] [[color]] [[empty_expr]] %int_1
1390 
1391                OpLine %7 10 3
1392                OpStore %83 %56
1393                OpLine %7 11 10
1394          %90 = OpCompositeConstruct %VS_OUTPUT %55 %56
1395                OpNoLine
1396          %95 = OpExtInst %void %1 DebugNoScope
1397          %58 = OpCompositeExtract %v4float %90 0
1398                OpStore %gl_Position %58
1399          %59 = OpCompositeExtract %v4float %90 1
1400                OpStore %out_var_COLOR %59
1401                OpReturn
1402                OpFunctionEnd
1403   )";
1404 
1405   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1406   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1407 }
1408 
TEST_F(LocalSingleStoreElimTest, AddDebugValueforStoreOutOfDebugDeclareScope)1409 TEST_F(LocalSingleStoreElimTest, AddDebugValueforStoreOutOfDebugDeclareScope) {
1410   const std::string text = R"(
1411                OpCapability Shader
1412           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1413                OpMemoryModel Logical GLSL450
1414                OpEntryPoint Vertex %main "main" %in_var_POSITION %in_var_COLOR %gl_Position %out_var_COLOR
1415           %7 = OpString "simple.hlsl"
1416           %8 = OpString "float"
1417           %9 = OpString "VS_OUTPUT"
1418          %10 = OpString "color"
1419          %11 = OpString "pos"
1420          %12 = OpString "main"
1421          %13 = OpString ""
1422          %14 = OpString "vout"
1423                OpName %in_var_POSITION "in.var.POSITION"
1424                OpName %in_var_COLOR "in.var.COLOR"
1425                OpName %out_var_COLOR "out.var.COLOR"
1426                OpName %main "main"
1427                OpName %VS_OUTPUT "VS_OUTPUT"
1428                OpMemberName %VS_OUTPUT 0 "pos"
1429                OpMemberName %VS_OUTPUT 1 "color"
1430                OpDecorate %gl_Position BuiltIn Position
1431                OpDecorate %in_var_POSITION Location 0
1432                OpDecorate %in_var_COLOR Location 1
1433                OpDecorate %out_var_COLOR Location 0
1434         %int = OpTypeInt 32 1
1435       %int_0 = OpConstant %int 0
1436       %int_1 = OpConstant %int 1
1437        %uint = OpTypeInt 32 0
1438     %uint_32 = OpConstant %uint 32
1439       %float = OpTypeFloat 32
1440     %v4float = OpTypeVector %float 4
1441 %_ptr_Input_v4float = OpTypePointer Input %v4float
1442 %_ptr_Output_v4float = OpTypePointer Output %v4float
1443        %void = OpTypeVoid
1444    %uint_256 = OpConstant %uint 256
1445    %uint_128 = OpConstant %uint 128
1446      %uint_0 = OpConstant %uint 0
1447          %36 = OpTypeFunction %void
1448 %_ptr_Function_v4float = OpTypePointer Function %v4float
1449   %VS_OUTPUT = OpTypeStruct %v4float %v4float
1450 %_ptr_Function_VS_OUTPUT = OpTypePointer Function %VS_OUTPUT
1451 %in_var_POSITION = OpVariable %_ptr_Input_v4float Input
1452 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
1453 %gl_Position = OpVariable %_ptr_Output_v4float Output
1454 %out_var_COLOR = OpVariable %_ptr_Output_v4float Output
1455          %85 = OpExtInst %void %1 DebugOperation Deref
1456          %81 = OpExtInst %void %1 DebugInfoNone
1457          %52 = OpExtInst %void %1 DebugExpression
1458          %40 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
1459          %41 = OpExtInst %void %1 DebugTypeVector %40 4
1460          %42 = OpExtInst %void %1 DebugSource %7
1461          %43 = OpExtInst %void %1 DebugCompilationUnit 1 4 %42 HLSL
1462          %44 = OpExtInst %void %1 DebugTypeComposite %9 Structure %42 1 8 %43 %9 %uint_256 FlagIsProtected|FlagIsPrivate %45 %46
1463          %46 = OpExtInst %void %1 DebugTypeMember %10 %41 %42 3 10 %44 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
1464          %45 = OpExtInst %void %1 DebugTypeMember %11 %41 %42 2 10 %44 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1465          %47 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %44 %41 %41
1466          %48 = OpExtInst %void %1 DebugFunction %12 %47 %42 6 1 %43 %13 FlagIsProtected|FlagIsPrivate 7 %81
1467          %49 = OpExtInst %void %1 DebugLexicalBlock %42 7 38 %48
1468          %50 = OpExtInst %void %1 DebugLocalVariable %14 %44 %42 8 13 %49 FlagIsLocal
1469          %51 = OpExtInst %void %1 DebugLocalVariable %10 %41 %42 7 23 %48 FlagIsLocal 2
1470          %53 = OpExtInst %void %1 DebugLocalVariable %11 %41 %42 6 23 %48 FlagIsLocal 1
1471 ;CHECK: [[dbg_color:%\w+]] = OpExtInst %void {{%\w+}} DebugLocalVariable {{%\w+}} {{%\w+}} {{%\w+}} 7 23 {{%\w+}} FlagIsLocal 2
1472 ;CHECK: [[dbg_pos:%\w+]] = OpExtInst %void {{%\w+}} DebugLocalVariable {{%\w+}} {{%\w+}} {{%\w+}} 6 23 {{%\w+}} FlagIsLocal 1
1473 
1474          %84 = OpExtInst %void %1 DebugExpression %85
1475        %main = OpFunction %void None %36
1476          %54 = OpLabel
1477          %91 = OpExtInst %void %1 DebugScope %49
1478                OpLine %7 7 23
1479          %83 = OpVariable %_ptr_Function_v4float Function
1480                OpLine %7 8 13
1481          %87 = OpExtInst %void %1 DebugValue %50 %83 %84 %int_1
1482                OpLine %7 7 23
1483          %82 = OpVariable %_ptr_Function_v4float Function
1484                OpLine %7 8 13
1485          %86 = OpExtInst %void %1 DebugValue %50 %82 %84 %int_0
1486                OpNoLine
1487          %92 = OpExtInst %void %1 DebugNoScope
1488 %param_var_pos = OpVariable %_ptr_Function_v4float Function
1489 %param_var_color = OpVariable %_ptr_Function_v4float Function
1490          %55 = OpLoad %v4float %in_var_POSITION
1491                OpLine %7 6 23
1492                OpStore %param_var_pos %55
1493                OpNoLine
1494          %56 = OpLoad %v4float %in_var_COLOR
1495 ;CHECK:      DebugNoScope
1496 ;CHECK-NOT:  OpLine
1497                OpLine %7 7 23
1498                OpStore %param_var_color %56
1499                OpNoLine
1500          %93 = OpExtInst %void %1 DebugScope %48
1501          %73 = OpExtInst %void %1 DebugDeclare %53 %param_var_pos %52
1502          %74 = OpExtInst %void %1 DebugDeclare %51 %param_var_color %52
1503 ;CHECK:      [[pos:%\w+]] = OpLoad %v4float %in_var_POSITION
1504 ;CHECK:      OpLine [[file:%\w+]] 6 23
1505 ;CHECK:      {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_pos]] [[pos]] [[empty_expr:%\w+]]
1506 ;CHECK:      [[color:%\w+]] = OpLoad %v4float %in_var_COLOR
1507 ;CHECK:      OpLine [[file]] 7 23
1508 ;CHECK:      {{%\w+}} = OpExtInst %void {{%\w+}} DebugValue [[dbg_color]] [[color]] [[empty_expr]]
1509 ;CHECK:      OpLine [[file]] 9 3
1510 
1511          %94 = OpExtInst %void %1 DebugScope %49
1512                OpLine %7 9 3
1513                OpStore %82 %55
1514                OpLine %7 10 3
1515                OpStore %83 %56
1516                OpLine %7 11 10
1517          %90 = OpCompositeConstruct %VS_OUTPUT %55 %56
1518                OpNoLine
1519          %95 = OpExtInst %void %1 DebugNoScope
1520          %58 = OpCompositeExtract %v4float %90 0
1521                OpStore %gl_Position %58
1522          %59 = OpCompositeExtract %v4float %90 1
1523                OpStore %out_var_COLOR %59
1524                OpReturn
1525                OpFunctionEnd
1526   )";
1527 
1528   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1529   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1530 }
1531 
TEST_F(LocalSingleStoreElimTest, DebugValuesForAllLocalsAndParams)1532 TEST_F(LocalSingleStoreElimTest, DebugValuesForAllLocalsAndParams) {
1533   // Texture2D g_tColor;
1534   //
1535   // SamplerState g_sAniso;
1536   //
1537   // struct PS_INPUT
1538   // {
1539   //     float2 vTextureCoords : TEXCOORD2 ;
1540   // } ;
1541   //
1542   // struct PS_OUTPUT
1543   // {
1544   //     float4 vColor : SV_Target0 ;
1545   // } ;
1546   //
1547   // void do_sample ( in float2 tc, out float4 c ) {
1548   //     c = g_tColor . Sample ( g_sAniso , tc ) ;
1549   // }
1550   //
1551   // PS_OUTPUT MainPs ( PS_INPUT i )
1552   // {
1553   //     PS_OUTPUT ps_output ;
1554   //     float4 color;
1555   //
1556   //     do_sample ( i . vTextureCoords . xy , color ) ;
1557   //     ps_output . vColor = color;
1558   //     return ps_output ;
1559   // }
1560   const std::string text = R"(
1561                OpCapability Shader
1562           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1563 ;CHECK:      [[set:%\w+]] = OpExtInstImport "OpenCL.DebugInfo.100"
1564                OpMemoryModel Logical GLSL450
1565                OpEntryPoint Fragment %MainPs "MainPs" %in_var_TEXCOORD2 %out_var_SV_Target0 %g_tColor %g_sAniso
1566                OpExecutionMode %MainPs OriginUpperLeft
1567           %7 = OpString "foo2.frag"
1568          %21 = OpString "float"
1569          %27 = OpString "PS_INPUT"
1570          %31 = OpString "vTextureCoords"
1571          %34 = OpString "PS_OUTPUT"
1572          %38 = OpString "vColor"
1573          %40 = OpString "do_sample"
1574          %41 = OpString ""
1575          %45 = OpString "c"
1576          %47 = OpString "tc"
1577          %50 = OpString "MainPs"
1578          %54 = OpString "color"
1579          %56 = OpString "ps_output"
1580          %59 = OpString "i"
1581          %62 = OpString "@type.sampler"
1582          %63 = OpString "type.sampler"
1583          %65 = OpString "g_sAniso"
1584          %67 = OpString "@type.2d.image"
1585          %68 = OpString "type.2d.image"
1586          %70 = OpString "TemplateParam"
1587          %73 = OpString "g_tColor"
1588 ;CHECK:      [[str_c:%\w+]] = OpString "c"
1589 ;CHECK:      [[str_tc:%\w+]] = OpString "tc"
1590 ;CHECK:      [[str_color:%\w+]] = OpString "color"
1591 ;CHECK:      [[str_ps_output:%\w+]] = OpString "ps_output"
1592 ;CHECK:      [[str_i:%\w+]] = OpString "i"
1593                OpName %type_2d_image "type.2d.image"
1594                OpName %g_tColor "g_tColor"
1595                OpName %type_sampler "type.sampler"
1596                OpName %g_sAniso "g_sAniso"
1597                OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
1598                OpName %out_var_SV_Target0 "out.var.SV_Target0"
1599                OpName %MainPs "MainPs"
1600                OpName %PS_INPUT "PS_INPUT"
1601                OpMemberName %PS_INPUT 0 "vTextureCoords"
1602                OpName %PS_OUTPUT "PS_OUTPUT"
1603                OpMemberName %PS_OUTPUT 0 "vColor"
1604                OpName %type_sampled_image "type.sampled.image"
1605                OpDecorate %in_var_TEXCOORD2 Location 0
1606                OpDecorate %out_var_SV_Target0 Location 0
1607                OpDecorate %g_tColor DescriptorSet 0
1608                OpDecorate %g_tColor Binding 0
1609                OpDecorate %g_sAniso DescriptorSet 0
1610                OpDecorate %g_sAniso Binding 1
1611         %int = OpTypeInt 32 1
1612       %int_0 = OpConstant %int 0
1613        %uint = OpTypeInt 32 0
1614     %uint_32 = OpConstant %uint 32
1615       %float = OpTypeFloat 32
1616 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
1617 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
1618 %type_sampler = OpTypeSampler
1619 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
1620     %v2float = OpTypeVector %float 2
1621 %_ptr_Input_v2float = OpTypePointer Input %v2float
1622     %v4float = OpTypeVector %float 4
1623 %_ptr_Output_v4float = OpTypePointer Output %v4float
1624        %void = OpTypeVoid
1625     %uint_64 = OpConstant %uint 64
1626      %uint_0 = OpConstant %uint 0
1627    %uint_128 = OpConstant %uint 128
1628          %75 = OpTypeFunction %void
1629    %PS_INPUT = OpTypeStruct %v2float
1630 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1631   %PS_OUTPUT = OpTypeStruct %v4float
1632          %85 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1633 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1634 %_ptr_Function_v4float = OpTypePointer Function %v4float
1635 %_ptr_Function_v2float = OpTypePointer Function %v2float
1636         %105 = OpTypeFunction %void %_ptr_Function_v2float %_ptr_Function_v4float
1637 %type_sampled_image = OpTypeSampledImage %type_2d_image
1638    %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
1639    %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
1640 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
1641 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
1642         %145 = OpExtInst %void %1 DebugOperation Deref
1643          %61 = OpExtInst %void %1 DebugInfoNone
1644          %58 = OpExtInst %void %1 DebugExpression
1645          %23 = OpExtInst %void %1 DebugTypeBasic %21 %uint_32 Float
1646          %24 = OpExtInst %void %1 DebugTypeVector %23 2
1647          %25 = OpExtInst %void %1 DebugSource %7
1648          %26 = OpExtInst %void %1 DebugCompilationUnit 1 4 %25 HLSL
1649          %29 = OpExtInst %void %1 DebugTypeComposite %27 Structure %25 5 8 %26 %27 %uint_64 FlagIsProtected|FlagIsPrivate %30
1650          %30 = OpExtInst %void %1 DebugTypeMember %31 %24 %25 7 12 %29 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
1651          %33 = OpExtInst %void %1 DebugTypeVector %23 4
1652          %36 = OpExtInst %void %1 DebugTypeComposite %34 Structure %25 10 8 %26 %34 %uint_128 FlagIsProtected|FlagIsPrivate %37
1653          %37 = OpExtInst %void %1 DebugTypeMember %38 %33 %25 12 12 %36 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1654          %39 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %void %24 %33
1655          %42 = OpExtInst %void %1 DebugFunction %40 %39 %25 15 1 %26 %41 FlagIsProtected|FlagIsPrivate 15 %61
1656          %44 = OpExtInst %void %1 DebugLexicalBlock %25 15 47 %42
1657          %46 = OpExtInst %void %1 DebugLocalVariable %45 %33 %25 15 43 %42 FlagIsLocal 2
1658          %48 = OpExtInst %void %1 DebugLocalVariable %47 %24 %25 15 28 %42 FlagIsLocal 1
1659          %49 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %29
1660          %51 = OpExtInst %void %1 DebugFunction %50 %49 %25 19 1 %26 %41 FlagIsProtected|FlagIsPrivate 20 %61
1661          %53 = OpExtInst %void %1 DebugLexicalBlock %25 20 1 %51
1662          %55 = OpExtInst %void %1 DebugLocalVariable %54 %33 %25 22 12 %53 FlagIsLocal
1663          %57 = OpExtInst %void %1 DebugLocalVariable %56 %36 %25 21 15 %53 FlagIsLocal
1664          %60 = OpExtInst %void %1 DebugLocalVariable %59 %29 %25 19 29 %51 FlagIsLocal 1
1665          %64 = OpExtInst %void %1 DebugTypeComposite %62 Structure %25 0 0 %26 %63 %61 FlagIsProtected|FlagIsPrivate
1666          %66 = OpExtInst %void %1 DebugGlobalVariable %65 %64 %25 3 14 %26 %65 %g_sAniso FlagIsDefinition
1667          %69 = OpExtInst %void %1 DebugTypeComposite %67 Class %25 0 0 %26 %68 %61 FlagIsProtected|FlagIsPrivate
1668          %71 = OpExtInst %void %1 DebugTypeTemplateParameter %70 %33 %61 %25 0 0
1669          %72 = OpExtInst %void %1 DebugTypeTemplate %69 %71
1670          %74 = OpExtInst %void %1 DebugGlobalVariable %73 %72 %25 1 11 %26 %73 %g_tColor FlagIsDefinition
1671         %142 = OpExtInst %void %1 DebugInlinedAt 24 %53
1672         %144 = OpExtInst %void %1 DebugExpression %145
1673         %155 = OpExtInst %void %1 DebugExpression %145
1674 ;CHECK:      [[var_c:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_c]]
1675 ;CHECK:      [[var_tc:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_tc]]
1676 ;CHECK:      [[var_color:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_color]]
1677 ;CHECK:      [[var_ps_output:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_ps_output]]
1678 ;CHECK:      [[var_i:%\w+]] = OpExtInst %void [[set]] DebugLocalVariable [[str_i]]
1679      %MainPs = OpFunction %void None %75
1680          %76 = OpLabel
1681         %153 = OpVariable %_ptr_Function_v2float Function
1682         %149 = OpVariable %_ptr_Function_v4float Function
1683         %157 = OpExtInst %void %1 DebugScope %53
1684         %143 = OpVariable %_ptr_Function_v4float Function
1685         %121 = OpVariable %_ptr_Function_v4float Function
1686         %122 = OpVariable %_ptr_Function_v2float Function
1687         %158 = OpExtInst %void %1 DebugScope %51
1688                OpLine %7 19 29
1689         %156 = OpExtInst %void %1 DebugValue %60 %153 %155 %int_0
1690         %159 = OpExtInst %void %1 DebugScope %53
1691                OpLine %7 21 15
1692         %146 = OpExtInst %void %1 DebugValue %57 %143 %144 %int_0
1693                OpNoLine
1694         %160 = OpExtInst %void %1 DebugNoScope
1695          %80 = OpLoad %v2float %in_var_TEXCOORD2
1696          %81 = OpCompositeConstruct %PS_INPUT %80
1697         %154 = OpCompositeExtract %v2float %81 0
1698                OpStore %153 %154
1699         %161 = OpExtInst %void %1 DebugScope %53
1700                OpLine %7 22 12
1701         %127 = OpExtInst %void %1 DebugDeclare %55 %121 %58
1702                OpLine %7 24 17
1703         %129 = OpLoad %v2float %153
1704                OpStore %122 %129
1705         %162 = OpExtInst %void %1 DebugScope %42 %142
1706                OpLine %7 15 28
1707         %135 = OpExtInst %void %1 DebugDeclare %48 %122 %58
1708                OpLine %7 15 43
1709         %136 = OpExtInst %void %1 DebugDeclare %46 %121 %58
1710         %163 = OpExtInst %void %1 DebugScope %44 %142
1711                OpLine %7 16 9
1712         %137 = OpLoad %type_2d_image %g_tColor
1713                OpLine %7 16 29
1714         %138 = OpLoad %type_sampler %g_sAniso
1715                OpLine %7 16 40
1716         %139 = OpLoad %v2float %122
1717                OpLine %7 16 9
1718         %140 = OpSampledImage %type_sampled_image %137 %138
1719         %141 = OpImageSampleImplicitLod %v4float %140 %139 None
1720                OpLine %7 16 5
1721                OpStore %121 %141
1722         %164 = OpExtInst %void %1 DebugScope %53
1723                OpLine %7 25 26
1724         %131 = OpLoad %v4float %121
1725                OpLine %7 25 5
1726                OpStore %143 %131
1727                OpLine %7 26 12
1728         %147 = OpLoad %v4float %143
1729         %148 = OpCompositeConstruct %PS_OUTPUT %147
1730                OpLine %7 26 5
1731         %150 = OpCompositeExtract %v4float %148 0
1732                OpStore %149 %150
1733                OpNoLine
1734         %165 = OpExtInst %void %1 DebugNoScope
1735         %151 = OpLoad %v4float %149
1736         %152 = OpCompositeConstruct %PS_OUTPUT %151
1737          %84 = OpCompositeExtract %v4float %152 0
1738                OpStore %out_var_SV_Target0 %84
1739                OpLine %7 27 1
1740                OpReturn
1741                OpFunctionEnd
1742 ;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_i]]
1743 ;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_tc]]
1744 ;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_c]]
1745 ;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_color]]
1746 ;CHECK:      {{%\w+}} = OpExtInst %void [[set]] DebugValue [[var_ps_output]]
1747   )";
1748 
1749   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1750   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1751 }
1752 
TEST_F(LocalSingleStoreElimTest, VkMemoryModelTest)1753 TEST_F(LocalSingleStoreElimTest, VkMemoryModelTest) {
1754   const std::string text =
1755       R"(
1756 ; CHECK: OpCapability Shader
1757 ; CHECK: OpCapability VulkanMemoryModel
1758 ; CHECK: OpExtension "SPV_KHR_vulkan_memory_model"
1759                OpCapability Shader
1760                OpCapability VulkanMemoryModel
1761                OpExtension "SPV_KHR_vulkan_memory_model"
1762           %1 = OpExtInstImport "GLSL.std.450"
1763                OpMemoryModel Logical Vulkan
1764                OpEntryPoint GLCompute %main "main"
1765                OpExecutionMode %main LocalSize 1 1 1
1766                OpSource GLSL 450
1767        %void = OpTypeVoid
1768           %3 = OpTypeFunction %void
1769         %int = OpTypeInt 32 1
1770 %_ptr_Function_int = OpTypePointer Function %int
1771       %int_0 = OpConstant %int 0
1772       %int_1 = OpConstant %int 1
1773        %bool = OpTypeBool
1774       %false = OpConstantFalse %bool
1775 ; CHECK: OpFunction
1776 ; CHECK-NEXT: OpLabel
1777 ; CHECK-NEXT: [[a:%\w+]] = OpVariable
1778 ; CHECK-NEXT: [[b:%\w+]] = OpVariable
1779 ; CHECK: OpStore [[a]] [[v:%\w+]]
1780 ; CHECK: OpStore [[b]]
1781 ; Make sure the load was removed.
1782 ; CHECK: OpLabel
1783 ; CHECK-NOT: OpLoad %int [[a]]
1784 ; CHECK: OpStore [[b]] [[v]]
1785        %main = OpFunction %void None %3
1786           %5 = OpLabel
1787           %a = OpVariable %_ptr_Function_int Function
1788           %b = OpVariable %_ptr_Function_int Function
1789                OpStore %a %int_0
1790                OpStore %b %int_1
1791                OpSelectionMerge %15 None
1792                OpBranchConditional %false %14 %15
1793          %14 = OpLabel
1794          %16 = OpLoad %int %a
1795                OpStore %b %16
1796                OpBranch %15
1797          %15 = OpLabel
1798                OpReturn
1799                OpFunctionEnd
1800 )";
1801 
1802   SinglePassRunAndMatch<LocalSingleStoreElimPass>(text, false);
1803 }
1804 
1805 // TODO(greg-lunarg): Add tests to verify handling of these cases:
1806 //
1807 //    Other types
1808 //    Others?
1809 
1810 }  // namespace
1811 }  // namespace opt
1812 }  // namespace spvtools
1813