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