• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 LocalSingleBlockLoadStoreElimTest = PassTest<::testing::Test>;
26 
TEST_F(LocalSingleBlockLoadStoreElimTest,SimpleStoreLoadElim)27 TEST_F(LocalSingleBlockLoadStoreElimTest, SimpleStoreLoadElim) {
28   // #version 140
29   //
30   // in vec4 BaseColor;
31   //
32   // void main()
33   // {
34   //     vec4 v = BaseColor;
35   //     gl_FragColor = v;
36   // }
37 
38   const std::string predefs_before =
39       R"(OpCapability Shader
40 %1 = OpExtInstImport "GLSL.std.450"
41 OpMemoryModel Logical GLSL450
42 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
43 OpExecutionMode %main OriginUpperLeft
44 OpSource GLSL 140
45 OpName %main "main"
46 OpName %v "v"
47 OpName %BaseColor "BaseColor"
48 OpName %gl_FragColor "gl_FragColor"
49 %void = OpTypeVoid
50 %7 = OpTypeFunction %void
51 %float = OpTypeFloat 32
52 %v4float = OpTypeVector %float 4
53 %_ptr_Function_v4float = OpTypePointer Function %v4float
54 %_ptr_Input_v4float = OpTypePointer Input %v4float
55 %BaseColor = OpVariable %_ptr_Input_v4float Input
56 %_ptr_Output_v4float = OpTypePointer Output %v4float
57 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
58 )";
59 
60   const std::string before =
61       R"(%main = OpFunction %void None %7
62 %13 = OpLabel
63 %v = OpVariable %_ptr_Function_v4float Function
64 %14 = OpLoad %v4float %BaseColor
65 OpStore %v %14
66 %15 = OpLoad %v4float %v
67 OpStore %gl_FragColor %15
68 OpReturn
69 OpFunctionEnd
70 )";
71 
72   const std::string after =
73       R"(%main = OpFunction %void None %7
74 %13 = OpLabel
75 %v = OpVariable %_ptr_Function_v4float Function
76 %14 = OpLoad %v4float %BaseColor
77 OpStore %v %14
78 OpStore %gl_FragColor %14
79 OpReturn
80 OpFunctionEnd
81 )";
82 
83   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
84       predefs_before + before, predefs_before + after, true, true);
85 }
86 
TEST_F(LocalSingleBlockLoadStoreElimTest,SimpleLoadLoadElim)87 TEST_F(LocalSingleBlockLoadStoreElimTest, SimpleLoadLoadElim) {
88   // #version 140
89   //
90   // in vec4 BaseColor;
91   // in float fi;
92   //
93   // void main()
94   // {
95   //     vec4 v = BaseColor;
96   //     if (fi < 0)
97   //         v = vec4(0.0);
98   //     gl_FragData[0] = v;
99   //     gl_FragData[1] = v;
100   // }
101 
102   const std::string predefs =
103       R"(OpCapability Shader
104 %1 = OpExtInstImport "GLSL.std.450"
105 OpMemoryModel Logical GLSL450
106 OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragData
107 OpExecutionMode %main OriginUpperLeft
108 OpSource GLSL 140
109 OpName %main "main"
110 OpName %v "v"
111 OpName %BaseColor "BaseColor"
112 OpName %fi "fi"
113 OpName %gl_FragData "gl_FragData"
114 %void = OpTypeVoid
115 %8 = OpTypeFunction %void
116 %float = OpTypeFloat 32
117 %v4float = OpTypeVector %float 4
118 %_ptr_Function_v4float = OpTypePointer Function %v4float
119 %_ptr_Input_v4float = OpTypePointer Input %v4float
120 %BaseColor = OpVariable %_ptr_Input_v4float Input
121 %_ptr_Input_float = OpTypePointer Input %float
122 %fi = OpVariable %_ptr_Input_float Input
123 %float_0 = OpConstant %float 0
124 %bool = OpTypeBool
125 %16 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
126 %uint = OpTypeInt 32 0
127 %uint_32 = OpConstant %uint 32
128 %_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
129 %_ptr_Output__arr_v4float_uint_32 = OpTypePointer Output %_arr_v4float_uint_32
130 %gl_FragData = OpVariable %_ptr_Output__arr_v4float_uint_32 Output
131 %int = OpTypeInt 32 1
132 %int_0 = OpConstant %int 0
133 %_ptr_Output_v4float = OpTypePointer Output %v4float
134 %int_1 = OpConstant %int 1
135 )";
136 
137   const std::string before =
138       R"(%main = OpFunction %void None %8
139 %25 = OpLabel
140 %v = OpVariable %_ptr_Function_v4float Function
141 %26 = OpLoad %v4float %BaseColor
142 OpStore %v %26
143 %27 = OpLoad %float %fi
144 %28 = OpFOrdLessThan %bool %27 %float_0
145 OpSelectionMerge %29 None
146 OpBranchConditional %28 %30 %29
147 %30 = OpLabel
148 OpStore %v %16
149 OpBranch %29
150 %29 = OpLabel
151 %31 = OpLoad %v4float %v
152 %32 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
153 OpStore %32 %31
154 %33 = OpLoad %v4float %v
155 %34 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
156 OpStore %34 %33
157 OpReturn
158 OpFunctionEnd
159 )";
160 
161   const std::string after =
162       R"(%main = OpFunction %void None %8
163 %25 = OpLabel
164 %v = OpVariable %_ptr_Function_v4float Function
165 %26 = OpLoad %v4float %BaseColor
166 OpStore %v %26
167 %27 = OpLoad %float %fi
168 %28 = OpFOrdLessThan %bool %27 %float_0
169 OpSelectionMerge %29 None
170 OpBranchConditional %28 %30 %29
171 %30 = OpLabel
172 OpStore %v %16
173 OpBranch %29
174 %29 = OpLabel
175 %31 = OpLoad %v4float %v
176 %32 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
177 OpStore %32 %31
178 %34 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
179 OpStore %34 %31
180 OpReturn
181 OpFunctionEnd
182 )";
183 
184   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
185       predefs + before, predefs + after, true, true);
186 }
187 
TEST_F(LocalSingleBlockLoadStoreElimTest,StoreStoreElim)188 TEST_F(LocalSingleBlockLoadStoreElimTest, StoreStoreElim) {
189   //
190   // Note first store to v is eliminated
191   //
192   // #version 450
193   //
194   // layout(location = 0) in vec4 BaseColor;
195   // layout(location = 0) out vec4 OutColor;
196   //
197   // void main()
198   // {
199   //     vec4 v = BaseColor;
200   //     v = v * 0.5;
201   //     OutColor = v;
202   // }
203 
204   const std::string predefs_before =
205       R"(OpCapability Shader
206 %1 = OpExtInstImport "GLSL.std.450"
207 OpMemoryModel Logical GLSL450
208 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
209 OpExecutionMode %main OriginUpperLeft
210 OpSource GLSL 450
211 OpName %main "main"
212 OpName %v "v"
213 OpName %BaseColor "BaseColor"
214 OpName %OutColor "OutColor"
215 OpDecorate %BaseColor Location 0
216 OpDecorate %OutColor Location 0
217 %void = OpTypeVoid
218 %7 = OpTypeFunction %void
219 %float = OpTypeFloat 32
220 %v4float = OpTypeVector %float 4
221 %_ptr_Function_v4float = OpTypePointer Function %v4float
222 %_ptr_Input_v4float = OpTypePointer Input %v4float
223 %BaseColor = OpVariable %_ptr_Input_v4float Input
224 %float_0_5 = OpConstant %float 0.5
225 %_ptr_Output_v4float = OpTypePointer Output %v4float
226 %OutColor = OpVariable %_ptr_Output_v4float Output
227 )";
228 
229   const std::string before =
230       R"(%main = OpFunction %void None %7
231 %14 = OpLabel
232 %v = OpVariable %_ptr_Function_v4float Function
233 %15 = OpLoad %v4float %BaseColor
234 OpStore %v %15
235 %16 = OpLoad %v4float %v
236 %17 = OpVectorTimesScalar %v4float %16 %float_0_5
237 OpStore %v %17
238 %18 = OpLoad %v4float %v
239 OpStore %OutColor %18
240 OpReturn
241 OpFunctionEnd
242 )";
243 
244   const std::string after =
245       R"(%main = OpFunction %void None %7
246 %14 = OpLabel
247 %v = OpVariable %_ptr_Function_v4float Function
248 %15 = OpLoad %v4float %BaseColor
249 %17 = OpVectorTimesScalar %v4float %15 %float_0_5
250 OpStore %v %17
251 OpStore %OutColor %17
252 OpReturn
253 OpFunctionEnd
254 )";
255 
256   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
257       predefs_before + before, predefs_before + after, true, true);
258 }
259 
TEST_F(LocalSingleBlockLoadStoreElimTest,NoStoreElimIfInterveningAccessChainLoad)260 TEST_F(LocalSingleBlockLoadStoreElimTest,
261        NoStoreElimIfInterveningAccessChainLoad) {
262   //
263   // Note the first Store to %v is not eliminated due to the following access
264   // chain reference.
265   //
266   // #version 450
267   //
268   // layout(location = 0) in vec4 BaseColor0;
269   // layout(location = 1) in vec4 BaseColor1;
270   // layout(location = 2) flat in int Idx;
271   // layout(location = 0) out vec4 OutColor;
272   //
273   // void main()
274   // {
275   //     vec4 v = BaseColor0;
276   //     float f = v[Idx];
277   //     v = BaseColor1 + vec4(0.1);
278   //     OutColor = v/f;
279   // }
280 
281   const std::string predefs =
282       R"(OpCapability Shader
283 %1 = OpExtInstImport "GLSL.std.450"
284 OpMemoryModel Logical GLSL450
285 OpEntryPoint Fragment %main "main" %BaseColor0 %Idx %BaseColor1 %OutColor
286 OpExecutionMode %main OriginUpperLeft
287 OpSource GLSL 450
288 OpName %main "main"
289 OpName %v "v"
290 OpName %BaseColor0 "BaseColor0"
291 OpName %f "f"
292 OpName %Idx "Idx"
293 OpName %BaseColor1 "BaseColor1"
294 OpName %OutColor "OutColor"
295 OpDecorate %BaseColor0 Location 0
296 OpDecorate %Idx Flat
297 OpDecorate %Idx Location 2
298 OpDecorate %BaseColor1 Location 1
299 OpDecorate %OutColor Location 0
300 %void = OpTypeVoid
301 %10 = OpTypeFunction %void
302 %float = OpTypeFloat 32
303 %v4float = OpTypeVector %float 4
304 %_ptr_Function_v4float = OpTypePointer Function %v4float
305 %_ptr_Input_v4float = OpTypePointer Input %v4float
306 %BaseColor0 = OpVariable %_ptr_Input_v4float Input
307 %_ptr_Function_float = OpTypePointer Function %float
308 %int = OpTypeInt 32 1
309 %_ptr_Input_int = OpTypePointer Input %int
310 %Idx = OpVariable %_ptr_Input_int Input
311 %BaseColor1 = OpVariable %_ptr_Input_v4float Input
312 %float_0_100000001 = OpConstant %float 0.100000001
313 %19 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
314 %_ptr_Output_v4float = OpTypePointer Output %v4float
315 %OutColor = OpVariable %_ptr_Output_v4float Output
316 )";
317 
318   const std::string before =
319       R"(%main = OpFunction %void None %10
320 %21 = OpLabel
321 %v = OpVariable %_ptr_Function_v4float Function
322 %f = OpVariable %_ptr_Function_float Function
323 %22 = OpLoad %v4float %BaseColor0
324 OpStore %v %22
325 %23 = OpLoad %int %Idx
326 %24 = OpAccessChain %_ptr_Function_float %v %23
327 %25 = OpLoad %float %24
328 OpStore %f %25
329 %26 = OpLoad %v4float %BaseColor1
330 %27 = OpFAdd %v4float %26 %19
331 OpStore %v %27
332 %28 = OpLoad %v4float %v
333 %29 = OpLoad %float %f
334 %30 = OpCompositeConstruct %v4float %29 %29 %29 %29
335 %31 = OpFDiv %v4float %28 %30
336 OpStore %OutColor %31
337 OpReturn
338 OpFunctionEnd
339 )";
340 
341   const std::string after =
342       R"(%main = OpFunction %void None %10
343 %21 = OpLabel
344 %v = OpVariable %_ptr_Function_v4float Function
345 %f = OpVariable %_ptr_Function_float Function
346 %22 = OpLoad %v4float %BaseColor0
347 OpStore %v %22
348 %23 = OpLoad %int %Idx
349 %24 = OpAccessChain %_ptr_Function_float %v %23
350 %25 = OpLoad %float %24
351 OpStore %f %25
352 %26 = OpLoad %v4float %BaseColor1
353 %27 = OpFAdd %v4float %26 %19
354 OpStore %v %27
355 %30 = OpCompositeConstruct %v4float %25 %25 %25 %25
356 %31 = OpFDiv %v4float %27 %30
357 OpStore %OutColor %31
358 OpReturn
359 OpFunctionEnd
360 )";
361 
362   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
363       predefs + before, predefs + after, true, true);
364 }
365 
TEST_F(LocalSingleBlockLoadStoreElimTest,NoElimIfInterveningAccessChainStore)366 TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningAccessChainStore) {
367   // #version 140
368   //
369   // in vec4 BaseColor;
370   // flat in int Idx;
371   //
372   // void main()
373   // {
374   //     vec4 v = BaseColor;
375   //     v[Idx] = 0;
376   //     gl_FragColor = v;
377   // }
378 
379   const std::string assembly =
380       R"(OpCapability Shader
381 %1 = OpExtInstImport "GLSL.std.450"
382 OpMemoryModel Logical GLSL450
383 OpEntryPoint Fragment %main "main" %BaseColor %Idx %gl_FragColor
384 OpExecutionMode %main OriginUpperLeft
385 OpSource GLSL 140
386 OpName %main "main"
387 OpName %v "v"
388 OpName %BaseColor "BaseColor"
389 OpName %Idx "Idx"
390 OpName %gl_FragColor "gl_FragColor"
391 OpDecorate %Idx Flat
392 %void = OpTypeVoid
393 %8 = OpTypeFunction %void
394 %float = OpTypeFloat 32
395 %v4float = OpTypeVector %float 4
396 %_ptr_Function_v4float = OpTypePointer Function %v4float
397 %_ptr_Input_v4float = OpTypePointer Input %v4float
398 %BaseColor = OpVariable %_ptr_Input_v4float Input
399 %int = OpTypeInt 32 1
400 %_ptr_Input_int = OpTypePointer Input %int
401 %Idx = OpVariable %_ptr_Input_int Input
402 %float_0 = OpConstant %float 0
403 %_ptr_Function_float = OpTypePointer Function %float
404 %_ptr_Output_v4float = OpTypePointer Output %v4float
405 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
406 %main = OpFunction %void None %8
407 %18 = OpLabel
408 %v = OpVariable %_ptr_Function_v4float Function
409 %19 = OpLoad %v4float %BaseColor
410 OpStore %v %19
411 %20 = OpLoad %int %Idx
412 %21 = OpAccessChain %_ptr_Function_float %v %20
413 OpStore %21 %float_0
414 %22 = OpLoad %v4float %v
415 OpStore %gl_FragColor %22
416 OpReturn
417 OpFunctionEnd
418 )";
419 
420   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(assembly, assembly,
421                                                            false, true);
422 }
423 
TEST_F(LocalSingleBlockLoadStoreElimTest,NoElimIfInterveningFunctionCall)424 TEST_F(LocalSingleBlockLoadStoreElimTest, NoElimIfInterveningFunctionCall) {
425   // #version 140
426   //
427   // in vec4 BaseColor;
428   //
429   // void foo() {
430   // }
431   //
432   // void main()
433   // {
434   //     vec4 v = BaseColor;
435   //     foo();
436   //     gl_FragColor = v;
437   // }
438 
439   const std::string assembly =
440       R"(OpCapability Shader
441 %1 = OpExtInstImport "GLSL.std.450"
442 OpMemoryModel Logical GLSL450
443 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
444 OpExecutionMode %main OriginUpperLeft
445 OpSource GLSL 140
446 OpName %main "main"
447 OpName %foo_ "foo("
448 OpName %v "v"
449 OpName %BaseColor "BaseColor"
450 OpName %gl_FragColor "gl_FragColor"
451 %void = OpTypeVoid
452 %8 = OpTypeFunction %void
453 %float = OpTypeFloat 32
454 %v4float = OpTypeVector %float 4
455 %_ptr_Function_v4float = OpTypePointer Function %v4float
456 %_ptr_Input_v4float = OpTypePointer Input %v4float
457 %BaseColor = OpVariable %_ptr_Input_v4float Input
458 %_ptr_Output_v4float = OpTypePointer Output %v4float
459 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
460 %main = OpFunction %void None %8
461 %14 = OpLabel
462 %v = OpVariable %_ptr_Function_v4float Function
463 %15 = OpLoad %v4float %BaseColor
464 OpStore %v %15
465 %16 = OpFunctionCall %void %foo_
466 %17 = OpLoad %v4float %v
467 OpStore %gl_FragColor %17
468 OpReturn
469 OpFunctionEnd
470 %foo_ = OpFunction %void None %8
471 %18 = OpLabel
472 OpReturn
473 OpFunctionEnd
474 )";
475 
476   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(assembly, assembly,
477                                                            false, true);
478 }
479 
TEST_F(LocalSingleBlockLoadStoreElimTest,ElimIfCopyObjectInFunction)480 TEST_F(LocalSingleBlockLoadStoreElimTest, ElimIfCopyObjectInFunction) {
481   // Note: SPIR-V hand edited to insert CopyObject
482   //
483   // #version 140
484   //
485   // in vec4 BaseColor;
486   //
487   // void main()
488   // {
489   //   vec4 v1 = BaseColor;
490   //   gl_FragData[0] = v1;
491   //   vec4 v2 = BaseColor * 0.5;
492   //   gl_FragData[1] = v2;
493   // }
494 
495   const std::string predefs =
496       R"(OpCapability Shader
497 %1 = OpExtInstImport "GLSL.std.450"
498 OpMemoryModel Logical GLSL450
499 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragData
500 OpExecutionMode %main OriginUpperLeft
501 OpSource GLSL 140
502 OpName %main "main"
503 OpName %v1 "v1"
504 OpName %BaseColor "BaseColor"
505 OpName %gl_FragData "gl_FragData"
506 OpName %v2 "v2"
507 %void = OpTypeVoid
508 %8 = OpTypeFunction %void
509 %float = OpTypeFloat 32
510 %v4float = OpTypeVector %float 4
511 %_ptr_Function_v4float = OpTypePointer Function %v4float
512 %_ptr_Input_v4float = OpTypePointer Input %v4float
513 %BaseColor = OpVariable %_ptr_Input_v4float Input
514 %uint = OpTypeInt 32 0
515 %uint_32 = OpConstant %uint 32
516 %_arr_v4float_uint_32 = OpTypeArray %v4float %uint_32
517 %_ptr_Output__arr_v4float_uint_32 = OpTypePointer Output %_arr_v4float_uint_32
518 %gl_FragData = OpVariable %_ptr_Output__arr_v4float_uint_32 Output
519 %int = OpTypeInt 32 1
520 %int_0 = OpConstant %int 0
521 %_ptr_Output_v4float = OpTypePointer Output %v4float
522 %float_0_5 = OpConstant %float 0.5
523 %int_1 = OpConstant %int 1
524 )";
525 
526   const std::string before =
527       R"(%main = OpFunction %void None %8
528 %22 = OpLabel
529 %v1 = OpVariable %_ptr_Function_v4float Function
530 %v2 = OpVariable %_ptr_Function_v4float Function
531 %23 = OpLoad %v4float %BaseColor
532 OpStore %v1 %23
533 %24 = OpLoad %v4float %v1
534 %25 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
535 OpStore %25 %24
536 %26 = OpLoad %v4float %BaseColor
537 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
538 %28 = OpCopyObject %_ptr_Function_v4float %v2
539 OpStore %28 %27
540 %29 = OpLoad %v4float %28
541 %30 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
542 OpStore %30 %29
543 OpReturn
544 OpFunctionEnd
545 )";
546 
547   const std::string after =
548       R"(%main = OpFunction %void None %8
549 %22 = OpLabel
550 %v1 = OpVariable %_ptr_Function_v4float Function
551 %v2 = OpVariable %_ptr_Function_v4float Function
552 %23 = OpLoad %v4float %BaseColor
553 OpStore %v1 %23
554 %25 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_0
555 OpStore %25 %23
556 %26 = OpLoad %v4float %BaseColor
557 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
558 %28 = OpCopyObject %_ptr_Function_v4float %v2
559 OpStore %28 %27
560 %30 = OpAccessChain %_ptr_Output_v4float %gl_FragData %int_1
561 OpStore %30 %27
562 OpReturn
563 OpFunctionEnd
564 )";
565 
566   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
567       predefs + before, predefs + after, true, true);
568 }
569 
TEST_F(LocalSingleBlockLoadStoreElimTest,ElimOpaque)570 TEST_F(LocalSingleBlockLoadStoreElimTest, ElimOpaque) {
571   // SPIR-V not representable in GLSL; not generatable from HLSL
572   // at the moment
573 
574   const std::string predefs =
575       R"(OpCapability Shader
576 %1 = OpExtInstImport "GLSL.std.450"
577 OpMemoryModel Logical GLSL450
578 OpEntryPoint Fragment %main "main" %outColor %texCoords
579 OpExecutionMode %main OriginUpperLeft
580 OpSource GLSL 140
581 OpName %main "main"
582 OpName %S_t "S_t"
583 OpMemberName %S_t 0 "v0"
584 OpMemberName %S_t 1 "v1"
585 OpMemberName %S_t 2 "smp"
586 OpName %outColor "outColor"
587 OpName %sampler15 "sampler15"
588 OpName %s0 "s0"
589 OpName %texCoords "texCoords"
590 OpName %param "param"
591 OpDecorate %sampler15 DescriptorSet 0
592 %void = OpTypeVoid
593 %12 = OpTypeFunction %void
594 %float = OpTypeFloat 32
595 %v2float = OpTypeVector %float 2
596 %v4float = OpTypeVector %float 4
597 %_ptr_Output_v4float = OpTypePointer Output %v4float
598 %outColor = OpVariable %_ptr_Output_v4float Output
599 %17 = OpTypeImage %float 2D 0 0 0 1 Unknown
600 %18 = OpTypeSampledImage %17
601 %S_t = OpTypeStruct %v2float %v2float %18
602 %_ptr_Function_S_t = OpTypePointer Function %S_t
603 %20 = OpTypeFunction %void %_ptr_Function_S_t
604 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
605 %_ptr_Function_18 = OpTypePointer Function %18
606 %sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant
607 %int = OpTypeInt 32 1
608 %int_0 = OpConstant %int 0
609 %int_2 = OpConstant %int 2
610 %_ptr_Function_v2float = OpTypePointer Function %v2float
611 %_ptr_Input_v2float = OpTypePointer Input %v2float
612 %texCoords = OpVariable %_ptr_Input_v2float Input
613 )";
614 
615   const std::string before =
616       R"(%main = OpFunction %void None %12
617 %28 = OpLabel
618 %s0 = OpVariable %_ptr_Function_S_t Function
619 %param = OpVariable %_ptr_Function_S_t Function
620 %29 = OpLoad %v2float %texCoords
621 %30 = OpLoad %S_t %s0
622 %31 = OpCompositeInsert %S_t %29 %30 0
623 OpStore %s0 %31
624 %32 = OpLoad %18 %sampler15
625 %33 = OpLoad %S_t %s0
626 %34 = OpCompositeInsert %S_t %32 %33 2
627 OpStore %s0 %34
628 %35 = OpLoad %S_t %s0
629 OpStore %param %35
630 %36 = OpLoad %S_t %param
631 %37 = OpCompositeExtract %18 %36 2
632 %38 = OpLoad %S_t %param
633 %39 = OpCompositeExtract %v2float %38 0
634 %40 = OpImageSampleImplicitLod %v4float %37 %39
635 OpStore %outColor %40
636 OpReturn
637 OpFunctionEnd
638 )";
639 
640   const std::string after =
641       R"(%main = OpFunction %void None %12
642 %28 = OpLabel
643 %s0 = OpVariable %_ptr_Function_S_t Function
644 %param = OpVariable %_ptr_Function_S_t Function
645 %29 = OpLoad %v2float %texCoords
646 %30 = OpLoad %S_t %s0
647 %31 = OpCompositeInsert %S_t %29 %30 0
648 %32 = OpLoad %18 %sampler15
649 %34 = OpCompositeInsert %S_t %32 %31 2
650 OpStore %s0 %34
651 OpStore %param %34
652 %37 = OpCompositeExtract %18 %34 2
653 %39 = OpCompositeExtract %v2float %34 0
654 %40 = OpImageSampleImplicitLod %v4float %37 %39
655 OpStore %outColor %40
656 OpReturn
657 OpFunctionEnd
658 )";
659 
660   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
661   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
662       predefs + before, predefs + after, true, true);
663 }
664 
TEST_F(LocalSingleBlockLoadStoreElimTest,PositiveAndNegativeCallTree)665 TEST_F(LocalSingleBlockLoadStoreElimTest, PositiveAndNegativeCallTree) {
666   // Note that the call tree function bar is optimized, but foo is not
667   //
668   // #version 140
669   //
670   // in vec4 BaseColor;
671   //
672   // vec4 foo(vec4 v1)
673   // {
674   //     vec4 t = v1;
675   //     return t;
676   // }
677   //
678   // vec4 bar(vec4 v1)
679   // {
680   //     vec4 t = v1;
681   //     return t;
682   // }
683   //
684   // void main()
685   // {
686   //     gl_FragColor = bar(BaseColor);
687   // }
688 
689   const std::string predefs =
690       R"(OpCapability Shader
691 %1 = OpExtInstImport "GLSL.std.450"
692 OpMemoryModel Logical GLSL450
693 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
694 OpExecutionMode %main OriginUpperLeft
695 OpSource GLSL 140
696 OpName %main "main"
697 OpName %foo_vf4_ "foo(vf4;"
698 OpName %v1 "v1"
699 OpName %bar_vf4_ "bar(vf4;"
700 OpName %v1_0 "v1"
701 OpName %t "t"
702 OpName %t_0 "t"
703 OpName %gl_FragColor "gl_FragColor"
704 OpName %BaseColor "BaseColor"
705 OpName %param "param"
706 %void = OpTypeVoid
707 %13 = OpTypeFunction %void
708 %float = OpTypeFloat 32
709 %v4float = OpTypeVector %float 4
710 %_ptr_Function_v4float = OpTypePointer Function %v4float
711 %17 = OpTypeFunction %v4float %_ptr_Function_v4float
712 %_ptr_Output_v4float = OpTypePointer Output %v4float
713 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
714 %_ptr_Input_v4float = OpTypePointer Input %v4float
715 %BaseColor = OpVariable %_ptr_Input_v4float Input
716 %main = OpFunction %void None %13
717 %20 = OpLabel
718 %param = OpVariable %_ptr_Function_v4float Function
719 %21 = OpLoad %v4float %BaseColor
720 OpStore %param %21
721 %22 = OpFunctionCall %v4float %bar_vf4_ %param
722 OpStore %gl_FragColor %22
723 OpReturn
724 OpFunctionEnd
725 )";
726 
727   const std::string before =
728       R"(%foo_vf4_ = OpFunction %v4float None %17
729 %v1 = OpFunctionParameter %_ptr_Function_v4float
730 %23 = OpLabel
731 %t = OpVariable %_ptr_Function_v4float Function
732 %24 = OpLoad %v4float %v1
733 OpStore %t %24
734 %25 = OpLoad %v4float %t
735 OpReturnValue %25
736 OpFunctionEnd
737 %bar_vf4_ = OpFunction %v4float None %17
738 %v1_0 = OpFunctionParameter %_ptr_Function_v4float
739 %26 = OpLabel
740 %t_0 = OpVariable %_ptr_Function_v4float Function
741 %27 = OpLoad %v4float %v1_0
742 OpStore %t_0 %27
743 %28 = OpLoad %v4float %t_0
744 OpReturnValue %28
745 OpFunctionEnd
746 )";
747 
748   const std::string after =
749       R"(%foo_vf4_ = OpFunction %v4float None %17
750 %v1 = OpFunctionParameter %_ptr_Function_v4float
751 %23 = OpLabel
752 %t = OpVariable %_ptr_Function_v4float Function
753 %24 = OpLoad %v4float %v1
754 OpStore %t %24
755 %25 = OpLoad %v4float %t
756 OpReturnValue %25
757 OpFunctionEnd
758 %bar_vf4_ = OpFunction %v4float None %17
759 %v1_0 = OpFunctionParameter %_ptr_Function_v4float
760 %26 = OpLabel
761 %t_0 = OpVariable %_ptr_Function_v4float Function
762 %27 = OpLoad %v4float %v1_0
763 OpStore %t_0 %27
764 OpReturnValue %27
765 OpFunctionEnd
766 )";
767 
768   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
769       predefs + before, predefs + after, true, true);
770 }
771 
TEST_F(LocalSingleBlockLoadStoreElimTest,PointerVariable)772 TEST_F(LocalSingleBlockLoadStoreElimTest, PointerVariable) {
773   // Test that checks if a pointer variable is removed.
774 
775   const std::string before =
776       R"(OpCapability Shader
777 OpMemoryModel Logical GLSL450
778 OpEntryPoint Fragment %1 "main" %2
779 OpExecutionMode %1 OriginUpperLeft
780 OpMemberDecorate %_struct_3 0 Offset 0
781 OpDecorate %_runtimearr__struct_3 ArrayStride 16
782 OpMemberDecorate %_struct_5 0 Offset 0
783 OpDecorate %_struct_5 BufferBlock
784 OpMemberDecorate %_struct_6 0 Offset 0
785 OpDecorate %_struct_6 BufferBlock
786 OpDecorate %2 Location 0
787 OpDecorate %7 DescriptorSet 0
788 OpDecorate %7 Binding 0
789 %void = OpTypeVoid
790 %10 = OpTypeFunction %void
791 %int = OpTypeInt 32 1
792 %uint = OpTypeInt 32 0
793 %float = OpTypeFloat 32
794 %v4float = OpTypeVector %float 4
795 %_ptr_Output_v4float = OpTypePointer Output %v4float
796 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
797 %_struct_3 = OpTypeStruct %v4float
798 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
799 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
800 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
801 %_struct_6 = OpTypeStruct %int
802 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
803 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
804 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
805 %int_0 = OpConstant %int 0
806 %uint_0 = OpConstant %uint 0
807 %2 = OpVariable %_ptr_Output_v4float Output
808 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
809 %1 = OpFunction %void None %10
810 %23 = OpLabel
811 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
812 OpStore %24 %7
813 %26 = OpLoad %_ptr_Uniform__struct_5 %24
814 %27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0
815 %28 = OpLoad %v4float %27
816 %29 = OpCopyObject %v4float %28
817 OpStore %2 %28
818 OpReturn
819 OpFunctionEnd
820 )";
821 
822   const std::string after =
823       R"(OpCapability Shader
824 OpMemoryModel Logical GLSL450
825 OpEntryPoint Fragment %1 "main" %2
826 OpExecutionMode %1 OriginUpperLeft
827 OpMemberDecorate %_struct_3 0 Offset 0
828 OpDecorate %_runtimearr__struct_3 ArrayStride 16
829 OpMemberDecorate %_struct_5 0 Offset 0
830 OpDecorate %_struct_5 BufferBlock
831 OpMemberDecorate %_struct_6 0 Offset 0
832 OpDecorate %_struct_6 BufferBlock
833 OpDecorate %2 Location 0
834 OpDecorate %7 DescriptorSet 0
835 OpDecorate %7 Binding 0
836 %void = OpTypeVoid
837 %10 = OpTypeFunction %void
838 %int = OpTypeInt 32 1
839 %uint = OpTypeInt 32 0
840 %float = OpTypeFloat 32
841 %v4float = OpTypeVector %float 4
842 %_ptr_Output_v4float = OpTypePointer Output %v4float
843 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
844 %_struct_3 = OpTypeStruct %v4float
845 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
846 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
847 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
848 %_struct_6 = OpTypeStruct %int
849 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
850 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
851 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
852 %int_0 = OpConstant %int 0
853 %uint_0 = OpConstant %uint 0
854 %2 = OpVariable %_ptr_Output_v4float Output
855 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
856 %1 = OpFunction %void None %10
857 %23 = OpLabel
858 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
859 OpStore %24 %7
860 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
861 %28 = OpLoad %v4float %27
862 %29 = OpCopyObject %v4float %28
863 OpStore %2 %28
864 OpReturn
865 OpFunctionEnd
866 )";
867 
868   // Relax logical pointers to allow pointer allocations.
869   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
870   ValidatorOptions()->relax_logical_pointer = true;
871   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(before, after, true,
872                                                            true);
873 }
874 
TEST_F(LocalSingleBlockLoadStoreElimTest,RedundantStore)875 TEST_F(LocalSingleBlockLoadStoreElimTest, RedundantStore) {
876   // Test that checks if a pointer variable is removed.
877   const std::string predefs_before =
878       R"(OpCapability Shader
879 %1 = OpExtInstImport "GLSL.std.450"
880 OpMemoryModel Logical GLSL450
881 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
882 OpExecutionMode %main OriginUpperLeft
883 OpSource GLSL 140
884 OpName %main "main"
885 OpName %v "v"
886 OpName %BaseColor "BaseColor"
887 OpName %gl_FragColor "gl_FragColor"
888 %void = OpTypeVoid
889 %7 = OpTypeFunction %void
890 %float = OpTypeFloat 32
891 %v4float = OpTypeVector %float 4
892 %_ptr_Function_v4float = OpTypePointer Function %v4float
893 %_ptr_Input_v4float = OpTypePointer Input %v4float
894 %BaseColor = OpVariable %_ptr_Input_v4float Input
895 %_ptr_Output_v4float = OpTypePointer Output %v4float
896 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
897 )";
898 
899   const std::string before =
900       R"(%main = OpFunction %void None %7
901 %13 = OpLabel
902 %v = OpVariable %_ptr_Function_v4float Function
903 %14 = OpLoad %v4float %BaseColor
904 OpStore %v %14
905 OpBranch %16
906 %16 = OpLabel
907 %15 = OpLoad %v4float %v
908 OpStore %v %15
909 OpReturn
910 OpFunctionEnd
911 )";
912 
913   const std::string after =
914       R"(%main = OpFunction %void None %7
915 %13 = OpLabel
916 %v = OpVariable %_ptr_Function_v4float Function
917 %14 = OpLoad %v4float %BaseColor
918 OpStore %v %14
919 OpBranch %16
920 %16 = OpLabel
921 %15 = OpLoad %v4float %v
922 OpReturn
923 OpFunctionEnd
924 )";
925 
926   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
927   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
928       predefs_before + before, predefs_before + after, true, true);
929 }
930 
TEST_F(LocalSingleBlockLoadStoreElimTest,RedundantStore2)931 TEST_F(LocalSingleBlockLoadStoreElimTest, RedundantStore2) {
932   // Test that checks if a pointer variable is removed.
933   const std::string predefs_before =
934       R"(OpCapability Shader
935 %1 = OpExtInstImport "GLSL.std.450"
936 OpMemoryModel Logical GLSL450
937 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
938 OpExecutionMode %main OriginUpperLeft
939 OpSource GLSL 140
940 OpName %main "main"
941 OpName %v "v"
942 OpName %BaseColor "BaseColor"
943 OpName %gl_FragColor "gl_FragColor"
944 %void = OpTypeVoid
945 %7 = OpTypeFunction %void
946 %float = OpTypeFloat 32
947 %v4float = OpTypeVector %float 4
948 %_ptr_Function_v4float = OpTypePointer Function %v4float
949 %_ptr_Input_v4float = OpTypePointer Input %v4float
950 %BaseColor = OpVariable %_ptr_Input_v4float Input
951 %_ptr_Output_v4float = OpTypePointer Output %v4float
952 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
953 )";
954 
955   const std::string before =
956       R"(%main = OpFunction %void None %7
957 %13 = OpLabel
958 %v = OpVariable %_ptr_Function_v4float Function
959 %14 = OpLoad %v4float %BaseColor
960 OpStore %v %14
961 OpBranch %16
962 %16 = OpLabel
963 %15 = OpLoad %v4float %v
964 OpStore %v %15
965 %17 = OpLoad %v4float %v
966 OpStore %v %17
967 OpReturn
968 OpFunctionEnd
969 )";
970 
971   const std::string after =
972       R"(%main = OpFunction %void None %7
973 %13 = OpLabel
974 %v = OpVariable %_ptr_Function_v4float Function
975 %14 = OpLoad %v4float %BaseColor
976 OpStore %v %14
977 OpBranch %16
978 %16 = OpLabel
979 %15 = OpLoad %v4float %v
980 OpReturn
981 OpFunctionEnd
982 )";
983 
984   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
985   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
986       predefs_before + before, predefs_before + after, true, true);
987 }
988 
989 // Test that that an unused OpAccessChain between two store does does not
990 // hinders the removal of the first store.  We need to check this because
991 // local-access-chain-convert does always remove the OpAccessChain instructions
992 // that become dead.
993 
TEST_F(LocalSingleBlockLoadStoreElimTest,StoreElimIfInterveningUnusedAccessChain)994 TEST_F(LocalSingleBlockLoadStoreElimTest,
995        StoreElimIfInterveningUnusedAccessChain) {
996   const std::string predefs =
997       R"(OpCapability Shader
998 %1 = OpExtInstImport "GLSL.std.450"
999 OpMemoryModel Logical GLSL450
1000 OpEntryPoint Fragment %main "main" %BaseColor0 %Idx %BaseColor1 %OutColor
1001 OpExecutionMode %main OriginUpperLeft
1002 OpSource GLSL 450
1003 OpName %main "main"
1004 OpName %v "v"
1005 OpName %BaseColor0 "BaseColor0"
1006 OpName %Idx "Idx"
1007 OpName %BaseColor1 "BaseColor1"
1008 OpName %OutColor "OutColor"
1009 OpDecorate %BaseColor0 Location 0
1010 OpDecorate %Idx Flat
1011 OpDecorate %Idx Location 2
1012 OpDecorate %BaseColor1 Location 1
1013 OpDecorate %OutColor Location 0
1014 %void = OpTypeVoid
1015 %10 = OpTypeFunction %void
1016 %float = OpTypeFloat 32
1017 %v4float = OpTypeVector %float 4
1018 %_ptr_Function_v4float = OpTypePointer Function %v4float
1019 %_ptr_Input_v4float = OpTypePointer Input %v4float
1020 %BaseColor0 = OpVariable %_ptr_Input_v4float Input
1021 %_ptr_Function_float = OpTypePointer Function %float
1022 %int = OpTypeInt 32 1
1023 %_ptr_Input_int = OpTypePointer Input %int
1024 %Idx = OpVariable %_ptr_Input_int Input
1025 %BaseColor1 = OpVariable %_ptr_Input_v4float Input
1026 %float_0_100000001 = OpConstant %float 0.100000001
1027 %19 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
1028 %_ptr_Output_v4float = OpTypePointer Output %v4float
1029 %OutColor = OpVariable %_ptr_Output_v4float Output
1030 )";
1031 
1032   const std::string before =
1033       R"(%main = OpFunction %void None %10
1034 %21 = OpLabel
1035 %v = OpVariable %_ptr_Function_v4float Function
1036 %22 = OpLoad %v4float %BaseColor0
1037 OpStore %v %22
1038 %23 = OpLoad %int %Idx
1039 %24 = OpAccessChain %_ptr_Function_float %v %23
1040 %26 = OpLoad %v4float %BaseColor1
1041 %27 = OpFAdd %v4float %26 %19
1042 OpStore %v %27
1043 OpReturn
1044 OpFunctionEnd
1045 )";
1046 
1047   const std::string after =
1048       R"(%main = OpFunction %void None %10
1049 %21 = OpLabel
1050 %v = OpVariable %_ptr_Function_v4float Function
1051 %22 = OpLoad %v4float %BaseColor0
1052 %23 = OpLoad %int %Idx
1053 %24 = OpAccessChain %_ptr_Function_float %v %23
1054 %26 = OpLoad %v4float %BaseColor1
1055 %27 = OpFAdd %v4float %26 %19
1056 OpStore %v %27
1057 OpReturn
1058 OpFunctionEnd
1059 )";
1060 
1061   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1062   SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
1063       predefs + before, predefs + after, true, true);
1064 }
1065 
TEST_F(LocalSingleBlockLoadStoreElimTest,VariablePointerTest)1066 TEST_F(LocalSingleBlockLoadStoreElimTest, VariablePointerTest) {
1067   // Check that the load of the first variable is still used and that the load
1068   // of the third variable is propagated.  The first load has to remain because
1069   // of the store to the variable pointer.
1070   const std::string text = R"(
1071 ; CHECK: [[v1:%\w+]] = OpVariable
1072 ; CHECK: [[v2:%\w+]] = OpVariable
1073 ; CHECK: [[v3:%\w+]] = OpVariable
1074 ; CHECK: [[phi:%\w+]] = OpPhi
1075 ; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]]
1076 ; CHECK: OpIAdd %int [[ld1]] %int_0
1077                OpCapability Shader
1078                OpCapability VariablePointers
1079           %1 = OpExtInstImport "GLSL.std.450"
1080                OpMemoryModel Logical GLSL450
1081                OpEntryPoint GLCompute %2 "main"
1082                OpExecutionMode %2 LocalSize 1 1 1
1083                OpSource GLSL 450
1084                OpMemberDecorate %_struct_3 0 Offset 0
1085                OpMemberDecorate %_struct_3 1 Offset 4
1086        %void = OpTypeVoid
1087           %5 = OpTypeFunction %void
1088         %int = OpTypeInt 32 1
1089        %bool = OpTypeBool
1090   %_struct_3 = OpTypeStruct %int %int
1091 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
1092 %_ptr_Function_int = OpTypePointer Function %int
1093        %true = OpConstantTrue %bool
1094       %int_0 = OpConstant %int 0
1095       %int_1 = OpConstant %int 1
1096          %13 = OpConstantNull %_struct_3
1097           %2 = OpFunction %void None %5
1098          %14 = OpLabel
1099          %15 = OpVariable %_ptr_Function_int Function
1100          %16 = OpVariable %_ptr_Function_int Function
1101          %17 = OpVariable %_ptr_Function_int Function
1102                OpSelectionMerge %18 None
1103                OpBranchConditional %true %19 %20
1104          %19 = OpLabel
1105                OpBranch %18
1106          %20 = OpLabel
1107                OpBranch %18
1108          %18 = OpLabel
1109          %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20
1110                OpStore %15 %int_1
1111                OpStore %21 %int_0
1112          %22 = OpLoad %int %15
1113                OpStore %17 %int_0
1114          %23 = OpLoad %int %17
1115          %24 = OpIAdd %int %22 %23
1116                OpReturn
1117                OpFunctionEnd
1118   )";
1119   SinglePassRunAndMatch<LocalSingleBlockLoadStoreElimPass>(text, false);
1120 }
1121 
TEST_F(LocalSingleBlockLoadStoreElimTest,DebugDeclareTest)1122 TEST_F(LocalSingleBlockLoadStoreElimTest, DebugDeclareTest) {
1123   // If OpenCL.DebugInfo.100 enabled, check that store/load is still
1124   // optimized, but stores are not deleted for store/store.
1125   //
1126   // struct PS_INPUT {
1127   //   float4 c0 : COLOR0;
1128   //   float4 c1 : COLOR1;
1129   // };
1130   //
1131   // struct PS_OUTPUT {
1132   //   float4 vColor : SV_Target0;
1133   // };
1134   //
1135   // PS_OUTPUT MainPs(PS_INPUT i) {
1136   //   PS_OUTPUT ps_output;
1137   //   float4 c;
1138   //   c = i.c0;
1139   //   c += i.c1;
1140   //   c /= 2.0;
1141   //   ps_output.vColor = c;
1142   //   return ps_output;
1143   // }
1144   const std::string text = R"(
1145                OpCapability Shader
1146           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1147                OpMemoryModel Logical GLSL450
1148                OpEntryPoint Fragment %MainPs "MainPs" %in_var_COLOR0 %in_var_COLOR1 %out_var_SV_Target0
1149                OpExecutionMode %MainPs OriginUpperLeft
1150           %6 = OpString "foo3.frag"
1151           %7 = OpString "PS_OUTPUT"
1152           %8 = OpString "float"
1153           %9 = OpString "vColor"
1154          %10 = OpString "PS_INPUT"
1155          %11 = OpString "c1"
1156          %12 = OpString "c0"
1157          %13 = OpString "src.MainPs"
1158          %14 = OpString "c"
1159          %15 = OpString "ps_output"
1160          %16 = OpString "i"
1161                OpName %in_var_COLOR0 "in.var.COLOR0"
1162                OpName %in_var_COLOR1 "in.var.COLOR1"
1163                OpName %out_var_SV_Target0 "out.var.SV_Target0"
1164                OpName %MainPs "MainPs"
1165                OpName %PS_INPUT "PS_INPUT"
1166                OpMemberName %PS_INPUT 0 "c0"
1167                OpMemberName %PS_INPUT 1 "c1"
1168                OpName %param_var_i "param.var.i"
1169                OpName %PS_OUTPUT "PS_OUTPUT"
1170                OpMemberName %PS_OUTPUT 0 "vColor"
1171                OpName %src_MainPs "src.MainPs"
1172                OpName %i "i"
1173                OpName %bb_entry "bb.entry"
1174                OpName %ps_output "ps_output"
1175                OpName %c "c"
1176                OpDecorate %in_var_COLOR0 Location 0
1177                OpDecorate %in_var_COLOR1 Location 1
1178                OpDecorate %out_var_SV_Target0 Location 0
1179         %int = OpTypeInt 32 1
1180       %int_0 = OpConstant %int 0
1181       %int_1 = OpConstant %int 1
1182       %float = OpTypeFloat 32
1183     %float_2 = OpConstant %float 2
1184     %v4float = OpTypeVector %float 4
1185          %31 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
1186        %uint = OpTypeInt 32 0
1187     %uint_32 = OpConstant %uint 32
1188 %_ptr_Input_v4float = OpTypePointer Input %v4float
1189 %_ptr_Output_v4float = OpTypePointer Output %v4float
1190        %void = OpTypeVoid
1191    %uint_128 = OpConstant %uint 128
1192      %uint_0 = OpConstant %uint 0
1193    %uint_256 = OpConstant %uint 256
1194          %40 = OpTypeFunction %void
1195    %PS_INPUT = OpTypeStruct %v4float %v4float
1196 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1197   %PS_OUTPUT = OpTypeStruct %v4float
1198          %42 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1199 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1200 %_ptr_Function_v4float = OpTypePointer Function %v4float
1201 %in_var_COLOR0 = OpVariable %_ptr_Input_v4float Input
1202 %in_var_COLOR1 = OpVariable %_ptr_Input_v4float Input
1203 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
1204          %45 = OpExtInst %void %1 DebugSource %6
1205          %46 = OpExtInst %void %1 DebugCompilationUnit 1 4 %45 HLSL
1206          %47 = OpExtInst %void %1 DebugTypeComposite %7 Structure %45 8 1 %46 %7 %uint_128 FlagIsProtected|FlagIsPrivate %48
1207          %49 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
1208          %50 = OpExtInst %void %1 DebugTypeVector %49 4
1209          %48 = OpExtInst %void %1 DebugTypeMember %9 %50 %45 10 5 %47 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1210          %51 = OpExtInst %void %1 DebugTypeComposite %10 Structure %45 2 1 %46 %10 %uint_256 FlagIsProtected|FlagIsPrivate %52 %53
1211          %53 = OpExtInst %void %1 DebugTypeMember %11 %50 %45 5 5 %51 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
1212          %52 = OpExtInst %void %1 DebugTypeMember %12 %50 %45 4 5 %51 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1213          %54 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %47 %51
1214          %55 = OpExtInst %void %1 DebugFunction %13 %54 %45 13 1 %46 %13 FlagIsProtected|FlagIsPrivate 14 %src_MainPs
1215          %56 = OpExtInst %void %1 DebugLexicalBlock %45 14 1 %55
1216          %57 = OpExtInst %void %1 DebugLocalVariable %14 %50 %45 16 12 %56 FlagIsLocal
1217          %58 = OpExtInst %void %1 DebugLocalVariable %15 %47 %45 15 15 %56 FlagIsLocal
1218          %59 = OpExtInst %void %1 DebugExpression
1219          %60 = OpExtInst %void %1 DebugLocalVariable %16 %51 %45 13 29 %55 FlagIsLocal 1
1220          %61 = OpExtInst %void %1 DebugLocalVariable %14 %50 %45 16 12 %55 FlagIsLocal 1
1221      %MainPs = OpFunction %void None %40
1222          %62 = OpLabel
1223 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
1224          %63 = OpLoad %v4float %in_var_COLOR0
1225          %64 = OpLoad %v4float %in_var_COLOR1
1226          %65 = OpCompositeConstruct %PS_INPUT %63 %64
1227                OpStore %param_var_i %65
1228          %66 = OpFunctionCall %PS_OUTPUT %src_MainPs %param_var_i
1229          %67 = OpCompositeExtract %v4float %66 0
1230                OpStore %out_var_SV_Target0 %67
1231                OpReturn
1232                OpFunctionEnd
1233                OpLine %6 13 1
1234  %src_MainPs = OpFunction %PS_OUTPUT None %42
1235          %83 = OpExtInst %void %1 DebugScope %55
1236                OpLine %6 13 29
1237           %i = OpFunctionParameter %_ptr_Function_PS_INPUT
1238          %69 = OpExtInst %void %1 DebugDeclare %60 %i %59
1239          %84 = OpExtInst %void %1 DebugNoScope
1240    %bb_entry = OpLabel
1241          %85 = OpExtInst %void %1 DebugScope %56
1242   %ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function
1243           %c = OpVariable %_ptr_Function_v4float Function
1244          %71 = OpExtInst %void %1 DebugDeclare %61 %c %59
1245                OpLine %6 18 9
1246          %72 = OpAccessChain %_ptr_Function_v4float %i %int_0
1247                OpLine %6 18 13
1248          %73 = OpLoad %v4float %72
1249                OpLine %6 18 5
1250                OpStore %c %73
1251 ;CHECK:        OpStore %c %73
1252                OpLine %6 19 10
1253          %74 = OpAccessChain %_ptr_Function_v4float %i %int_1
1254                OpLine %6 19 14
1255          %75 = OpLoad %v4float %74
1256                OpLine %6 19 5
1257          %76 = OpLoad %v4float %c
1258 ;CHECK-NOT:       OpLine %6 19 5
1259 ;CHECK-NOT: %76 = OpLoad %v4float %c
1260                OpLine %6 19 7
1261          %77 = OpFAdd %v4float %76 %75
1262 ;CHECK-NOT: %77 = OpFAdd %v4float %76 %75
1263 ;CHECK:     %77 = OpFAdd %v4float %73 %75
1264                OpLine %6 19 5
1265                OpStore %c %77
1266 ;CHECK:        OpStore %c %77
1267                OpLine %6 20 5
1268          %78 = OpLoad %v4float %c
1269 ;CHECK-NOT:       OpLine %6 20 5
1270 ;CHECK-NOT: %78 = OpLoad %v4float %c
1271                OpLine %6 20 7
1272          %79 = OpFDiv %v4float %78 %31
1273 ;CHECK-NOT %79 = OpFDiv %v4float %78 %31
1274 ;CHECK:    %79 = OpFDiv %v4float %77 %31
1275                OpLine %6 20 5
1276                OpStore %c %79
1277 ;CHECK:        OpStore %c %79
1278                OpLine %6 22 26
1279          %80 = OpLoad %v4float %c
1280 ;CHECK-NOT:       OpLine %6 22 26
1281 ;CHECK-NOT: %80 = OpLoad %v4float %c
1282                OpLine %6 22 5
1283          %81 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
1284                OpStore %81 %80
1285 ;CHECK-NOT:    OpStore %81 %80
1286 ;CHECK:        OpStore %81 %79
1287                OpLine %6 23 12
1288          %82 = OpLoad %PS_OUTPUT %ps_output
1289                OpLine %6 23 5
1290                OpReturnValue %82
1291          %86 = OpExtInst %void %1 DebugNoScope
1292                OpFunctionEnd
1293   )";
1294   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1295   SinglePassRunAndMatch<LocalSingleBlockLoadStoreElimPass>(text, false);
1296 }
TEST_F(LocalSingleBlockLoadStoreElimTest,DebugValueTest)1297 TEST_F(LocalSingleBlockLoadStoreElimTest, DebugValueTest) {
1298   // If OpenCL.DebugInfo.100 enabled, check that store/load is still
1299   // optimized, but stores are not deleted for store/store.
1300   // Same source as DebugDeclareTest; DebugDeclare replaced with
1301   // equivalent DebugValue
1302   const std::string text = R"(
1303                OpCapability Shader
1304           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1305                OpMemoryModel Logical GLSL450
1306                OpEntryPoint Fragment %MainPs "MainPs" %in_var_COLOR0 %in_var_COLOR1 %out_var_SV_Target0
1307                OpExecutionMode %MainPs OriginUpperLeft
1308           %6 = OpString "foo3.frag"
1309           %7 = OpString "PS_OUTPUT"
1310           %8 = OpString "float"
1311           %9 = OpString "vColor"
1312          %10 = OpString "PS_INPUT"
1313          %11 = OpString "c1"
1314          %12 = OpString "c0"
1315          %13 = OpString "src.MainPs"
1316          %14 = OpString "c"
1317          %15 = OpString "ps_output"
1318          %16 = OpString "i"
1319                OpName %in_var_COLOR0 "in.var.COLOR0"
1320                OpName %in_var_COLOR1 "in.var.COLOR1"
1321                OpName %out_var_SV_Target0 "out.var.SV_Target0"
1322                OpName %MainPs "MainPs"
1323                OpName %PS_INPUT "PS_INPUT"
1324                OpMemberName %PS_INPUT 0 "c0"
1325                OpMemberName %PS_INPUT 1 "c1"
1326                OpName %param_var_i "param.var.i"
1327                OpName %PS_OUTPUT "PS_OUTPUT"
1328                OpMemberName %PS_OUTPUT 0 "vColor"
1329                OpName %src_MainPs "src.MainPs"
1330                OpName %i "i"
1331                OpName %bb_entry "bb.entry"
1332                OpName %ps_output "ps_output"
1333                OpName %c "c"
1334                OpDecorate %in_var_COLOR0 Location 0
1335                OpDecorate %in_var_COLOR1 Location 1
1336                OpDecorate %out_var_SV_Target0 Location 0
1337         %int = OpTypeInt 32 1
1338       %int_0 = OpConstant %int 0
1339       %int_1 = OpConstant %int 1
1340       %float = OpTypeFloat 32
1341     %float_2 = OpConstant %float 2
1342     %v4float = OpTypeVector %float 4
1343          %31 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
1344        %uint = OpTypeInt 32 0
1345     %uint_32 = OpConstant %uint 32
1346 %_ptr_Input_v4float = OpTypePointer Input %v4float
1347 %_ptr_Output_v4float = OpTypePointer Output %v4float
1348        %void = OpTypeVoid
1349    %uint_128 = OpConstant %uint 128
1350      %uint_0 = OpConstant %uint 0
1351    %uint_256 = OpConstant %uint 256
1352          %40 = OpTypeFunction %void
1353    %PS_INPUT = OpTypeStruct %v4float %v4float
1354 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
1355   %PS_OUTPUT = OpTypeStruct %v4float
1356          %42 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT
1357 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
1358 %_ptr_Function_v4float = OpTypePointer Function %v4float
1359 %in_var_COLOR0 = OpVariable %_ptr_Input_v4float Input
1360 %in_var_COLOR1 = OpVariable %_ptr_Input_v4float Input
1361 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
1362          %45 = OpExtInst %void %1 DebugSource %6
1363          %46 = OpExtInst %void %1 DebugCompilationUnit 1 4 %45 HLSL
1364          %47 = OpExtInst %void %1 DebugTypeComposite %7 Structure %45 8 1 %46 %7 %uint_128 FlagIsProtected|FlagIsPrivate %48
1365          %49 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
1366          %50 = OpExtInst %void %1 DebugTypeVector %49 4
1367          %48 = OpExtInst %void %1 DebugTypeMember %9 %50 %45 10 5 %47 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1368          %51 = OpExtInst %void %1 DebugTypeComposite %10 Structure %45 2 1 %46 %10 %uint_256 FlagIsProtected|FlagIsPrivate %52 %53
1369          %53 = OpExtInst %void %1 DebugTypeMember %11 %50 %45 5 5 %51 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
1370          %52 = OpExtInst %void %1 DebugTypeMember %12 %50 %45 4 5 %51 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
1371          %54 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %47 %51
1372          %55 = OpExtInst %void %1 DebugFunction %13 %54 %45 13 1 %46 %13 FlagIsProtected|FlagIsPrivate 14 %src_MainPs
1373          %56 = OpExtInst %void %1 DebugLexicalBlock %45 14 1 %55
1374          %57 = OpExtInst %void %1 DebugLocalVariable %14 %50 %45 16 12 %56 FlagIsLocal
1375          %58 = OpExtInst %void %1 DebugLocalVariable %15 %47 %45 15 15 %56 FlagIsLocal
1376          %59 = OpExtInst %void %1 DebugExpression %60 = OpExtInst %void %1 DebugOperation Deref %61 = OpExtInst
1377 %void %1 DebugExpression %60 %62 = OpExtInst %void %1 DebugLocalVariable %16 %51
1378 %45 13 29 %55 FlagIsLocal 1 %63 = OpExtInst %void %1 DebugLocalVariable %14 %50
1379 %45 16 12 %55 FlagIsLocal 1 %MainPs = OpFunction %void None %40 %64 = OpLabel
1380 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
1381          %65 = OpLoad %v4float %in_var_COLOR0
1382          %66 = OpLoad %v4float %in_var_COLOR1
1383          %67 = OpCompositeConstruct %PS_INPUT %65 %66
1384                OpStore %param_var_i %67
1385          %68 = OpFunctionCall %PS_OUTPUT %src_MainPs %param_var_i
1386          %69 = OpCompositeExtract %v4float %68 0
1387                OpStore %out_var_SV_Target0 %69
1388                OpReturn
1389                OpFunctionEnd
1390                OpLine %6 13 1
1391  %src_MainPs = OpFunction %PS_OUTPUT None %42
1392          %70 = OpExtInst %void %1 DebugScope %55
1393                OpLine %6 13 29
1394           %i = OpFunctionParameter %_ptr_Function_PS_INPUT
1395          %71 = OpExtInst %void %1 DebugDeclare %62 %i %59
1396          %72 = OpExtInst %void %1 DebugNoScope
1397    %bb_entry = OpLabel
1398          %73 = OpExtInst %void %1 DebugScope %56
1399   %ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function
1400           %c = OpVariable %_ptr_Function_v4float Function
1401          %74 = OpExtInst %void %1 DebugValue %63 %c %61
1402                OpLine %6 18 9
1403          %75 = OpAccessChain %_ptr_Function_v4float %i %int_0
1404                OpLine %6 18 13
1405          %76 = OpLoad %v4float %75
1406                OpLine %6 18 5
1407                OpStore %c %76
1408 ;CHECK:        OpStore %c %76
1409                OpLine %6 19 10
1410          %77 = OpAccessChain %_ptr_Function_v4float %i %int_1
1411                OpLine %6 19 14
1412          %78 = OpLoad %v4float %77
1413                OpLine %6 19 5
1414          %79 = OpLoad %v4float %c
1415 ;CHECK-NOT:       OpLine %6 19 5
1416 ;CHECK-NOT: %79 = OpLoad %v4float %c
1417                OpLine %6 19 7
1418          %80 = OpFAdd %v4float %79 %78
1419 ;CHECK-NOT: %80 = OpFAdd %v4float %79 %78
1420 ;CHECK:     %80 = OpFAdd %v4float %76 %78
1421                OpLine %6 19 5
1422                OpStore %c %80
1423 ;CHECK:        OpStore %c %80
1424                OpLine %6 20 5
1425          %81 = OpLoad %v4float %c
1426 ;CHECK-NOT:       OpLine %6 20 5
1427 ;CHECK-NOT: %81 = OpLoad %v4float %c
1428                OpLine %6 20 7
1429          %82 = OpFDiv %v4float %81 %31
1430 ;CHECK-NOT: %82 = OpFDiv %v4float %81 %31
1431 ;CHECK:     %82 = OpFDiv %v4float %80 %31
1432                OpLine %6 20 5
1433                OpStore %c %82
1434 ;CHECK:        OpStore %c %82
1435                OpLine %6 22 26
1436          %83 = OpLoad %v4float %c
1437 ;CHECK-NOT:       OpLine %6 22 26
1438 ;CHECK-NOT: %83 = OpLoad %v4float %c
1439                OpLine %6 22 5
1440          %84 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0
1441                OpStore %84 %83
1442 ;CHECK-NOT:    OpStore %84 %83
1443 ;CHECK:        OpStore %84 %82
1444                OpLine %6 23 12
1445          %85 = OpLoad %PS_OUTPUT %ps_output
1446                OpLine %6 23 5
1447                OpReturnValue %85
1448          %86 = OpExtInst %void %1 DebugNoScope
1449                OpFunctionEnd
1450   )";
1451   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1452   SinglePassRunAndMatch<LocalSingleBlockLoadStoreElimPass>(text, false);
1453 }
1454 
1455 // TODO(greg-lunarg): Add tests to verify handling of these cases:
1456 //
1457 //    Other target variable types
1458 //    InBounds Access Chains
1459 //    Check for correctness in the presence of function calls
1460 //    Others?
1461 
1462 }  // namespace
1463 }  // namespace opt
1464 }  // namespace spvtools
1465