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