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