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 <memory>
17 #include <string>
18
19 #include "test/opt/pass_fixture.h"
20 #include "test/opt/pass_utils.h"
21
22 namespace spvtools {
23 namespace opt {
24 namespace {
25
26 using LocalSSAElimTest = PassTest<::testing::Test>;
27
TEST_F(LocalSSAElimTest,ForLoop)28 TEST_F(LocalSSAElimTest, ForLoop) {
29 // #version 140
30 //
31 // in vec4 BC;
32 // out float fo;
33 //
34 // void main()
35 // {
36 // float f = 0.0;
37 // for (int i=0; i<4; i++) {
38 // f = f + BC[i];
39 // }
40 // fo = f;
41 // }
42
43 const std::string predefs =
44 R"(OpCapability Shader
45 %1 = OpExtInstImport "GLSL.std.450"
46 OpMemoryModel Logical GLSL450
47 OpEntryPoint Fragment %main "main" %BC %fo
48 OpExecutionMode %main OriginUpperLeft
49 OpSource GLSL 140
50 OpName %main "main"
51 OpName %f "f"
52 OpName %i "i"
53 OpName %BC "BC"
54 OpName %fo "fo"
55 %void = OpTypeVoid
56 %8 = OpTypeFunction %void
57 %float = OpTypeFloat 32
58 %_ptr_Function_float = OpTypePointer Function %float
59 %float_0 = OpConstant %float 0
60 %int = OpTypeInt 32 1
61 %_ptr_Function_int = OpTypePointer Function %int
62 %int_0 = OpConstant %int 0
63 %int_4 = OpConstant %int 4
64 %bool = OpTypeBool
65 %v4float = OpTypeVector %float 4
66 %_ptr_Input_v4float = OpTypePointer Input %v4float
67 %BC = OpVariable %_ptr_Input_v4float Input
68 %_ptr_Input_float = OpTypePointer Input %float
69 %int_1 = OpConstant %int 1
70 %_ptr_Output_float = OpTypePointer Output %float
71 %fo = OpVariable %_ptr_Output_float Output
72 )";
73
74 const std::string before =
75 R"(%main = OpFunction %void None %8
76 %22 = OpLabel
77 %f = OpVariable %_ptr_Function_float Function
78 %i = OpVariable %_ptr_Function_int Function
79 OpStore %f %float_0
80 OpStore %i %int_0
81 OpBranch %23
82 %23 = OpLabel
83 OpLoopMerge %24 %25 None
84 OpBranch %26
85 %26 = OpLabel
86 %27 = OpLoad %int %i
87 %28 = OpSLessThan %bool %27 %int_4
88 OpBranchConditional %28 %29 %24
89 %29 = OpLabel
90 %30 = OpLoad %float %f
91 %31 = OpLoad %int %i
92 %32 = OpAccessChain %_ptr_Input_float %BC %31
93 %33 = OpLoad %float %32
94 %34 = OpFAdd %float %30 %33
95 OpStore %f %34
96 OpBranch %25
97 %25 = OpLabel
98 %35 = OpLoad %int %i
99 %36 = OpIAdd %int %35 %int_1
100 OpStore %i %36
101 OpBranch %23
102 %24 = OpLabel
103 %37 = OpLoad %float %f
104 OpStore %fo %37
105 OpReturn
106 OpFunctionEnd
107 )";
108
109 const std::string after =
110 R"(%main = OpFunction %void None %8
111 %22 = OpLabel
112 %f = OpVariable %_ptr_Function_float Function
113 %i = OpVariable %_ptr_Function_int Function
114 OpStore %f %float_0
115 OpStore %i %int_0
116 OpBranch %23
117 %23 = OpLabel
118 %39 = OpPhi %float %float_0 %22 %34 %25
119 %38 = OpPhi %int %int_0 %22 %36 %25
120 OpLoopMerge %24 %25 None
121 OpBranch %26
122 %26 = OpLabel
123 %28 = OpSLessThan %bool %38 %int_4
124 OpBranchConditional %28 %29 %24
125 %29 = OpLabel
126 %32 = OpAccessChain %_ptr_Input_float %BC %38
127 %33 = OpLoad %float %32
128 %34 = OpFAdd %float %39 %33
129 OpStore %f %34
130 OpBranch %25
131 %25 = OpLabel
132 %36 = OpIAdd %int %38 %int_1
133 OpStore %i %36
134 OpBranch %23
135 %24 = OpLabel
136 OpStore %fo %39
137 OpReturn
138 OpFunctionEnd
139 )";
140
141 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
142 true);
143 }
144
TEST_F(LocalSSAElimTest,NestedForLoop)145 TEST_F(LocalSSAElimTest, NestedForLoop) {
146 // #version 450
147 //
148 // layout (location=0) in mat4 BC;
149 // layout (location=0) out float fo;
150 //
151 // void main()
152 // {
153 // float f = 0.0;
154 // for (int i=0; i<4; i++)
155 // for (int j=0; j<4; j++)
156 // f = f + BC[i][j];
157 // fo = f;
158 // }
159
160 const std::string predefs =
161 R"(OpCapability Shader
162 %1 = OpExtInstImport "GLSL.std.450"
163 OpMemoryModel Logical GLSL450
164 OpEntryPoint Fragment %main "main" %BC %fo
165 OpExecutionMode %main OriginUpperLeft
166 OpSource GLSL 450
167 OpName %main "main"
168 OpName %f "f"
169 OpName %i "i"
170 OpName %j "j"
171 OpName %BC "BC"
172 OpName %fo "fo"
173 OpDecorate %BC Location 0
174 OpDecorate %fo Location 0
175 %void = OpTypeVoid
176 %9 = OpTypeFunction %void
177 %float = OpTypeFloat 32
178 %_ptr_Function_float = OpTypePointer Function %float
179 %float_0 = OpConstant %float 0
180 %int = OpTypeInt 32 1
181 %_ptr_Function_int = OpTypePointer Function %int
182 %int_0 = OpConstant %int 0
183 %int_4 = OpConstant %int 4
184 %bool = OpTypeBool
185 %v4float = OpTypeVector %float 4
186 %mat4v4float = OpTypeMatrix %v4float 4
187 %_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float
188 %BC = OpVariable %_ptr_Input_mat4v4float Input
189 %_ptr_Input_float = OpTypePointer Input %float
190 %int_1 = OpConstant %int 1
191 %_ptr_Output_float = OpTypePointer Output %float
192 %fo = OpVariable %_ptr_Output_float Output
193 )";
194
195 const std::string before =
196 R"(
197 ; CHECK: = OpFunction
198 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
199 ; CHECK: [[outer_header:%\w+]] = OpLabel
200 ; CHECK-NEXT: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[outer_be:%\w+]]
201 ; CHECK-NEXT: [[i:%\w+]] = OpPhi %int %int_0 [[entry]] [[i_next:%\w+]] [[outer_be]]
202 ; CHECK-NEXT: OpSLessThan {{%\w+}} [[i]]
203 ; CHECK: [[inner_pre_header:%\w+]] = OpLabel
204 ; CHECK: [[inner_header:%\w+]] = OpLabel
205 ; CHECK-NEXT: [[inner_f]] = OpPhi %float [[outer_f]] [[inner_pre_header]] [[f_next:%\w+]] [[inner_be:%\w+]]
206 ; CHECK-NEXT: [[j:%\w+]] = OpPhi %int %int_0 [[inner_pre_header]] [[j_next:%\w+]] [[inner_be]]
207 ; CHECK: [[inner_be]] = OpLabel
208 ; CHECK: [[f_next]] = OpFAdd %float [[inner_f]]
209 ; CHECK: [[j_next]] = OpIAdd %int [[j]] %int_1
210 ; CHECK: [[outer_be]] = OpLabel
211 ; CHECK: [[i_next]] = OpIAdd
212 ; CHECK: OpStore %fo [[outer_f]]
213 %main = OpFunction %void None %9
214 %24 = OpLabel
215 %f = OpVariable %_ptr_Function_float Function
216 %i = OpVariable %_ptr_Function_int Function
217 %j = OpVariable %_ptr_Function_int Function
218 OpStore %f %float_0
219 OpStore %i %int_0
220 OpBranch %25
221 %25 = OpLabel
222 %26 = OpLoad %int %i
223 %27 = OpSLessThan %bool %26 %int_4
224 OpLoopMerge %28 %29 None
225 OpBranchConditional %27 %30 %28
226 %30 = OpLabel
227 OpStore %j %int_0
228 OpBranch %31
229 %31 = OpLabel
230 %32 = OpLoad %int %j
231 %33 = OpSLessThan %bool %32 %int_4
232 OpLoopMerge %50 %34 None
233 OpBranchConditional %33 %34 %50
234 %34 = OpLabel
235 %35 = OpLoad %float %f
236 %36 = OpLoad %int %i
237 %37 = OpLoad %int %j
238 %38 = OpAccessChain %_ptr_Input_float %BC %36 %37
239 %39 = OpLoad %float %38
240 %40 = OpFAdd %float %35 %39
241 OpStore %f %40
242 %41 = OpLoad %int %j
243 %42 = OpIAdd %int %41 %int_1
244 OpStore %j %42
245 OpBranch %31
246 %50 = OpLabel
247 OpBranch %29
248 %29 = OpLabel
249 %43 = OpLoad %int %i
250 %44 = OpIAdd %int %43 %int_1
251 OpStore %i %44
252 OpBranch %25
253 %28 = OpLabel
254 %45 = OpLoad %float %f
255 OpStore %fo %45
256 OpReturn
257 OpFunctionEnd
258 )";
259
260 SinglePassRunAndMatch<SSARewritePass>(predefs + before, true);
261 }
262
TEST_F(LocalSSAElimTest,ForLoopWithContinue)263 TEST_F(LocalSSAElimTest, ForLoopWithContinue) {
264 // #version 140
265 //
266 // in vec4 BC;
267 // out float fo;
268 //
269 // void main()
270 // {
271 // float f = 0.0;
272 // for (int i=0; i<4; i++) {
273 // float t = BC[i];
274 // if (t < 0.0)
275 // continue;
276 // f = f + t;
277 // }
278 // fo = 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" %BC %fo
286 OpExecutionMode %main OriginUpperLeft
287 OpSource GLSL 140
288 )";
289
290 const std::string names =
291 R"(OpName %main "main"
292 OpName %f "f"
293 OpName %i "i"
294 OpName %t "t"
295 OpName %BC "BC"
296 OpName %fo "fo"
297 )";
298
299 const std::string predefs2 =
300 R"(%void = OpTypeVoid
301 %9 = OpTypeFunction %void
302 %float = OpTypeFloat 32
303 %_ptr_Function_float = OpTypePointer Function %float
304 %float_0 = OpConstant %float 0
305 %int = OpTypeInt 32 1
306 %_ptr_Function_int = OpTypePointer Function %int
307 %int_0 = OpConstant %int 0
308 %int_4 = OpConstant %int 4
309 %bool = OpTypeBool
310 %v4float = OpTypeVector %float 4
311 %_ptr_Input_v4float = OpTypePointer Input %v4float
312 %BC = OpVariable %_ptr_Input_v4float Input
313 %_ptr_Input_float = OpTypePointer Input %float
314 %int_1 = OpConstant %int 1
315 %_ptr_Output_float = OpTypePointer Output %float
316 %fo = OpVariable %_ptr_Output_float Output
317 )";
318
319 const std::string before =
320 R"(%main = OpFunction %void None %9
321 %23 = OpLabel
322 %f = OpVariable %_ptr_Function_float Function
323 %i = OpVariable %_ptr_Function_int Function
324 %t = OpVariable %_ptr_Function_float Function
325 OpStore %f %float_0
326 OpStore %i %int_0
327 OpBranch %24
328 %24 = OpLabel
329 OpLoopMerge %25 %26 None
330 OpBranch %27
331 %27 = OpLabel
332 %28 = OpLoad %int %i
333 %29 = OpSLessThan %bool %28 %int_4
334 OpBranchConditional %29 %30 %25
335 %30 = OpLabel
336 %31 = OpLoad %int %i
337 %32 = OpAccessChain %_ptr_Input_float %BC %31
338 %33 = OpLoad %float %32
339 OpStore %t %33
340 %34 = OpLoad %float %t
341 %35 = OpFOrdLessThan %bool %34 %float_0
342 OpSelectionMerge %36 None
343 OpBranchConditional %35 %37 %36
344 %37 = OpLabel
345 OpBranch %26
346 %36 = OpLabel
347 %38 = OpLoad %float %f
348 %39 = OpLoad %float %t
349 %40 = OpFAdd %float %38 %39
350 OpStore %f %40
351 OpBranch %26
352 %26 = OpLabel
353 %41 = OpLoad %int %i
354 %42 = OpIAdd %int %41 %int_1
355 OpStore %i %42
356 OpBranch %24
357 %25 = OpLabel
358 %43 = OpLoad %float %f
359 OpStore %fo %43
360 OpReturn
361 OpFunctionEnd
362 )";
363
364 const std::string after =
365 R"(%main = OpFunction %void None %9
366 %23 = OpLabel
367 %f = OpVariable %_ptr_Function_float Function
368 %i = OpVariable %_ptr_Function_int Function
369 %t = OpVariable %_ptr_Function_float Function
370 OpStore %f %float_0
371 OpStore %i %int_0
372 OpBranch %24
373 %24 = OpLabel
374 %45 = OpPhi %float %float_0 %23 %47 %26
375 %44 = OpPhi %int %int_0 %23 %42 %26
376 OpLoopMerge %25 %26 None
377 OpBranch %27
378 %27 = OpLabel
379 %29 = OpSLessThan %bool %44 %int_4
380 OpBranchConditional %29 %30 %25
381 %30 = OpLabel
382 %32 = OpAccessChain %_ptr_Input_float %BC %44
383 %33 = OpLoad %float %32
384 OpStore %t %33
385 %35 = OpFOrdLessThan %bool %33 %float_0
386 OpSelectionMerge %36 None
387 OpBranchConditional %35 %37 %36
388 %37 = OpLabel
389 OpBranch %26
390 %36 = OpLabel
391 %40 = OpFAdd %float %45 %33
392 OpStore %f %40
393 OpBranch %26
394 %26 = OpLabel
395 %47 = OpPhi %float %45 %37 %40 %36
396 %42 = OpIAdd %int %44 %int_1
397 OpStore %i %42
398 OpBranch %24
399 %25 = OpLabel
400 OpStore %fo %45
401 OpReturn
402 OpFunctionEnd
403 )";
404
405 SinglePassRunAndCheck<SSARewritePass>(predefs + names + predefs2 + before,
406 predefs + names + predefs2 + after,
407 true, true);
408 }
409
TEST_F(LocalSSAElimTest,ForLoopWithBreak)410 TEST_F(LocalSSAElimTest, ForLoopWithBreak) {
411 // #version 140
412 //
413 // in vec4 BC;
414 // out float fo;
415 //
416 // void main()
417 // {
418 // float f = 0.0;
419 // for (int i=0; i<4; i++) {
420 // float t = f + BC[i];
421 // if (t > 1.0)
422 // break;
423 // f = t;
424 // }
425 // fo = f;
426 // }
427
428 const std::string predefs =
429 R"(OpCapability Shader
430 %1 = OpExtInstImport "GLSL.std.450"
431 OpMemoryModel Logical GLSL450
432 OpEntryPoint Fragment %main "main" %BC %fo
433 OpExecutionMode %main OriginUpperLeft
434 OpSource GLSL 140
435 OpName %main "main"
436 OpName %f "f"
437 OpName %i "i"
438 OpName %t "t"
439 OpName %BC "BC"
440 OpName %fo "fo"
441 %void = OpTypeVoid
442 %9 = OpTypeFunction %void
443 %float = OpTypeFloat 32
444 %_ptr_Function_float = OpTypePointer Function %float
445 %float_0 = OpConstant %float 0
446 %int = OpTypeInt 32 1
447 %_ptr_Function_int = OpTypePointer Function %int
448 %int_0 = OpConstant %int 0
449 %int_4 = OpConstant %int 4
450 %bool = OpTypeBool
451 %v4float = OpTypeVector %float 4
452 %_ptr_Input_v4float = OpTypePointer Input %v4float
453 %BC = OpVariable %_ptr_Input_v4float Input
454 %_ptr_Input_float = OpTypePointer Input %float
455 %float_1 = OpConstant %float 1
456 %int_1 = OpConstant %int 1
457 %_ptr_Output_float = OpTypePointer Output %float
458 %fo = OpVariable %_ptr_Output_float Output
459 )";
460
461 const std::string before =
462 R"(%main = OpFunction %void None %9
463 %24 = OpLabel
464 %f = OpVariable %_ptr_Function_float Function
465 %i = OpVariable %_ptr_Function_int Function
466 %t = OpVariable %_ptr_Function_float Function
467 OpStore %f %float_0
468 OpStore %i %int_0
469 OpBranch %25
470 %25 = OpLabel
471 OpLoopMerge %26 %27 None
472 OpBranch %28
473 %28 = OpLabel
474 %29 = OpLoad %int %i
475 %30 = OpSLessThan %bool %29 %int_4
476 OpBranchConditional %30 %31 %26
477 %31 = OpLabel
478 %32 = OpLoad %float %f
479 %33 = OpLoad %int %i
480 %34 = OpAccessChain %_ptr_Input_float %BC %33
481 %35 = OpLoad %float %34
482 %36 = OpFAdd %float %32 %35
483 OpStore %t %36
484 %37 = OpLoad %float %t
485 %38 = OpFOrdGreaterThan %bool %37 %float_1
486 OpSelectionMerge %39 None
487 OpBranchConditional %38 %40 %39
488 %40 = OpLabel
489 OpBranch %26
490 %39 = OpLabel
491 %41 = OpLoad %float %t
492 OpStore %f %41
493 OpBranch %27
494 %27 = OpLabel
495 %42 = OpLoad %int %i
496 %43 = OpIAdd %int %42 %int_1
497 OpStore %i %43
498 OpBranch %25
499 %26 = OpLabel
500 %44 = OpLoad %float %f
501 OpStore %fo %44
502 OpReturn
503 OpFunctionEnd
504 )";
505
506 const std::string after =
507 R"(%main = OpFunction %void None %9
508 %24 = OpLabel
509 %f = OpVariable %_ptr_Function_float Function
510 %i = OpVariable %_ptr_Function_int Function
511 %t = OpVariable %_ptr_Function_float Function
512 OpStore %f %float_0
513 OpStore %i %int_0
514 OpBranch %25
515 %25 = OpLabel
516 %46 = OpPhi %float %float_0 %24 %36 %27
517 %45 = OpPhi %int %int_0 %24 %43 %27
518 OpLoopMerge %26 %27 None
519 OpBranch %28
520 %28 = OpLabel
521 %30 = OpSLessThan %bool %45 %int_4
522 OpBranchConditional %30 %31 %26
523 %31 = OpLabel
524 %34 = OpAccessChain %_ptr_Input_float %BC %45
525 %35 = OpLoad %float %34
526 %36 = OpFAdd %float %46 %35
527 OpStore %t %36
528 %38 = OpFOrdGreaterThan %bool %36 %float_1
529 OpSelectionMerge %39 None
530 OpBranchConditional %38 %40 %39
531 %40 = OpLabel
532 OpBranch %26
533 %39 = OpLabel
534 OpStore %f %36
535 OpBranch %27
536 %27 = OpLabel
537 %43 = OpIAdd %int %45 %int_1
538 OpStore %i %43
539 OpBranch %25
540 %26 = OpLabel
541 OpStore %fo %46
542 OpReturn
543 OpFunctionEnd
544 )";
545
546 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
547 true);
548 }
549
TEST_F(LocalSSAElimTest,SwapProblem)550 TEST_F(LocalSSAElimTest, SwapProblem) {
551 // #version 140
552 //
553 // in float fe;
554 // out float fo;
555 //
556 // void main()
557 // {
558 // float f1 = 0.0;
559 // float f2 = 1.0;
560 // int ie = int(fe);
561 // for (int i=0; i<ie; i++) {
562 // float t = f1;
563 // f1 = f2;
564 // f2 = t;
565 // }
566 // fo = f1;
567 // }
568
569 const std::string predefs =
570 R"(OpCapability Shader
571 %1 = OpExtInstImport "GLSL.std.450"
572 OpMemoryModel Logical GLSL450
573 OpEntryPoint Fragment %main "main" %fe %fo
574 OpExecutionMode %main OriginUpperLeft
575 OpSource GLSL 140
576 OpName %main "main"
577 OpName %f1 "f1"
578 OpName %f2 "f2"
579 OpName %ie "ie"
580 OpName %fe "fe"
581 OpName %i "i"
582 OpName %t "t"
583 OpName %fo "fo"
584 %void = OpTypeVoid
585 %11 = OpTypeFunction %void
586 %float = OpTypeFloat 32
587 %_ptr_Function_float = OpTypePointer Function %float
588 %float_0 = OpConstant %float 0
589 %float_1 = OpConstant %float 1
590 %int = OpTypeInt 32 1
591 %_ptr_Function_int = OpTypePointer Function %int
592 %_ptr_Input_float = OpTypePointer Input %float
593 %fe = OpVariable %_ptr_Input_float Input
594 %int_0 = OpConstant %int 0
595 %bool = OpTypeBool
596 %int_1 = OpConstant %int 1
597 %_ptr_Output_float = OpTypePointer Output %float
598 %fo = OpVariable %_ptr_Output_float Output
599 )";
600
601 const std::string before =
602 R"(%main = OpFunction %void None %11
603 %23 = OpLabel
604 %f1 = OpVariable %_ptr_Function_float Function
605 %f2 = OpVariable %_ptr_Function_float Function
606 %ie = OpVariable %_ptr_Function_int Function
607 %i = OpVariable %_ptr_Function_int Function
608 %t = OpVariable %_ptr_Function_float Function
609 OpStore %f1 %float_0
610 OpStore %f2 %float_1
611 %24 = OpLoad %float %fe
612 %25 = OpConvertFToS %int %24
613 OpStore %ie %25
614 OpStore %i %int_0
615 OpBranch %26
616 %26 = OpLabel
617 OpLoopMerge %27 %28 None
618 OpBranch %29
619 %29 = OpLabel
620 %30 = OpLoad %int %i
621 %31 = OpLoad %int %ie
622 %32 = OpSLessThan %bool %30 %31
623 OpBranchConditional %32 %33 %27
624 %33 = OpLabel
625 %34 = OpLoad %float %f1
626 OpStore %t %34
627 %35 = OpLoad %float %f2
628 OpStore %f1 %35
629 %36 = OpLoad %float %t
630 OpStore %f2 %36
631 OpBranch %28
632 %28 = OpLabel
633 %37 = OpLoad %int %i
634 %38 = OpIAdd %int %37 %int_1
635 OpStore %i %38
636 OpBranch %26
637 %27 = OpLabel
638 %39 = OpLoad %float %f1
639 OpStore %fo %39
640 OpReturn
641 OpFunctionEnd
642 )";
643
644 const std::string after =
645 R"(%main = OpFunction %void None %11
646 %23 = OpLabel
647 %f1 = OpVariable %_ptr_Function_float Function
648 %f2 = OpVariable %_ptr_Function_float Function
649 %ie = OpVariable %_ptr_Function_int Function
650 %i = OpVariable %_ptr_Function_int Function
651 %t = OpVariable %_ptr_Function_float Function
652 OpStore %f1 %float_0
653 OpStore %f2 %float_1
654 %24 = OpLoad %float %fe
655 %25 = OpConvertFToS %int %24
656 OpStore %ie %25
657 OpStore %i %int_0
658 OpBranch %26
659 %26 = OpLabel
660 %43 = OpPhi %float %float_1 %23 %42 %28
661 %42 = OpPhi %float %float_0 %23 %43 %28
662 %40 = OpPhi %int %int_0 %23 %38 %28
663 OpLoopMerge %27 %28 None
664 OpBranch %29
665 %29 = OpLabel
666 %32 = OpSLessThan %bool %40 %25
667 OpBranchConditional %32 %33 %27
668 %33 = OpLabel
669 OpStore %t %42
670 OpStore %f1 %43
671 OpStore %f2 %42
672 OpBranch %28
673 %28 = OpLabel
674 %38 = OpIAdd %int %40 %int_1
675 OpStore %i %38
676 OpBranch %26
677 %27 = OpLabel
678 OpStore %fo %42
679 OpReturn
680 OpFunctionEnd
681 )";
682
683 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
684 true);
685 }
686
TEST_F(LocalSSAElimTest,LostCopyProblem)687 TEST_F(LocalSSAElimTest, LostCopyProblem) {
688 // #version 140
689 //
690 // in vec4 BC;
691 // out float fo;
692 //
693 // void main()
694 // {
695 // float f = 0.0;
696 // float t;
697 // for (int i=0; i<4; i++) {
698 // t = f;
699 // f = f + BC[i];
700 // if (f > 1.0)
701 // break;
702 // }
703 // fo = t;
704 // }
705
706 const std::string predefs =
707 R"(OpCapability Shader
708 %1 = OpExtInstImport "GLSL.std.450"
709 OpMemoryModel Logical GLSL450
710 OpEntryPoint Fragment %main "main" %BC %fo
711 OpExecutionMode %main OriginUpperLeft
712 OpSource GLSL 140
713 OpName %main "main"
714 OpName %f "f"
715 OpName %i "i"
716 OpName %t "t"
717 OpName %BC "BC"
718 OpName %fo "fo"
719 %void = OpTypeVoid
720 %9 = OpTypeFunction %void
721 %float = OpTypeFloat 32
722 %_ptr_Function_float = OpTypePointer Function %float
723 %float_0 = OpConstant %float 0
724 %int = OpTypeInt 32 1
725 %_ptr_Function_int = OpTypePointer Function %int
726 %int_0 = OpConstant %int 0
727 %int_4 = OpConstant %int 4
728 %bool = OpTypeBool
729 %v4float = OpTypeVector %float 4
730 %_ptr_Input_v4float = OpTypePointer Input %v4float
731 %BC = OpVariable %_ptr_Input_v4float Input
732 %_ptr_Input_float = OpTypePointer Input %float
733 %float_1 = OpConstant %float 1
734 %int_1 = OpConstant %int 1
735 %_ptr_Output_float = OpTypePointer Output %float
736 %fo = OpVariable %_ptr_Output_float Output
737 )";
738
739 const std::string before =
740 R"(%main = OpFunction %void None %9
741 %24 = OpLabel
742 %f = OpVariable %_ptr_Function_float Function
743 %i = OpVariable %_ptr_Function_int Function
744 %t = OpVariable %_ptr_Function_float Function
745 OpStore %f %float_0
746 OpStore %i %int_0
747 OpBranch %25
748 %25 = OpLabel
749 OpLoopMerge %26 %27 None
750 OpBranch %28
751 %28 = OpLabel
752 %29 = OpLoad %int %i
753 %30 = OpSLessThan %bool %29 %int_4
754 OpBranchConditional %30 %31 %26
755 %31 = OpLabel
756 %32 = OpLoad %float %f
757 OpStore %t %32
758 %33 = OpLoad %float %f
759 %34 = OpLoad %int %i
760 %35 = OpAccessChain %_ptr_Input_float %BC %34
761 %36 = OpLoad %float %35
762 %37 = OpFAdd %float %33 %36
763 OpStore %f %37
764 %38 = OpLoad %float %f
765 %39 = OpFOrdGreaterThan %bool %38 %float_1
766 OpSelectionMerge %40 None
767 OpBranchConditional %39 %41 %40
768 %41 = OpLabel
769 OpBranch %26
770 %40 = OpLabel
771 OpBranch %27
772 %27 = OpLabel
773 %42 = OpLoad %int %i
774 %43 = OpIAdd %int %42 %int_1
775 OpStore %i %43
776 OpBranch %25
777 %26 = OpLabel
778 %44 = OpLoad %float %t
779 OpStore %fo %44
780 OpReturn
781 OpFunctionEnd
782 )";
783
784 const std::string after =
785 R"(%49 = OpUndef %float
786 %main = OpFunction %void None %9
787 %24 = OpLabel
788 %f = OpVariable %_ptr_Function_float Function
789 %i = OpVariable %_ptr_Function_int Function
790 %t = OpVariable %_ptr_Function_float Function
791 OpStore %f %float_0
792 OpStore %i %int_0
793 OpBranch %25
794 %25 = OpLabel
795 %46 = OpPhi %float %float_0 %24 %37 %27
796 %45 = OpPhi %int %int_0 %24 %43 %27
797 %48 = OpPhi %float %49 %24 %46 %27
798 OpLoopMerge %26 %27 None
799 OpBranch %28
800 %28 = OpLabel
801 %30 = OpSLessThan %bool %45 %int_4
802 OpBranchConditional %30 %31 %26
803 %31 = OpLabel
804 OpStore %t %46
805 %35 = OpAccessChain %_ptr_Input_float %BC %45
806 %36 = OpLoad %float %35
807 %37 = OpFAdd %float %46 %36
808 OpStore %f %37
809 %39 = OpFOrdGreaterThan %bool %37 %float_1
810 OpSelectionMerge %40 None
811 OpBranchConditional %39 %41 %40
812 %41 = OpLabel
813 OpBranch %26
814 %40 = OpLabel
815 OpBranch %27
816 %27 = OpLabel
817 %43 = OpIAdd %int %45 %int_1
818 OpStore %i %43
819 OpBranch %25
820 %26 = OpLabel
821 %47 = OpPhi %float %48 %28 %46 %41
822 OpStore %fo %47
823 OpReturn
824 OpFunctionEnd
825 )";
826
827 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
828 true);
829 }
830
TEST_F(LocalSSAElimTest,IfThenElse)831 TEST_F(LocalSSAElimTest, IfThenElse) {
832 // #version 140
833 //
834 // in vec4 BaseColor;
835 // in float f;
836 //
837 // void main()
838 // {
839 // vec4 v;
840 // if (f >= 0)
841 // v = BaseColor * 0.5;
842 // else
843 // v = BaseColor + vec4(1.0,1.0,1.0,1.0);
844 // gl_FragColor = v;
845 // }
846
847 const std::string predefs =
848 R"(OpCapability Shader
849 %1 = OpExtInstImport "GLSL.std.450"
850 OpMemoryModel Logical GLSL450
851 OpEntryPoint Fragment %main "main" %f %BaseColor %gl_FragColor
852 OpExecutionMode %main OriginUpperLeft
853 OpSource GLSL 140
854 OpName %main "main"
855 OpName %f "f"
856 OpName %v "v"
857 OpName %BaseColor "BaseColor"
858 OpName %gl_FragColor "gl_FragColor"
859 %void = OpTypeVoid
860 %8 = OpTypeFunction %void
861 %float = OpTypeFloat 32
862 %_ptr_Input_float = OpTypePointer Input %float
863 %f = OpVariable %_ptr_Input_float Input
864 %float_0 = OpConstant %float 0
865 %bool = OpTypeBool
866 %v4float = OpTypeVector %float 4
867 %_ptr_Function_v4float = OpTypePointer Function %v4float
868 %_ptr_Input_v4float = OpTypePointer Input %v4float
869 %BaseColor = OpVariable %_ptr_Input_v4float Input
870 %float_0_5 = OpConstant %float 0.5
871 %float_1 = OpConstant %float 1
872 %18 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
873 %_ptr_Output_v4float = OpTypePointer Output %v4float
874 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
875 )";
876
877 const std::string before =
878 R"(%main = OpFunction %void None %8
879 %20 = OpLabel
880 %v = OpVariable %_ptr_Function_v4float Function
881 %21 = OpLoad %float %f
882 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
883 OpSelectionMerge %23 None
884 OpBranchConditional %22 %24 %25
885 %24 = OpLabel
886 %26 = OpLoad %v4float %BaseColor
887 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
888 OpStore %v %27
889 OpBranch %23
890 %25 = OpLabel
891 %28 = OpLoad %v4float %BaseColor
892 %29 = OpFAdd %v4float %28 %18
893 OpStore %v %29
894 OpBranch %23
895 %23 = OpLabel
896 %30 = OpLoad %v4float %v
897 OpStore %gl_FragColor %30
898 OpReturn
899 OpFunctionEnd
900 )";
901
902 const std::string after =
903 R"(%main = OpFunction %void None %8
904 %20 = OpLabel
905 %v = OpVariable %_ptr_Function_v4float Function
906 %21 = OpLoad %float %f
907 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
908 OpSelectionMerge %23 None
909 OpBranchConditional %22 %24 %25
910 %24 = OpLabel
911 %26 = OpLoad %v4float %BaseColor
912 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
913 OpStore %v %27
914 OpBranch %23
915 %25 = OpLabel
916 %28 = OpLoad %v4float %BaseColor
917 %29 = OpFAdd %v4float %28 %18
918 OpStore %v %29
919 OpBranch %23
920 %23 = OpLabel
921 %31 = OpPhi %v4float %27 %24 %29 %25
922 OpStore %gl_FragColor %31
923 OpReturn
924 OpFunctionEnd
925 )";
926
927 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
928 true);
929 }
930
TEST_F(LocalSSAElimTest,IfThen)931 TEST_F(LocalSSAElimTest, IfThen) {
932 // #version 140
933 //
934 // in vec4 BaseColor;
935 // in float f;
936 //
937 // void main()
938 // {
939 // vec4 v = BaseColor;
940 // if (f <= 0)
941 // v = v * 0.5;
942 // gl_FragColor = v;
943 // }
944
945 const std::string predefs =
946 R"(OpCapability Shader
947 %1 = OpExtInstImport "GLSL.std.450"
948 OpMemoryModel Logical GLSL450
949 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
950 OpExecutionMode %main OriginUpperLeft
951 OpSource GLSL 140
952 OpName %main "main"
953 OpName %v "v"
954 OpName %BaseColor "BaseColor"
955 OpName %f "f"
956 OpName %gl_FragColor "gl_FragColor"
957 %void = OpTypeVoid
958 %8 = OpTypeFunction %void
959 %float = OpTypeFloat 32
960 %v4float = OpTypeVector %float 4
961 %_ptr_Function_v4float = OpTypePointer Function %v4float
962 %_ptr_Input_v4float = OpTypePointer Input %v4float
963 %BaseColor = OpVariable %_ptr_Input_v4float Input
964 %_ptr_Input_float = OpTypePointer Input %float
965 %f = OpVariable %_ptr_Input_float Input
966 %float_0 = OpConstant %float 0
967 %bool = OpTypeBool
968 %float_0_5 = OpConstant %float 0.5
969 %_ptr_Output_v4float = OpTypePointer Output %v4float
970 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
971 )";
972
973 const std::string before =
974 R"(%main = OpFunction %void None %8
975 %18 = OpLabel
976 %v = OpVariable %_ptr_Function_v4float Function
977 %19 = OpLoad %v4float %BaseColor
978 OpStore %v %19
979 %20 = OpLoad %float %f
980 %21 = OpFOrdLessThanEqual %bool %20 %float_0
981 OpSelectionMerge %22 None
982 OpBranchConditional %21 %23 %22
983 %23 = OpLabel
984 %24 = OpLoad %v4float %v
985 %25 = OpVectorTimesScalar %v4float %24 %float_0_5
986 OpStore %v %25
987 OpBranch %22
988 %22 = OpLabel
989 %26 = OpLoad %v4float %v
990 OpStore %gl_FragColor %26
991 OpReturn
992 OpFunctionEnd
993 )";
994
995 const std::string after =
996 R"(%main = OpFunction %void None %8
997 %18 = OpLabel
998 %v = OpVariable %_ptr_Function_v4float Function
999 %19 = OpLoad %v4float %BaseColor
1000 OpStore %v %19
1001 %20 = OpLoad %float %f
1002 %21 = OpFOrdLessThanEqual %bool %20 %float_0
1003 OpSelectionMerge %22 None
1004 OpBranchConditional %21 %23 %22
1005 %23 = OpLabel
1006 %25 = OpVectorTimesScalar %v4float %19 %float_0_5
1007 OpStore %v %25
1008 OpBranch %22
1009 %22 = OpLabel
1010 %27 = OpPhi %v4float %19 %18 %25 %23
1011 OpStore %gl_FragColor %27
1012 OpReturn
1013 OpFunctionEnd
1014 )";
1015
1016 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
1017 true);
1018 }
1019
TEST_F(LocalSSAElimTest,Switch)1020 TEST_F(LocalSSAElimTest, Switch) {
1021 // #version 140
1022 //
1023 // in vec4 BaseColor;
1024 // in float f;
1025 //
1026 // void main()
1027 // {
1028 // vec4 v = BaseColor;
1029 // int i = int(f);
1030 // switch (i) {
1031 // case 0:
1032 // v = v * 0.25;
1033 // break;
1034 // case 1:
1035 // v = v * 0.625;
1036 // break;
1037 // case 2:
1038 // v = v * 0.75;
1039 // break;
1040 // default:
1041 // break;
1042 // }
1043 // gl_FragColor = v;
1044 // }
1045
1046 const std::string predefs =
1047 R"(OpCapability Shader
1048 %1 = OpExtInstImport "GLSL.std.450"
1049 OpMemoryModel Logical GLSL450
1050 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
1051 OpExecutionMode %main OriginUpperLeft
1052 OpSource GLSL 140
1053 OpName %main "main"
1054 OpName %v "v"
1055 OpName %BaseColor "BaseColor"
1056 OpName %i "i"
1057 OpName %f "f"
1058 OpName %gl_FragColor "gl_FragColor"
1059 %void = OpTypeVoid
1060 %9 = OpTypeFunction %void
1061 %float = OpTypeFloat 32
1062 %v4float = OpTypeVector %float 4
1063 %_ptr_Function_v4float = OpTypePointer Function %v4float
1064 %_ptr_Input_v4float = OpTypePointer Input %v4float
1065 %BaseColor = OpVariable %_ptr_Input_v4float Input
1066 %int = OpTypeInt 32 1
1067 %_ptr_Function_int = OpTypePointer Function %int
1068 %_ptr_Input_float = OpTypePointer Input %float
1069 %f = OpVariable %_ptr_Input_float Input
1070 %float_0_25 = OpConstant %float 0.25
1071 %float_0_625 = OpConstant %float 0.625
1072 %float_0_75 = OpConstant %float 0.75
1073 %_ptr_Output_v4float = OpTypePointer Output %v4float
1074 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
1075 )";
1076
1077 const std::string before =
1078 R"(%main = OpFunction %void None %9
1079 %21 = OpLabel
1080 %v = OpVariable %_ptr_Function_v4float Function
1081 %i = OpVariable %_ptr_Function_int Function
1082 %22 = OpLoad %v4float %BaseColor
1083 OpStore %v %22
1084 %23 = OpLoad %float %f
1085 %24 = OpConvertFToS %int %23
1086 OpStore %i %24
1087 %25 = OpLoad %int %i
1088 OpSelectionMerge %26 None
1089 OpSwitch %25 %27 0 %28 1 %29 2 %30
1090 %27 = OpLabel
1091 OpBranch %26
1092 %28 = OpLabel
1093 %31 = OpLoad %v4float %v
1094 %32 = OpVectorTimesScalar %v4float %31 %float_0_25
1095 OpStore %v %32
1096 OpBranch %26
1097 %29 = OpLabel
1098 %33 = OpLoad %v4float %v
1099 %34 = OpVectorTimesScalar %v4float %33 %float_0_625
1100 OpStore %v %34
1101 OpBranch %26
1102 %30 = OpLabel
1103 %35 = OpLoad %v4float %v
1104 %36 = OpVectorTimesScalar %v4float %35 %float_0_75
1105 OpStore %v %36
1106 OpBranch %26
1107 %26 = OpLabel
1108 %37 = OpLoad %v4float %v
1109 OpStore %gl_FragColor %37
1110 OpReturn
1111 OpFunctionEnd
1112 )";
1113
1114 const std::string after =
1115 R"(%main = OpFunction %void None %9
1116 %21 = OpLabel
1117 %v = OpVariable %_ptr_Function_v4float Function
1118 %i = OpVariable %_ptr_Function_int Function
1119 %22 = OpLoad %v4float %BaseColor
1120 OpStore %v %22
1121 %23 = OpLoad %float %f
1122 %24 = OpConvertFToS %int %23
1123 OpStore %i %24
1124 OpSelectionMerge %26 None
1125 OpSwitch %24 %27 0 %28 1 %29 2 %30
1126 %27 = OpLabel
1127 OpBranch %26
1128 %28 = OpLabel
1129 %32 = OpVectorTimesScalar %v4float %22 %float_0_25
1130 OpStore %v %32
1131 OpBranch %26
1132 %29 = OpLabel
1133 %34 = OpVectorTimesScalar %v4float %22 %float_0_625
1134 OpStore %v %34
1135 OpBranch %26
1136 %30 = OpLabel
1137 %36 = OpVectorTimesScalar %v4float %22 %float_0_75
1138 OpStore %v %36
1139 OpBranch %26
1140 %26 = OpLabel
1141 %38 = OpPhi %v4float %22 %27 %32 %28 %34 %29 %36 %30
1142 OpStore %gl_FragColor %38
1143 OpReturn
1144 OpFunctionEnd
1145 )";
1146
1147 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
1148 true);
1149 }
1150
TEST_F(LocalSSAElimTest,SwitchWithFallThrough)1151 TEST_F(LocalSSAElimTest, SwitchWithFallThrough) {
1152 // #version 140
1153 //
1154 // in vec4 BaseColor;
1155 // in float f;
1156 //
1157 // void main()
1158 // {
1159 // vec4 v = BaseColor;
1160 // int i = int(f);
1161 // switch (i) {
1162 // case 0:
1163 // v = v * 0.25;
1164 // break;
1165 // case 1:
1166 // v = v + 0.25;
1167 // case 2:
1168 // v = v * 0.75;
1169 // break;
1170 // default:
1171 // break;
1172 // }
1173 // gl_FragColor = v;
1174 // }
1175
1176 const std::string predefs =
1177 R"(OpCapability Shader
1178 %1 = OpExtInstImport "GLSL.std.450"
1179 OpMemoryModel Logical GLSL450
1180 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
1181 OpExecutionMode %main OriginUpperLeft
1182 OpSource GLSL 140
1183 OpName %main "main"
1184 OpName %v "v"
1185 OpName %BaseColor "BaseColor"
1186 OpName %i "i"
1187 OpName %f "f"
1188 OpName %gl_FragColor "gl_FragColor"
1189 %void = OpTypeVoid
1190 %9 = OpTypeFunction %void
1191 %float = OpTypeFloat 32
1192 %v4float = OpTypeVector %float 4
1193 %_ptr_Function_v4float = OpTypePointer Function %v4float
1194 %_ptr_Input_v4float = OpTypePointer Input %v4float
1195 %BaseColor = OpVariable %_ptr_Input_v4float Input
1196 %int = OpTypeInt 32 1
1197 %_ptr_Function_int = OpTypePointer Function %int
1198 %_ptr_Input_float = OpTypePointer Input %float
1199 %f = OpVariable %_ptr_Input_float Input
1200 %float_0_25 = OpConstant %float 0.25
1201 %float_0_75 = OpConstant %float 0.75
1202 %_ptr_Output_v4float = OpTypePointer Output %v4float
1203 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
1204 )";
1205
1206 const std::string before =
1207 R"(%main = OpFunction %void None %9
1208 %20 = OpLabel
1209 %v = OpVariable %_ptr_Function_v4float Function
1210 %i = OpVariable %_ptr_Function_int Function
1211 %21 = OpLoad %v4float %BaseColor
1212 OpStore %v %21
1213 %22 = OpLoad %float %f
1214 %23 = OpConvertFToS %int %22
1215 OpStore %i %23
1216 %24 = OpLoad %int %i
1217 OpSelectionMerge %25 None
1218 OpSwitch %24 %26 0 %27 1 %28 2 %29
1219 %26 = OpLabel
1220 OpBranch %25
1221 %27 = OpLabel
1222 %30 = OpLoad %v4float %v
1223 %31 = OpVectorTimesScalar %v4float %30 %float_0_25
1224 OpStore %v %31
1225 OpBranch %25
1226 %28 = OpLabel
1227 %32 = OpLoad %v4float %v
1228 %33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
1229 %34 = OpFAdd %v4float %32 %33
1230 OpStore %v %34
1231 OpBranch %29
1232 %29 = OpLabel
1233 %35 = OpLoad %v4float %v
1234 %36 = OpVectorTimesScalar %v4float %35 %float_0_75
1235 OpStore %v %36
1236 OpBranch %25
1237 %25 = OpLabel
1238 %37 = OpLoad %v4float %v
1239 OpStore %gl_FragColor %37
1240 OpReturn
1241 OpFunctionEnd
1242 )";
1243
1244 const std::string after =
1245 R"(%main = OpFunction %void None %9
1246 %20 = OpLabel
1247 %v = OpVariable %_ptr_Function_v4float Function
1248 %i = OpVariable %_ptr_Function_int Function
1249 %21 = OpLoad %v4float %BaseColor
1250 OpStore %v %21
1251 %22 = OpLoad %float %f
1252 %23 = OpConvertFToS %int %22
1253 OpStore %i %23
1254 OpSelectionMerge %25 None
1255 OpSwitch %23 %26 0 %27 1 %28 2 %29
1256 %26 = OpLabel
1257 OpBranch %25
1258 %27 = OpLabel
1259 %31 = OpVectorTimesScalar %v4float %21 %float_0_25
1260 OpStore %v %31
1261 OpBranch %25
1262 %28 = OpLabel
1263 %33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
1264 %34 = OpFAdd %v4float %21 %33
1265 OpStore %v %34
1266 OpBranch %29
1267 %29 = OpLabel
1268 %38 = OpPhi %v4float %21 %20 %34 %28
1269 %36 = OpVectorTimesScalar %v4float %38 %float_0_75
1270 OpStore %v %36
1271 OpBranch %25
1272 %25 = OpLabel
1273 %39 = OpPhi %v4float %21 %26 %31 %27 %36 %29
1274 OpStore %gl_FragColor %39
1275 OpReturn
1276 OpFunctionEnd
1277 )";
1278
1279 SinglePassRunAndCheck<SSARewritePass>(predefs + before, predefs + after, true,
1280 true);
1281 }
1282
TEST_F(LocalSSAElimTest,DontPatchPhiInLoopHeaderThatIsNotAVar)1283 TEST_F(LocalSSAElimTest, DontPatchPhiInLoopHeaderThatIsNotAVar) {
1284 // From https://github.com/KhronosGroup/SPIRV-Tools/issues/826
1285 // Don't try patching the (%16 %7) value/predecessor pair in the OpPhi.
1286 // That OpPhi is unrelated to this optimization: we did not set that up
1287 // in the SSA initialization for the loop header block.
1288 // The pass should be a no-op on this module.
1289
1290 const std::string before = R"(OpCapability Shader
1291 OpMemoryModel Logical GLSL450
1292 OpEntryPoint GLCompute %1 "main"
1293 %void = OpTypeVoid
1294 %3 = OpTypeFunction %void
1295 %float = OpTypeFloat 32
1296 %float_1 = OpConstant %float 1
1297 %1 = OpFunction %void None %3
1298 %6 = OpLabel
1299 OpBranch %7
1300 %7 = OpLabel
1301 %8 = OpPhi %float %float_1 %6 %9 %7
1302 %9 = OpFAdd %float %8 %float_1
1303 OpLoopMerge %10 %7 None
1304 OpBranch %7
1305 %10 = OpLabel
1306 OpReturn
1307 OpFunctionEnd
1308 )";
1309
1310 SinglePassRunAndCheck<SSARewritePass>(before, before, true, true);
1311 }
1312
TEST_F(LocalSSAElimTest,OptInitializedVariableLikeStore)1313 TEST_F(LocalSSAElimTest, OptInitializedVariableLikeStore) {
1314 // Note: SPIR-V edited to change store to v into variable initialization
1315 //
1316 // #version 450
1317 //
1318 // layout (location=0) in vec4 iColor;
1319 // layout (location=1) in float fi;
1320 // layout (location=0) out vec4 oColor;
1321 //
1322 // void main()
1323 // {
1324 // vec4 v = vec4(0.0);
1325 // if (fi < 0.0)
1326 // v.x = iColor.x;
1327 // oColor = v;
1328 // }
1329
1330 const std::string predefs =
1331 R"(OpCapability Shader
1332 %1 = OpExtInstImport "GLSL.std.450"
1333 OpMemoryModel Logical GLSL450
1334 OpEntryPoint Fragment %main "main" %fi %iColor %oColor
1335 OpExecutionMode %main OriginUpperLeft
1336 OpSource GLSL 450
1337 OpName %main "main"
1338 OpName %v "v"
1339 OpName %fi "fi"
1340 OpName %iColor "iColor"
1341 OpName %oColor "oColor"
1342 OpDecorate %fi Location 1
1343 OpDecorate %iColor Location 0
1344 OpDecorate %oColor Location 0
1345 %void = OpTypeVoid
1346 %8 = OpTypeFunction %void
1347 %float = OpTypeFloat 32
1348 %v4float = OpTypeVector %float 4
1349 %_ptr_Function_v4float = OpTypePointer Function %v4float
1350 %float_0 = OpConstant %float 0
1351 %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1352 %_ptr_Input_float = OpTypePointer Input %float
1353 %fi = OpVariable %_ptr_Input_float Input
1354 %bool = OpTypeBool
1355 %_ptr_Input_v4float = OpTypePointer Input %v4float
1356 %iColor = OpVariable %_ptr_Input_v4float Input
1357 %uint = OpTypeInt 32 0
1358 %uint_0 = OpConstant %uint 0
1359 %_ptr_Function_float = OpTypePointer Function %float
1360 %_ptr_Output_v4float = OpTypePointer Output %v4float
1361 %oColor = OpVariable %_ptr_Output_v4float Output
1362 )";
1363
1364 const std::string func_before =
1365 R"(%main = OpFunction %void None %8
1366 %21 = OpLabel
1367 %v = OpVariable %_ptr_Function_v4float Function %13
1368 %22 = OpLoad %float %fi
1369 %23 = OpFOrdLessThan %bool %22 %float_0
1370 OpSelectionMerge %24 None
1371 OpBranchConditional %23 %25 %24
1372 %25 = OpLabel
1373 %26 = OpAccessChain %_ptr_Input_float %iColor %uint_0
1374 %27 = OpLoad %float %26
1375 %28 = OpLoad %v4float %v
1376 %29 = OpCompositeInsert %v4float %27 %28 0
1377 OpStore %v %29
1378 OpBranch %24
1379 %24 = OpLabel
1380 %30 = OpLoad %v4float %v
1381 OpStore %oColor %30
1382 OpReturn
1383 OpFunctionEnd
1384 )";
1385
1386 const std::string func_after =
1387 R"(%main = OpFunction %void None %8
1388 %21 = OpLabel
1389 %v = OpVariable %_ptr_Function_v4float Function %13
1390 %22 = OpLoad %float %fi
1391 %23 = OpFOrdLessThan %bool %22 %float_0
1392 OpSelectionMerge %24 None
1393 OpBranchConditional %23 %25 %24
1394 %25 = OpLabel
1395 %26 = OpAccessChain %_ptr_Input_float %iColor %uint_0
1396 %27 = OpLoad %float %26
1397 %29 = OpCompositeInsert %v4float %27 %13 0
1398 OpStore %v %29
1399 OpBranch %24
1400 %24 = OpLabel
1401 %31 = OpPhi %v4float %13 %21 %29 %25
1402 OpStore %oColor %31
1403 OpReturn
1404 OpFunctionEnd
1405 )";
1406
1407 SinglePassRunAndCheck<SSARewritePass>(predefs + func_before,
1408 predefs + func_after, true, true);
1409 }
1410
TEST_F(LocalSSAElimTest,PointerVariable)1411 TEST_F(LocalSSAElimTest, PointerVariable) {
1412 // Test that checks if a pointer variable is removed.
1413
1414 const std::string before =
1415 R"(OpCapability Shader
1416 OpMemoryModel Logical GLSL450
1417 OpEntryPoint Fragment %1 "main" %2
1418 OpExecutionMode %1 OriginUpperLeft
1419 OpMemberDecorate %_struct_3 0 Offset 0
1420 OpDecorate %_runtimearr__struct_3 ArrayStride 16
1421 OpMemberDecorate %_struct_5 0 Offset 0
1422 OpDecorate %_struct_5 BufferBlock
1423 OpMemberDecorate %_struct_6 0 Offset 0
1424 OpDecorate %_struct_6 BufferBlock
1425 OpDecorate %2 Location 0
1426 OpDecorate %7 DescriptorSet 0
1427 OpDecorate %7 Binding 0
1428 %void = OpTypeVoid
1429 %10 = OpTypeFunction %void
1430 %int = OpTypeInt 32 1
1431 %uint = OpTypeInt 32 0
1432 %float = OpTypeFloat 32
1433 %v4float = OpTypeVector %float 4
1434 %_ptr_Output_v4float = OpTypePointer Output %v4float
1435 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
1436 %_struct_3 = OpTypeStruct %v4float
1437 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
1438 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
1439 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
1440 %_struct_6 = OpTypeStruct %int
1441 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
1442 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
1443 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
1444 %int_0 = OpConstant %int 0
1445 %uint_0 = OpConstant %uint 0
1446 %2 = OpVariable %_ptr_Output_v4float Output
1447 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
1448 %1 = OpFunction %void None %10
1449 %23 = OpLabel
1450 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
1451 OpStore %24 %7
1452 %26 = OpLoad %_ptr_Uniform__struct_5 %24
1453 %27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0
1454 %28 = OpLoad %v4float %27
1455 %29 = OpCopyObject %v4float %28
1456 OpStore %2 %28
1457 OpReturn
1458 OpFunctionEnd
1459 )";
1460
1461 const std::string after =
1462 R"(OpCapability Shader
1463 OpMemoryModel Logical GLSL450
1464 OpEntryPoint Fragment %1 "main" %2
1465 OpExecutionMode %1 OriginUpperLeft
1466 OpMemberDecorate %_struct_3 0 Offset 0
1467 OpDecorate %_runtimearr__struct_3 ArrayStride 16
1468 OpMemberDecorate %_struct_5 0 Offset 0
1469 OpDecorate %_struct_5 BufferBlock
1470 OpMemberDecorate %_struct_6 0 Offset 0
1471 OpDecorate %_struct_6 BufferBlock
1472 OpDecorate %2 Location 0
1473 OpDecorate %7 DescriptorSet 0
1474 OpDecorate %7 Binding 0
1475 %void = OpTypeVoid
1476 %10 = OpTypeFunction %void
1477 %int = OpTypeInt 32 1
1478 %uint = OpTypeInt 32 0
1479 %float = OpTypeFloat 32
1480 %v4float = OpTypeVector %float 4
1481 %_ptr_Output_v4float = OpTypePointer Output %v4float
1482 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
1483 %_struct_3 = OpTypeStruct %v4float
1484 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
1485 %_struct_5 = OpTypeStruct %_runtimearr__struct_3
1486 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
1487 %_struct_6 = OpTypeStruct %int
1488 %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
1489 %_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5
1490 %_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6
1491 %int_0 = OpConstant %int 0
1492 %uint_0 = OpConstant %uint 0
1493 %2 = OpVariable %_ptr_Output_v4float Output
1494 %7 = OpVariable %_ptr_Uniform__struct_5 Uniform
1495 %1 = OpFunction %void None %10
1496 %23 = OpLabel
1497 %24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function
1498 OpStore %24 %7
1499 %27 = OpAccessChain %_ptr_Uniform_v4float %7 %int_0 %uint_0 %int_0
1500 %28 = OpLoad %v4float %27
1501 %29 = OpCopyObject %v4float %28
1502 OpStore %2 %28
1503 OpReturn
1504 OpFunctionEnd
1505 )";
1506
1507 // Relax logical pointers to allow pointer allocations.
1508 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1509 ValidatorOptions()->relax_logical_pointer = true;
1510 SinglePassRunAndCheck<SSARewritePass>(before, after, true, true);
1511 }
1512
TEST_F(LocalSSAElimTest,VerifyInstToBlockMap)1513 TEST_F(LocalSSAElimTest, VerifyInstToBlockMap) {
1514 // #version 140
1515 //
1516 // in vec4 BC;
1517 // out float fo;
1518 //
1519 // void main()
1520 // {
1521 // float f = 0.0;
1522 // for (int i=0; i<4; i++) {
1523 // f = f + BC[i];
1524 // }
1525 // fo = f;
1526 // }
1527
1528 const std::string text = R"(
1529 OpCapability Shader
1530 %1 = OpExtInstImport "GLSL.std.450"
1531 OpMemoryModel Logical GLSL450
1532 OpEntryPoint Fragment %main "main" %BC %fo
1533 OpExecutionMode %main OriginUpperLeft
1534 OpSource GLSL 140
1535 OpName %main "main"
1536 OpName %f "f"
1537 OpName %i "i"
1538 OpName %BC "BC"
1539 OpName %fo "fo"
1540 %void = OpTypeVoid
1541 %8 = OpTypeFunction %void
1542 %float = OpTypeFloat 32
1543 %_ptr_Function_float = OpTypePointer Function %float
1544 %float_0 = OpConstant %float 0
1545 %int = OpTypeInt 32 1
1546 %_ptr_Function_int = OpTypePointer Function %int
1547 %int_0 = OpConstant %int 0
1548 %int_4 = OpConstant %int 4
1549 %bool = OpTypeBool
1550 %v4float = OpTypeVector %float 4
1551 %_ptr_Input_v4float = OpTypePointer Input %v4float
1552 %BC = OpVariable %_ptr_Input_v4float Input
1553 %_ptr_Input_float = OpTypePointer Input %float
1554 %int_1 = OpConstant %int 1
1555 %_ptr_Output_float = OpTypePointer Output %float
1556 %fo = OpVariable %_ptr_Output_float Output
1557 %main = OpFunction %void None %8
1558 %22 = OpLabel
1559 %f = OpVariable %_ptr_Function_float Function
1560 %i = OpVariable %_ptr_Function_int Function
1561 OpStore %f %float_0
1562 OpStore %i %int_0
1563 OpBranch %23
1564 %23 = OpLabel
1565 OpLoopMerge %24 %25 None
1566 OpBranch %26
1567 %26 = OpLabel
1568 %27 = OpLoad %int %i
1569 %28 = OpSLessThan %bool %27 %int_4
1570 OpBranchConditional %28 %29 %24
1571 %29 = OpLabel
1572 %30 = OpLoad %float %f
1573 %31 = OpLoad %int %i
1574 %32 = OpAccessChain %_ptr_Input_float %BC %31
1575 %33 = OpLoad %float %32
1576 %34 = OpFAdd %float %30 %33
1577 OpStore %f %34
1578 OpBranch %25
1579 %25 = OpLabel
1580 %35 = OpLoad %int %i
1581 %36 = OpIAdd %int %35 %int_1
1582 OpStore %i %36
1583 OpBranch %23
1584 %24 = OpLabel
1585 %37 = OpLoad %float %f
1586 OpStore %fo %37
1587 OpReturn
1588 OpFunctionEnd
1589 )";
1590
1591 std::unique_ptr<IRContext> context =
1592 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
1593 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1594 EXPECT_NE(nullptr, context);
1595
1596 // Force the instruction to block mapping to get built.
1597 context->get_instr_block(27u);
1598
1599 auto pass = MakeUnique<SSARewritePass>();
1600 pass->SetMessageConsumer(nullptr);
1601 const auto status = pass->Run(context.get());
1602 EXPECT_TRUE(status == Pass::Status::SuccessWithChange);
1603 }
1604
TEST_F(LocalSSAElimTest,CompositeExtractProblem)1605 TEST_F(LocalSSAElimTest, CompositeExtractProblem) {
1606 const std::string spv_asm = R"(
1607 OpCapability Tessellation
1608 %1 = OpExtInstImport "GLSL.std.450"
1609 OpMemoryModel Logical GLSL450
1610 OpEntryPoint TessellationControl %2 "main" %16 %17 %18 %20 %22 %26 %27 %30 %31
1611 %void = OpTypeVoid
1612 %4 = OpTypeFunction %void
1613 %float = OpTypeFloat 32
1614 %v4float = OpTypeVector %float 4
1615 %uint = OpTypeInt 32 0
1616 %uint_3 = OpConstant %uint 3
1617 %v3float = OpTypeVector %float 3
1618 %v2float = OpTypeVector %float 2
1619 %_struct_11 = OpTypeStruct %v4float %v4float %v4float %v3float %v3float %v2float %v2float
1620 %_arr__struct_11_uint_3 = OpTypeArray %_struct_11 %uint_3
1621 %_ptr_Function__arr__struct_11_uint_3 = OpTypePointer Function %_arr__struct_11_uint_3
1622 %_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
1623 %_ptr_Input__arr_v4float_uint_3 = OpTypePointer Input %_arr_v4float_uint_3
1624 %16 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input
1625 %17 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input
1626 %18 = OpVariable %_ptr_Input__arr_v4float_uint_3 Input
1627 %_ptr_Input_uint = OpTypePointer Input %uint
1628 %20 = OpVariable %_ptr_Input_uint Input
1629 %_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3
1630 %22 = OpVariable %_ptr_Output__arr_v4float_uint_3 Output
1631 %_ptr_Output_v4float = OpTypePointer Output %v4float
1632 %_arr_v3float_uint_3 = OpTypeArray %v3float %uint_3
1633 %_ptr_Input__arr_v3float_uint_3 = OpTypePointer Input %_arr_v3float_uint_3
1634 %26 = OpVariable %_ptr_Input__arr_v3float_uint_3 Input
1635 %27 = OpVariable %_ptr_Input__arr_v3float_uint_3 Input
1636 %_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3
1637 %_ptr_Input__arr_v2float_uint_3 = OpTypePointer Input %_arr_v2float_uint_3
1638 %30 = OpVariable %_ptr_Input__arr_v2float_uint_3 Input
1639 %31 = OpVariable %_ptr_Input__arr_v2float_uint_3 Input
1640 %_ptr_Function__struct_11 = OpTypePointer Function %_struct_11
1641 %2 = OpFunction %void None %4
1642 %33 = OpLabel
1643 %66 = OpVariable %_ptr_Function__arr__struct_11_uint_3 Function
1644 %34 = OpLoad %_arr_v4float_uint_3 %16
1645 %35 = OpLoad %_arr_v4float_uint_3 %17
1646 %36 = OpLoad %_arr_v4float_uint_3 %18
1647 %37 = OpLoad %_arr_v3float_uint_3 %26
1648 %38 = OpLoad %_arr_v3float_uint_3 %27
1649 %39 = OpLoad %_arr_v2float_uint_3 %30
1650 %40 = OpLoad %_arr_v2float_uint_3 %31
1651 %41 = OpCompositeExtract %v4float %34 0
1652 %42 = OpCompositeExtract %v4float %35 0
1653 %43 = OpCompositeExtract %v4float %36 0
1654 %44 = OpCompositeExtract %v3float %37 0
1655 %45 = OpCompositeExtract %v3float %38 0
1656 %46 = OpCompositeExtract %v2float %39 0
1657 %47 = OpCompositeExtract %v2float %40 0
1658 %48 = OpCompositeConstruct %_struct_11 %41 %42 %43 %44 %45 %46 %47
1659 %49 = OpCompositeExtract %v4float %34 1
1660 %50 = OpCompositeExtract %v4float %35 1
1661 %51 = OpCompositeExtract %v4float %36 1
1662 %52 = OpCompositeExtract %v3float %37 1
1663 %53 = OpCompositeExtract %v3float %38 1
1664 %54 = OpCompositeExtract %v2float %39 1
1665 %55 = OpCompositeExtract %v2float %40 1
1666 %56 = OpCompositeConstruct %_struct_11 %49 %50 %51 %52 %53 %54 %55
1667 %57 = OpCompositeExtract %v4float %34 2
1668 %58 = OpCompositeExtract %v4float %35 2
1669 %59 = OpCompositeExtract %v4float %36 2
1670 %60 = OpCompositeExtract %v3float %37 2
1671 %61 = OpCompositeExtract %v3float %38 2
1672 %62 = OpCompositeExtract %v2float %39 2
1673 %63 = OpCompositeExtract %v2float %40 2
1674 %64 = OpCompositeConstruct %_struct_11 %57 %58 %59 %60 %61 %62 %63
1675 %65 = OpCompositeConstruct %_arr__struct_11_uint_3 %48 %56 %64
1676 %67 = OpLoad %uint %20
1677
1678 ; CHECK OpStore {{%\d+}} [[store_source:%\d+]]
1679 OpStore %66 %65
1680 %68 = OpAccessChain %_ptr_Function__struct_11 %66 %67
1681
1682 ; This load was being removed, because %_ptr_Function__struct_11 was being
1683 ; wrongfully considered an SSA target.
1684 ; CHECK OpLoad %_struct_11 %68
1685 %69 = OpLoad %_struct_11 %68
1686
1687 ; Similarly, %69 cannot be replaced with %65.
1688 ; CHECK-NOT: OpCompositeExtract %v4float [[store_source]] 0
1689 %70 = OpCompositeExtract %v4float %69 0
1690
1691 %71 = OpAccessChain %_ptr_Output_v4float %22 %67
1692 OpStore %71 %70
1693 OpReturn
1694 OpFunctionEnd)";
1695
1696 SinglePassRunAndMatch<SSARewritePass>(spv_asm, true);
1697 }
1698
1699 // Test that the RelaxedPrecision decoration on the variable to added to the
1700 // result of the OpPhi instruction.
TEST_F(LocalSSAElimTest,DecoratedVariable)1701 TEST_F(LocalSSAElimTest, DecoratedVariable) {
1702 const std::string spv_asm = R"(
1703 ; CHECK: OpDecorate [[var:%\w+]] RelaxedPrecision
1704 ; CHECK: OpDecorate [[phi_id:%\w+]] RelaxedPrecision
1705 ; CHECK: [[phi_id]] = OpPhi
1706 OpCapability Shader
1707 %1 = OpExtInstImport "GLSL.std.450"
1708 OpMemoryModel Logical GLSL450
1709 OpEntryPoint GLCompute %2 "main"
1710 OpDecorate %v RelaxedPrecision
1711 %void = OpTypeVoid
1712 %func_t = OpTypeFunction %void
1713 %bool = OpTypeBool
1714 %true = OpConstantTrue %bool
1715 %int = OpTypeInt 32 0
1716 %int_p = OpTypePointer Function %int
1717 %int_1 = OpConstant %int 1
1718 %int_0 = OpConstant %int 0
1719 %2 = OpFunction %void None %func_t
1720 %33 = OpLabel
1721 %v = OpVariable %int_p Function
1722 OpSelectionMerge %merge None
1723 OpBranchConditional %true %l1 %l2
1724 %l1 = OpLabel
1725 OpStore %v %int_1
1726 OpBranch %merge
1727 %l2 = OpLabel
1728 OpStore %v %int_0
1729 OpBranch %merge
1730 %merge = OpLabel
1731 %ld = OpLoad %int %v
1732 OpReturn
1733 OpFunctionEnd)";
1734
1735 SinglePassRunAndMatch<SSARewritePass>(spv_asm, true);
1736 }
1737
1738 // Test that the RelaxedPrecision decoration on the variable to added to the
1739 // result of the OpPhi instruction.
TEST_F(LocalSSAElimTest,MultipleEdges)1740 TEST_F(LocalSSAElimTest, MultipleEdges) {
1741 const std::string spv_asm = R"(
1742 ; CHECK: OpSelectionMerge
1743 ; CHECK: [[header_bb:%\w+]] = OpLabel
1744 ; CHECK-NOT: OpLabel
1745 ; CHECK: OpSwitch {{%\w+}} {{%\w+}} 76 [[bb1:%\w+]] 17 [[bb2:%\w+]]
1746 ; CHECK-SAME: 4 [[bb2]]
1747 ; CHECK: [[bb2]] = OpLabel
1748 ; CHECK-NEXT: OpPhi [[type:%\w+]] [[val:%\w+]] [[header_bb]] %int_0 [[bb1]]
1749 OpCapability Shader
1750 %1 = OpExtInstImport "GLSL.std.450"
1751 OpMemoryModel Logical GLSL450
1752 OpEntryPoint Fragment %4 "main"
1753 OpExecutionMode %4 OriginUpperLeft
1754 OpSource ESSL 310
1755 %void = OpTypeVoid
1756 %3 = OpTypeFunction %void
1757 %int = OpTypeInt 32 1
1758 %_ptr_Function_int = OpTypePointer Function %int
1759 %int_0 = OpConstant %int 0
1760 %bool = OpTypeBool
1761 %true = OpConstantTrue %bool
1762 %false = OpConstantFalse %bool
1763 %int_1 = OpConstant %int 1
1764 %4 = OpFunction %void None %3
1765 %5 = OpLabel
1766 %8 = OpVariable %_ptr_Function_int Function
1767 OpBranch %10
1768 %10 = OpLabel
1769 OpLoopMerge %12 %13 None
1770 OpBranch %14
1771 %14 = OpLabel
1772 OpBranchConditional %true %11 %12
1773 %11 = OpLabel
1774 OpSelectionMerge %19 None
1775 OpBranchConditional %false %18 %19
1776 %18 = OpLabel
1777 OpSelectionMerge %22 None
1778 OpSwitch %int_0 %22 76 %20 17 %21 4 %21
1779 %20 = OpLabel
1780 %23 = OpLoad %int %8
1781 OpStore %8 %int_0
1782 OpBranch %21
1783 %21 = OpLabel
1784 OpBranch %22
1785 %22 = OpLabel
1786 OpBranch %19
1787 %19 = OpLabel
1788 OpBranch %13
1789 %13 = OpLabel
1790 OpBranch %10
1791 %12 = OpLabel
1792 OpReturn
1793 OpFunctionEnd
1794 )";
1795
1796 SinglePassRunAndMatch<SSARewritePass>(spv_asm, true);
1797 }
1798
TEST_F(LocalSSAElimTest,VariablePointerTest1)1799 TEST_F(LocalSSAElimTest, VariablePointerTest1) {
1800 // Check that the load of the first variable is still used and that the load
1801 // of the third variable is propagated. The first load has to remain because
1802 // of the store to the variable pointer.
1803 const std::string text = R"(
1804 ; CHECK: [[v1:%\w+]] = OpVariable
1805 ; CHECK: [[v2:%\w+]] = OpVariable
1806 ; CHECK: [[v3:%\w+]] = OpVariable
1807 ; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]]
1808 ; CHECK: OpIAdd %int [[ld1]] %int_0
1809 OpCapability Shader
1810 OpCapability VariablePointers
1811 %1 = OpExtInstImport "GLSL.std.450"
1812 OpMemoryModel Logical GLSL450
1813 OpEntryPoint GLCompute %2 "main"
1814 OpExecutionMode %2 LocalSize 1 1 1
1815 OpSource GLSL 450
1816 OpMemberDecorate %_struct_3 0 Offset 0
1817 OpMemberDecorate %_struct_3 1 Offset 4
1818 %void = OpTypeVoid
1819 %5 = OpTypeFunction %void
1820 %int = OpTypeInt 32 1
1821 %bool = OpTypeBool
1822 %_struct_3 = OpTypeStruct %int %int
1823 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
1824 %_ptr_Function_int = OpTypePointer Function %int
1825 %true = OpConstantTrue %bool
1826 %int_0 = OpConstant %int 0
1827 %int_1 = OpConstant %int 1
1828 %13 = OpConstantNull %_struct_3
1829 %2 = OpFunction %void None %5
1830 %14 = OpLabel
1831 %15 = OpVariable %_ptr_Function_int Function
1832 %16 = OpVariable %_ptr_Function_int Function
1833 %17 = OpVariable %_ptr_Function_int Function
1834 OpStore %15 %int_1
1835 OpStore %17 %int_0
1836 OpSelectionMerge %18 None
1837 OpBranchConditional %true %19 %20
1838 %19 = OpLabel
1839 OpBranch %18
1840 %20 = OpLabel
1841 OpBranch %18
1842 %18 = OpLabel
1843 %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20
1844 OpStore %21 %int_0
1845 %22 = OpLoad %int %15
1846 %23 = OpLoad %int %17
1847 %24 = OpIAdd %int %22 %23
1848 OpReturn
1849 OpFunctionEnd
1850 )";
1851 SinglePassRunAndMatch<SSARewritePass>(text, false);
1852 }
1853
TEST_F(LocalSSAElimTest,VariablePointerTest2)1854 TEST_F(LocalSSAElimTest, VariablePointerTest2) {
1855 // Check that the load of the first variable is still used and that the load
1856 // of the third variable is propagated. The first load has to remain because
1857 // of the store to the variable pointer.
1858 const std::string text = R"(
1859 ; CHECK: [[v1:%\w+]] = OpVariable
1860 ; CHECK: [[v2:%\w+]] = OpVariable
1861 ; CHECK: [[v3:%\w+]] = OpVariable
1862 ; CHECK: [[ld1:%\w+]] = OpLoad %int [[v1]]
1863 ; CHECK: OpIAdd %int [[ld1]] %int_0
1864 OpCapability Shader
1865 OpCapability VariablePointers
1866 %1 = OpExtInstImport "GLSL.std.450"
1867 OpMemoryModel Logical GLSL450
1868 OpEntryPoint GLCompute %2 "main"
1869 OpExecutionMode %2 LocalSize 1 1 1
1870 OpSource GLSL 450
1871 OpMemberDecorate %_struct_3 0 Offset 0
1872 OpMemberDecorate %_struct_3 1 Offset 4
1873 %void = OpTypeVoid
1874 %5 = OpTypeFunction %void
1875 %int = OpTypeInt 32 1
1876 %bool = OpTypeBool
1877 %_struct_3 = OpTypeStruct %int %int
1878 %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
1879 %_ptr_Function_int = OpTypePointer Function %int
1880 %true = OpConstantTrue %bool
1881 %int_0 = OpConstant %int 0
1882 %int_1 = OpConstant %int 1
1883 %13 = OpConstantNull %_struct_3
1884 %2 = OpFunction %void None %5
1885 %14 = OpLabel
1886 %15 = OpVariable %_ptr_Function_int Function
1887 %16 = OpVariable %_ptr_Function_int Function
1888 %17 = OpVariable %_ptr_Function_int Function
1889 OpStore %15 %int_1
1890 OpStore %17 %int_0
1891 OpSelectionMerge %18 None
1892 OpBranchConditional %true %19 %20
1893 %19 = OpLabel
1894 OpBranch %18
1895 %20 = OpLabel
1896 OpBranch %18
1897 %18 = OpLabel
1898 %21 = OpPhi %_ptr_Function_int %15 %19 %16 %20
1899 OpStore %21 %int_0
1900 %22 = OpLoad %int %15
1901 %23 = OpLoad %int %17
1902 %24 = OpIAdd %int %22 %23
1903 OpReturn
1904 OpFunctionEnd
1905 )";
1906 SinglePassRunAndMatch<SSARewritePass>(text, false);
1907 }
1908
TEST_F(LocalSSAElimTest,ChainedTrivialPhis)1909 TEST_F(LocalSSAElimTest, ChainedTrivialPhis) {
1910 // Check that the copy object get the undef value implicitly assigned in the
1911 // entry block.
1912 const std::string text = R"(
1913 ; CHECK: [[undef:%\w+]] = OpUndef %v4float
1914 ; CHECK: OpCopyObject %v4float [[undef]]
1915 OpCapability Shader
1916 %1 = OpExtInstImport "GLSL.std.450"
1917 OpMemoryModel Logical GLSL450
1918 OpEntryPoint GLCompute %2 "main"
1919 OpExecutionMode %2 LocalSize 1 18 6
1920 OpSource ESSL 310
1921 %void = OpTypeVoid
1922 %4 = OpTypeFunction %void
1923 %bool = OpTypeBool
1924 %float = OpTypeFloat 32
1925 %v4float = OpTypeVector %float 4
1926 %_ptr_Function_v4float = OpTypePointer Function %v4float
1927 %2 = OpFunction %void None %4
1928 %9 = OpLabel
1929 %10 = OpVariable %_ptr_Function_v4float Function
1930 OpBranch %11
1931 %11 = OpLabel
1932 OpLoopMerge %12 %13 None
1933 OpBranch %14
1934 %14 = OpLabel
1935 %15 = OpUndef %bool
1936 OpBranchConditional %15 %16 %12
1937 %16 = OpLabel
1938 %17 = OpUndef %bool
1939 OpSelectionMerge %18 None
1940 OpBranchConditional %17 %19 %18
1941 %19 = OpLabel
1942 %20 = OpUndef %bool
1943 OpLoopMerge %21 %22 None
1944 OpBranchConditional %20 %23 %21
1945 %23 = OpLabel
1946 %24 = OpLoad %v4float %10
1947 %25 = OpCopyObject %v4float %24
1948 %26 = OpUndef %bool
1949 OpBranch %22
1950 %22 = OpLabel
1951 OpBranch %19
1952 %21 = OpLabel
1953 OpBranch %12
1954 %18 = OpLabel
1955 OpBranch %13
1956 %13 = OpLabel
1957 OpBranch %11
1958 %12 = OpLabel
1959 %27 = OpLoad %v4float %10
1960 OpReturn
1961 OpFunctionEnd
1962 )";
1963 SinglePassRunAndMatch<SSARewritePass>(text, false);
1964 }
1965
TEST_F(LocalSSAElimTest,Overflowtest1)1966 TEST_F(LocalSSAElimTest, Overflowtest1) {
1967 // Check that the copy object get the undef value implicitly assigned in the
1968 // entry block.
1969 const std::string text = R"(
1970 OpCapability Geometry
1971 OpMemoryModel Logical GLSL450
1972 OpEntryPoint Fragment %4 "P2Mai" %12 %17
1973 OpExecutionMode %4 OriginUpperLeft
1974 %2 = OpTypeVoid
1975 %3 = OpTypeFunction %2
1976 %6 = OpTypeFloat 32
1977 %7 = OpTypeVector %6 4
1978 %11 = OpTypePointer Input %7
1979 %16 = OpTypePointer Output %7
1980 %23 = OpTypePointer Function %7
1981 %12 = OpVariable %11 Input
1982 %17 = OpVariable %16 Output
1983 %4 = OpFunction %2 None %3
1984 %2177 = OpLabel
1985 %4194302 = OpVariable %23 Function
1986 %4194301 = OpLoad %7 %4194302
1987 OpStore %17 %4194301
1988 OpReturn
1989 OpFunctionEnd
1990 )";
1991
1992 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1993
1994 std::vector<Message> messages = {
1995 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1996 SetMessageConsumer(GetTestMessageConsumer(messages));
1997 auto result = SinglePassRunToBinary<SSARewritePass>(text, true);
1998 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1999 }
2000
TEST_F(LocalSSAElimTest,OpConstantNull)2001 TEST_F(LocalSSAElimTest, OpConstantNull) {
2002 const std::string text = R"(
2003 OpCapability Addresses
2004 OpCapability Kernel
2005 OpCapability Int64
2006 OpMemoryModel Physical64 OpenCL
2007 OpEntryPoint Kernel %4 "A"
2008 OpSource OpenCL_C 200000
2009 %2 = OpTypeVoid
2010 %3 = OpTypeFunction %2
2011 %6 = OpTypeInt 32 0
2012 %11 = OpTypePointer CrossWorkgroup %6
2013 %16 = OpConstantNull %11
2014 %20 = OpConstant %6 269484031
2015 %4 = OpFunction %2 None %3
2016 %17 = OpLabel
2017 %18 = OpLoad %6 %16 Aligned 536870912
2018 %19 = OpBitwiseXor %6 %18 %20
2019 OpStore %16 %19 Aligned 536870912
2020 OpReturn
2021 OpFunctionEnd
2022 )";
2023
2024 SinglePassRunToBinary<SSARewritePass>(text, false);
2025 }
2026
TEST_F(LocalSSAElimTest,DebugForLoop)2027 TEST_F(LocalSSAElimTest, DebugForLoop) {
2028 // #version 140
2029 //
2030 // in vec4 BC;
2031 // out float fo;
2032 //
2033 // void main()
2034 // {
2035 // float f = 0.0;
2036 // for (int i=0; i<4; i++) {
2037 // f = f + BC[i];
2038 // }
2039 // fo = f;
2040 // }
2041
2042 const std::string text = R"(
2043 ; CHECK: [[f_name:%\w+]] = OpString "f"
2044 ; CHECK: [[i_name:%\w+]] = OpString "i"
2045 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2046 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2047
2048 ; CHECK: OpStore %f %float_0
2049 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2050 ; CHECK-NEXT: OpStore %i %int_0
2051 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2052
2053 ; CHECK-NOT: DebugDeclare
2054
2055 ; CHECK: [[loop_head:%\w+]] = OpLabel
2056 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
2057 ; CHECK: [[phi1:%\w+]] = OpPhi %int %int_0
2058 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2059 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2060 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2061 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2062
2063 ; CHECK-NEXT: [[loop_body]] = OpLabel
2064 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2065
2066 ; CHECK: [[bb]] = OpLabel
2067 ; CHECK: OpStore %f [[f_val:%\w+]]
2068 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
2069 ; CHECK-NEXT: OpBranch [[loop_cont]]
2070
2071 ; CHECK: [[loop_cont]] = OpLabel
2072 ; CHECK: OpStore %i [[i_val:%\w+]]
2073 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
2074 ; CHECK-NEXT: OpBranch [[loop_head]]
2075
2076 ; CHECK: [[loop_merge]] = OpLabel
2077
2078 OpCapability Shader
2079 %1 = OpExtInstImport "GLSL.std.450"
2080 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2081 OpMemoryModel Logical GLSL450
2082 OpEntryPoint Fragment %main "main" %BC %fo
2083 OpExecutionMode %main OriginUpperLeft
2084 %file_name = OpString "test"
2085 OpSource GLSL 140
2086 %float_name = OpString "float"
2087 %main_name = OpString "main"
2088 %f_name = OpString "f"
2089 %i_name = OpString "i"
2090 OpName %main "main"
2091 OpName %f "f"
2092 OpName %i "i"
2093 OpName %BC "BC"
2094 OpName %fo "fo"
2095 %void = OpTypeVoid
2096 %8 = OpTypeFunction %void
2097 %float = OpTypeFloat 32
2098 %_ptr_Function_float = OpTypePointer Function %float
2099 %float_0 = OpConstant %float 0
2100 %int = OpTypeInt 32 1
2101 %uint = OpTypeInt 32 0
2102 %uint_32 = OpConstant %uint 32
2103 %_ptr_Function_int = OpTypePointer Function %int
2104 %int_0 = OpConstant %int 0
2105 %int_4 = OpConstant %int 4
2106 %bool = OpTypeBool
2107 %v4float = OpTypeVector %float 4
2108 %_ptr_Input_v4float = OpTypePointer Input %v4float
2109 %BC = OpVariable %_ptr_Input_v4float Input
2110 %_ptr_Input_float = OpTypePointer Input %float
2111 %int_1 = OpConstant %int 1
2112 %_ptr_Output_float = OpTypePointer Output %float
2113 %fo = OpVariable %_ptr_Output_float Output
2114 %null_expr = OpExtInst %void %ext DebugExpression
2115 %src = OpExtInst %void %ext DebugSource %file_name
2116 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2117 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2118 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2119 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2120 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2121 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2122 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2123 %main = OpFunction %void None %8
2124 %22 = OpLabel
2125 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2126 %f = OpVariable %_ptr_Function_float Function
2127 %i = OpVariable %_ptr_Function_int Function
2128 OpStore %f %float_0
2129 OpStore %i %int_0
2130 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2131 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2132 OpBranch %23
2133 %23 = OpLabel
2134 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2135 OpLoopMerge %24 %25 None
2136 OpBranch %26
2137 %26 = OpLabel
2138 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2139 %27 = OpLoad %int %i
2140 %28 = OpSLessThan %bool %27 %int_4
2141 OpBranchConditional %28 %29 %24
2142 %29 = OpLabel
2143 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2144 %30 = OpLoad %float %f
2145 %31 = OpLoad %int %i
2146 %32 = OpAccessChain %_ptr_Input_float %BC %31
2147 %33 = OpLoad %float %32
2148 %34 = OpFAdd %float %30 %33
2149 OpStore %f %34
2150 OpBranch %25
2151 %25 = OpLabel
2152 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2153 %35 = OpLoad %int %i
2154 %36 = OpIAdd %int %35 %int_1
2155 OpStore %i %36
2156 OpBranch %23
2157 %24 = OpLabel
2158 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2159 %37 = OpLoad %float %f
2160 OpStore %fo %37
2161 OpReturn
2162 OpFunctionEnd
2163 )";
2164
2165 SinglePassRunAndMatch<SSARewritePass>(text, true);
2166 }
2167
TEST_F(LocalSSAElimTest,ShaderDebugForLoop)2168 TEST_F(LocalSSAElimTest, ShaderDebugForLoop) {
2169 const std::string text = R"(
2170 ; CHECK: [[f_name:%\w+]] = OpString "f"
2171 ; CHECK: [[i_name:%\w+]] = OpString "i"
2172 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2173 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2174
2175 ; CHECK: OpStore %f %float_0
2176 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2177 ; CHECK-NEXT: OpStore %i %int_0
2178 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2179
2180 ; CHECK-NOT: DebugDeclare
2181
2182 ; CHECK: [[loop_head:%\w+]] = OpLabel
2183 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
2184 ; CHECK: [[phi1:%\w+]] = OpPhi %int %int_0
2185 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2186 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2187 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2188 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2189
2190 ; CHECK-NEXT: [[loop_body]] = OpLabel
2191 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2192
2193 ; CHECK: [[bb]] = OpLabel
2194 ; CHECK: OpStore %f [[f_val:%\w+]]
2195 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
2196 ; CHECK-NEXT: OpBranch [[loop_cont]]
2197
2198 ; CHECK: [[loop_cont]] = OpLabel
2199 ; CHECK: OpStore %i [[i_val:%\w+]]
2200 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
2201 ; CHECK-NEXT: OpBranch [[loop_head]]
2202
2203 ; CHECK: [[loop_merge]] = OpLabel
2204
2205 OpCapability Shader
2206 OpExtension "SPV_KHR_non_semantic_info"
2207 %1 = OpExtInstImport "GLSL.std.450"
2208 %ext = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
2209 OpMemoryModel Logical GLSL450
2210 OpEntryPoint Fragment %main "main" %BC %fo
2211 OpExecutionMode %main OriginUpperLeft
2212 %file_name = OpString "test"
2213 OpSource GLSL 140
2214 %float_name = OpString "float"
2215 %main_name = OpString "main"
2216 %f_name = OpString "f"
2217 %i_name = OpString "i"
2218 OpName %main "main"
2219 OpName %f "f"
2220 OpName %i "i"
2221 OpName %BC "BC"
2222 OpName %fo "fo"
2223 %void = OpTypeVoid
2224 %8 = OpTypeFunction %void
2225 %float = OpTypeFloat 32
2226 %_ptr_Function_float = OpTypePointer Function %float
2227 %float_0 = OpConstant %float 0
2228 %int = OpTypeInt 32 1
2229 %uint = OpTypeInt 32 0
2230 %uint_0 = OpConstant %uint 0
2231 %uint_1 = OpConstant %uint 1
2232 %uint_3 = OpConstant %uint 3
2233 %uint_4 = OpConstant %uint 4
2234 %uint_5 = OpConstant %uint 5
2235 %uint_10 = OpConstant %uint 10
2236 %uint_32 = OpConstant %uint 32
2237 %_ptr_Function_int = OpTypePointer Function %int
2238 %int_0 = OpConstant %int 0
2239 %int_4 = OpConstant %int 4
2240 %bool = OpTypeBool
2241 %v4float = OpTypeVector %float 4
2242 %_ptr_Input_v4float = OpTypePointer Input %v4float
2243 %BC = OpVariable %_ptr_Input_v4float Input
2244 %_ptr_Input_float = OpTypePointer Input %float
2245 %int_1 = OpConstant %int 1
2246 %_ptr_Output_float = OpTypePointer Output %float
2247 %fo = OpVariable %_ptr_Output_float Output
2248 %null_expr = OpExtInst %void %ext DebugExpression
2249 %src = OpExtInst %void %ext DebugSource %file_name
2250 %cu = OpExtInst %void %ext DebugCompilationUnit %uint_1 %uint_4 %src %uint_5
2251 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 %uint_3 %uint_0
2252 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf %uint_4
2253 %main_ty = OpExtInst %void %ext DebugTypeFunction %uint_3 %dbg_v4f %dbg_v4f
2254 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src %uint_0 %uint_0 %cu %main_name %uint_3 %uint_10
2255 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src %uint_0 %uint_0 %dbg_main %uint_4
2256 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src %uint_0 %uint_0 %dbg_main %uint_4
2257 %main = OpFunction %void None %8
2258 %22 = OpLabel
2259 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2260 %f = OpVariable %_ptr_Function_float Function
2261 %i = OpVariable %_ptr_Function_int Function
2262 OpStore %f %float_0
2263 OpStore %i %int_0
2264 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2265 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2266 OpBranch %23
2267 %23 = OpLabel
2268 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2269 OpLoopMerge %24 %25 None
2270 OpBranch %26
2271 %26 = OpLabel
2272 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2273 %27 = OpLoad %int %i
2274 %28 = OpSLessThan %bool %27 %int_4
2275 OpBranchConditional %28 %29 %24
2276 %29 = OpLabel
2277 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2278 %30 = OpLoad %float %f
2279 %31 = OpLoad %int %i
2280 %32 = OpAccessChain %_ptr_Input_float %BC %31
2281 %33 = OpLoad %float %32
2282 %34 = OpFAdd %float %30 %33
2283 OpStore %f %34
2284 OpBranch %25
2285 %25 = OpLabel
2286 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2287 %35 = OpLoad %int %i
2288 %36 = OpIAdd %int %35 %int_1
2289 OpStore %i %36
2290 OpBranch %23
2291 %24 = OpLabel
2292 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2293 %37 = OpLoad %float %f
2294 OpStore %fo %37
2295 OpReturn
2296 OpFunctionEnd
2297 )";
2298
2299 SinglePassRunAndMatch<SSARewritePass>(text, true);
2300 }
2301
TEST_F(LocalSSAElimTest,AddDebugValueForFunctionParameterWithPhi)2302 TEST_F(LocalSSAElimTest, AddDebugValueForFunctionParameterWithPhi) {
2303 // Test the distribution of DebugValue for a parameter of an inlined function
2304 // and the visibility of Phi instruction. The ssa-rewrite pass must add
2305 // DebugValue for the value assignment of function argument even when it is an
2306 // inlined function. It has to check the visibility Phi through all its value
2307 // operands. See the DebugValue for "int i" of "foo()" in the following code.
2308 //
2309 // struct VS_OUTPUT {
2310 // float4 pos : SV_POSITION;
2311 // float4 color : COLOR;
2312 // };
2313 //
2314 // float4 foo(int i, float4 pos) {
2315 // while (i < pos.x) {
2316 // pos = pos.x + i;
2317 // ++i;
2318 // }
2319 // return pos;
2320 // }
2321 //
2322 // VS_OUTPUT main(float4 pos : POSITION,
2323 // float4 color : COLOR) {
2324 // VS_OUTPUT vout;
2325 // vout.pos = foo(4, pos);
2326 // vout.color = color;
2327 // return vout;
2328 // }
2329 const std::string text = R"(
2330 OpCapability Shader
2331 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
2332 OpMemoryModel Logical GLSL450
2333 OpEntryPoint Vertex %main "main" %in_var_POSITION %in_var_COLOR %gl_Position %out_var_COLOR
2334 %7 = OpString "vertex.hlsl"
2335 %8 = OpString "float"
2336 %9 = OpString "VS_OUTPUT"
2337 %10 = OpString "color"
2338 %11 = OpString "pos"
2339 %12 = OpString "int"
2340 %13 = OpString "foo"
2341 %14 = OpString ""
2342 %15 = OpString "i"
2343 %16 = OpString "main"
2344 %17 = OpString "vout"
2345 OpName %in_var_POSITION "in.var.POSITION"
2346 OpName %in_var_COLOR "in.var.COLOR"
2347 OpName %out_var_COLOR "out.var.COLOR"
2348 OpName %main "main"
2349 OpName %param_var_pos "param.var.pos"
2350 OpName %param_var_color "param.var.color"
2351 OpName %VS_OUTPUT "VS_OUTPUT"
2352 OpMemberName %VS_OUTPUT 0 "pos"
2353 OpMemberName %VS_OUTPUT 1 "color"
2354 OpDecorate %gl_Position BuiltIn Position
2355 OpDecorate %in_var_POSITION Location 0
2356 OpDecorate %in_var_COLOR Location 1
2357 OpDecorate %out_var_COLOR Location 0
2358 %int = OpTypeInt 32 1
2359 %int_4 = OpConstant %int 4
2360 %int_0 = OpConstant %int 0
2361 %int_1 = OpConstant %int 1
2362 %uint = OpTypeInt 32 0
2363 %uint_32 = OpConstant %uint 32
2364 %float = OpTypeFloat 32
2365 %v4float = OpTypeVector %float 4
2366 %_ptr_Input_v4float = OpTypePointer Input %v4float
2367 %_ptr_Output_v4float = OpTypePointer Output %v4float
2368 %void = OpTypeVoid
2369 %uint_256 = OpConstant %uint 256
2370 %uint_128 = OpConstant %uint 128
2371 %uint_0 = OpConstant %uint 0
2372 %50 = OpTypeFunction %void
2373 %_ptr_Function_v4float = OpTypePointer Function %v4float
2374 %VS_OUTPUT = OpTypeStruct %v4float %v4float
2375 %_ptr_Function_int = OpTypePointer Function %int
2376 %_ptr_Function_float = OpTypePointer Function %float
2377 %bool = OpTypeBool
2378 %in_var_POSITION = OpVariable %_ptr_Input_v4float Input
2379 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
2380 %gl_Position = OpVariable %_ptr_Output_v4float Output
2381 %out_var_COLOR = OpVariable %_ptr_Output_v4float Output
2382 %156 = OpExtInst %void %1 DebugInfoNone
2383 %77 = OpExtInst %void %1 DebugExpression
2384 %58 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
2385 %59 = OpExtInst %void %1 DebugTypeVector %58 4
2386 %60 = OpExtInst %void %1 DebugSource %7
2387 %61 = OpExtInst %void %1 DebugCompilationUnit 1 4 %60 HLSL
2388 %62 = OpExtInst %void %1 DebugTypeComposite %9 Structure %60 1 8 %61 %9 %uint_256 FlagIsProtected|FlagIsPrivate %63 %64
2389 %64 = OpExtInst %void %1 DebugTypeMember %10 %59 %60 3 10 %62 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
2390 %63 = OpExtInst %void %1 DebugTypeMember %11 %59 %60 2 10 %62 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
2391 %65 = OpExtInst %void %1 DebugTypeBasic %12 %uint_32 Signed
2392 %66 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %59 %65 %59
2393 %67 = OpExtInst %void %1 DebugFunction %13 %66 %60 6 1 %61 %14 FlagIsProtected|FlagIsPrivate 6 %156
2394 %68 = OpExtInst %void %1 DebugLexicalBlock %60 6 31 %67
2395 %69 = OpExtInst %void %1 DebugLexicalBlock %60 7 21 %68
2396 %70 = OpExtInst %void %1 DebugLocalVariable %11 %59 %60 6 26 %67 FlagIsLocal 2
2397
2398 ; CHECK: [[color_name:%\w+]] = OpString "color"
2399 ; CHECK: [[pos_name:%\w+]] = OpString "pos"
2400 ; CHECK: [[i_name:%\w+]] = OpString "i"
2401 ; CHECK: [[null_expr:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugExpression
2402 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]] {{%\w+}} {{%\w+}} 6 16 {{%\w+}} FlagIsLocal 1
2403 ; CHECK: [[dbg_color:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[color_name]] {{%\w+}} {{%\w+}} 15 23
2404 ; CHECK: [[dbg_pos:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[pos_name]] {{%\w+}} {{%\w+}} 14 23
2405 %71 = OpExtInst %void %1 DebugLocalVariable %15 %65 %60 6 16 %67 FlagIsLocal 1
2406 %72 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %62 %59 %59
2407 %73 = OpExtInst %void %1 DebugFunction %16 %72 %60 14 1 %61 %14 FlagIsProtected|FlagIsPrivate 15 %156
2408 %74 = OpExtInst %void %1 DebugLexicalBlock %60 15 38 %73
2409 %75 = OpExtInst %void %1 DebugLocalVariable %17 %62 %60 16 13 %74 FlagIsLocal
2410 %76 = OpExtInst %void %1 DebugLocalVariable %10 %59 %60 15 23 %73 FlagIsLocal 2
2411 %78 = OpExtInst %void %1 DebugLocalVariable %11 %59 %60 14 23 %73 FlagIsLocal 1
2412 %155 = OpExtInst %void %1 DebugInlinedAt 17 %74
2413 %main = OpFunction %void None %50
2414 %79 = OpLabel
2415 %168 = OpExtInst %void %1 DebugScope %74
2416
2417 ; CHECK: [[i:%\w+]] = OpVariable %_ptr_Function_int Function
2418 %120 = OpVariable %_ptr_Function_int Function
2419 %121 = OpVariable %_ptr_Function_v4float Function
2420 %169 = OpExtInst %void %1 DebugNoScope
2421 %param_var_pos = OpVariable %_ptr_Function_v4float Function
2422 %param_var_color = OpVariable %_ptr_Function_v4float Function
2423 OpLine %7 100 105
2424 %80 = OpLoad %v4float %in_var_POSITION
2425 OpStore %param_var_pos %80
2426 OpNoLine
2427 OpLine %7 200 205
2428 %81 = OpLoad %v4float %in_var_COLOR
2429 OpStore %param_var_color %81
2430 OpNoLine
2431 %170 = OpExtInst %void %1 DebugScope %73
2432
2433 ; CHECK: OpLine {{%\w+}} 100 105
2434 ; CHECK: DebugValue [[dbg_pos]]
2435 %124 = OpExtInst %void %1 DebugDeclare %78 %param_var_pos %77
2436 ; CHECK: OpLine {{%\w+}} 200 205
2437 ; CHECK: DebugValue [[dbg_color]]
2438 %125 = OpExtInst %void %1 DebugDeclare %76 %param_var_color %77
2439
2440 %171 = OpExtInst %void %1 DebugScope %74
2441 OpLine %7 17 18
2442
2443 ; CHECK: OpStore {{%\w+}} %int_4
2444 ; CHECK: DebugValue [[dbg_i]] %int_4 [[null_expr]]
2445 OpStore %120 %int_4
2446 OpStore %121 %80
2447 %172 = OpExtInst %void %1 DebugScope %67 %155
2448 %135 = OpExtInst %void %1 DebugDeclare %71 %120 %77
2449 %136 = OpExtInst %void %1 DebugDeclare %70 %121 %77
2450 %173 = OpExtInst %void %1 DebugScope %68 %155
2451 OpLine %7 7 3
2452 OpBranch %137
2453 %174 = OpExtInst %void %1 DebugNoScope
2454 %137 = OpLabel
2455
2456 ; CHECK: [[phi:%\w+]] = OpPhi %int %int_4
2457 ; CHECK: DebugValue [[dbg_i]] [[phi]] [[null_expr]]
2458 %175 = OpExtInst %void %1 DebugScope %68 %155
2459 OpLine %7 7 10
2460 %138 = OpLoad %int %120
2461 %139 = OpConvertSToF %float %138
2462 OpLine %7 7 14
2463 %140 = OpAccessChain %_ptr_Function_float %121 %int_0
2464 %141 = OpLoad %float %140
2465 OpLine %7 7 12
2466 %142 = OpFOrdLessThan %bool %139 %141
2467 OpLine %7 7 3
2468 %176 = OpExtInst %void %1 DebugNoScope
2469 OpLoopMerge %153 %152 None
2470 OpBranchConditional %142 %143 %153
2471 %177 = OpExtInst %void %1 DebugNoScope
2472 %143 = OpLabel
2473 %178 = OpExtInst %void %1 DebugScope %69 %155
2474 OpLine %7 8 11
2475 %144 = OpAccessChain %_ptr_Function_float %121 %int_0
2476 %145 = OpLoad %float %144
2477 OpLine %7 8 19
2478 %146 = OpLoad %int %120
2479 %147 = OpConvertSToF %float %146
2480 OpLine %7 8 17
2481 %148 = OpFAdd %float %145 %147
2482 OpLine %7 8 11
2483 %149 = OpCompositeConstruct %v4float %148 %148 %148 %148
2484 OpLine %7 8 5
2485 OpStore %121 %149
2486 OpLine %7 9 5
2487 %151 = OpIAdd %int %146 %int_1
2488 OpLine %7 9 7
2489
2490 ; CHECK: OpStore [[i]] [[value:%\w+]]
2491 ; CHECK: DebugValue [[dbg_i]] [[value]] [[null_expr]]
2492 OpStore %120 %151
2493 %179 = OpExtInst %void %1 DebugScope %68 %155
2494 OpLine %7 10 3
2495 OpBranch %152
2496 %180 = OpExtInst %void %1 DebugNoScope
2497 %152 = OpLabel
2498 %181 = OpExtInst %void %1 DebugScope %68 %155
2499 OpBranch %137
2500 %182 = OpExtInst %void %1 DebugNoScope
2501 %153 = OpLabel
2502 %183 = OpExtInst %void %1 DebugScope %68 %155
2503 OpLine %7 11 10
2504 %154 = OpLoad %v4float %121
2505 %184 = OpExtInst %void %1 DebugScope %74
2506 %167 = OpExtInst %void %1 DebugValue %75 %154 %77 %int_0
2507 %166 = OpExtInst %void %1 DebugValue %75 %81 %77 %int_1
2508 OpLine %7 19 10
2509 %165 = OpCompositeConstruct %VS_OUTPUT %154 %81
2510 %185 = OpExtInst %void %1 DebugNoScope
2511 %83 = OpCompositeExtract %v4float %165 0
2512 OpStore %gl_Position %83
2513 %84 = OpCompositeExtract %v4float %165 1
2514 OpStore %out_var_COLOR %84
2515 OpReturn
2516 OpFunctionEnd
2517 )";
2518
2519 SinglePassRunAndMatch<SSARewritePass>(text, true);
2520 }
2521
TEST_F(LocalSSAElimTest,DebugValueWithIndexesInForLoop)2522 TEST_F(LocalSSAElimTest, DebugValueWithIndexesInForLoop) {
2523 // #version 140
2524 //
2525 // in vec4 BC;
2526 // out float fo;
2527 //
2528 // struct T {
2529 // float a;
2530 // float f;
2531 // };
2532 //
2533 // struct value {
2534 // int x;
2535 // int y;
2536 // T z;
2537 // };
2538 //
2539 // void main()
2540 // {
2541 // value v;
2542 // v.z.f = 0.0;
2543 // for (int i=0; i<4; i++) {
2544 // v.z.f = v.z.f + BC[i];
2545 // }
2546 // fo = v.z.f;
2547 // }
2548
2549 const std::string text = R"(
2550 ; CHECK: [[f_name:%\w+]] = OpString "f"
2551 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2552
2553 ; CHECK: OpStore %f %float_0
2554 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0 [[null_expr:%\d+]] %int_2 %int_1
2555
2556 ; CHECK-NOT: DebugDeclare
2557
2558 ; CHECK: [[loop_head:%\w+]] = OpLabel
2559 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
2560 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]] [[null_expr]] %int_2 %int_1
2561 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2562 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2563
2564 ; CHECK-NEXT: [[loop_body]] = OpLabel
2565 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2566
2567 ; CHECK: [[bb]] = OpLabel
2568 ; CHECK: OpStore %f [[f_val:%\w+]]
2569 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]] [[null_expr]] %int_2 %int_1
2570 ; CHECK-NEXT: OpBranch [[loop_cont]]
2571
2572 ; CHECK: [[loop_cont]] = OpLabel
2573 ; CHECK: OpBranch [[loop_head]]
2574
2575 ; CHECK: [[loop_merge]] = OpLabel
2576
2577 OpCapability Shader
2578 %1 = OpExtInstImport "GLSL.std.450"
2579 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2580 OpMemoryModel Logical GLSL450
2581 OpEntryPoint Fragment %main "main" %BC %fo
2582 OpExecutionMode %main OriginUpperLeft
2583 %file_name = OpString "test"
2584 OpSource GLSL 140
2585 %float_name = OpString "float"
2586 %main_name = OpString "main"
2587 %f_name = OpString "f"
2588 %i_name = OpString "i"
2589 OpName %main "main"
2590 OpName %f "f"
2591 OpName %i "i"
2592 OpName %BC "BC"
2593 OpName %fo "fo"
2594 %void = OpTypeVoid
2595 %8 = OpTypeFunction %void
2596 %float = OpTypeFloat 32
2597 %_ptr_Function_float = OpTypePointer Function %float
2598 %float_0 = OpConstant %float 0
2599 %int = OpTypeInt 32 1
2600 %uint = OpTypeInt 32 0
2601 %uint_32 = OpConstant %uint 32
2602 %_ptr_Function_int = OpTypePointer Function %int
2603 %int_0 = OpConstant %int 0
2604 %int_4 = OpConstant %int 4
2605 %bool = OpTypeBool
2606 %v4float = OpTypeVector %float 4
2607 %_ptr_Input_v4float = OpTypePointer Input %v4float
2608 %BC = OpVariable %_ptr_Input_v4float Input
2609 %_ptr_Input_float = OpTypePointer Input %float
2610 %int_1 = OpConstant %int 1
2611 %int_2 = OpConstant %int 2
2612 %_ptr_Output_float = OpTypePointer Output %float
2613 %fo = OpVariable %_ptr_Output_float Output
2614 %deref = OpExtInst %void %ext DebugOperation Deref
2615 %null_expr = OpExtInst %void %ext DebugExpression
2616 %deref_expr = OpExtInst %void %ext DebugExpression %deref
2617 %src = OpExtInst %void %ext DebugSource %file_name
2618 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2619 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2620 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2621 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2622 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2623 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2624 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2625 %main = OpFunction %void None %8
2626 %22 = OpLabel
2627 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2628 %f = OpVariable %_ptr_Function_float Function
2629 %i = OpVariable %_ptr_Function_int Function
2630 OpStore %f %float_0
2631 OpStore %i %int_0
2632 %decl0 = OpExtInst %void %ext DebugValue %dbg_f %f %deref_expr %int_2 %int_1
2633 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2634 OpBranch %23
2635 %23 = OpLabel
2636 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2637 OpLoopMerge %24 %25 None
2638 OpBranch %26
2639 %26 = OpLabel
2640 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2641 %27 = OpLoad %int %i
2642 %28 = OpSLessThan %bool %27 %int_4
2643 OpBranchConditional %28 %29 %24
2644 %29 = OpLabel
2645 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2646 %30 = OpLoad %float %f
2647 %31 = OpLoad %int %i
2648 %32 = OpAccessChain %_ptr_Input_float %BC %31
2649 %33 = OpLoad %float %32
2650 %34 = OpFAdd %float %30 %33
2651 OpStore %f %34
2652 OpBranch %25
2653 %25 = OpLabel
2654 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2655 %35 = OpLoad %int %i
2656 %36 = OpIAdd %int %35 %int_1
2657 OpStore %i %36
2658 OpBranch %23
2659 %24 = OpLabel
2660 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2661 %37 = OpLoad %float %f
2662 OpStore %fo %37
2663 OpReturn
2664 OpFunctionEnd
2665 )";
2666
2667 SinglePassRunAndMatch<SSARewritePass>(text, true);
2668 }
2669
TEST_F(LocalSSAElimTest,PartiallyKillDebugDeclare)2670 TEST_F(LocalSSAElimTest, PartiallyKillDebugDeclare) {
2671 // For a reference variable e.g., int i in the following example,
2672 // we do not propagate DebugValue for a store or phi instruction
2673 // out of the variable's scope. In that case, we should not remove
2674 // DebugDeclare for the variable that we did not add its DebugValue.
2675 //
2676 // #version 140
2677 //
2678 // in vec4 BC;
2679 // out float fo;
2680 //
2681 // int j;
2682 // void main()
2683 // {
2684 // float f = 0.0;
2685 // for (j=0; j<4; j++) {
2686 // int& i = j;
2687 // f = f + BC[i];
2688 // }
2689 // fo = f;
2690 // }
2691
2692 const std::string text = R"(
2693 ; CHECK: [[f_name:%\w+]] = OpString "f"
2694 ; CHECK: [[i_name:%\w+]] = OpString "i"
2695 ; CHECK: [[fn:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugFunction
2696 ; CHECK: [[bb:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2697 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]] {{%\w+}} {{%\w+}} 0 0 [[fn]]
2698 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]] {{%\w+}} {{%\w+}} 0 0 [[bb]]
2699
2700 ; CHECK: OpStore %f %float_0
2701 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2702 ; CHECK-NOT: DebugDeclare [[dbg_f]]
2703 ; CHECK: OpExtInst %void [[ext]] DebugDeclare [[dbg_i]] %j
2704
2705 OpCapability Shader
2706 %1 = OpExtInstImport "GLSL.std.450"
2707 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2708 OpMemoryModel Logical GLSL450
2709 OpEntryPoint Fragment %main "main" %BC %fo
2710 OpExecutionMode %main OriginUpperLeft
2711 %file_name = OpString "test"
2712 OpSource GLSL 140
2713 %float_name = OpString "float"
2714 %main_name = OpString "main"
2715 %f_name = OpString "f"
2716 %i_name = OpString "i"
2717 %j_name = OpString "j"
2718 OpName %main "main"
2719 OpName %f "f"
2720 OpName %j "j"
2721 OpName %BC "BC"
2722 OpName %fo "fo"
2723 %void = OpTypeVoid
2724 %8 = OpTypeFunction %void
2725 %float = OpTypeFloat 32
2726 %_ptr_Function_float = OpTypePointer Function %float
2727 %float_0 = OpConstant %float 0
2728 %int = OpTypeInt 32 1
2729 %uint = OpTypeInt 32 0
2730 %uint_32 = OpConstant %uint 32
2731 %_ptr_Function_int = OpTypePointer Function %int
2732 %_ptr_Private_int = OpTypePointer Private %int
2733 %int_0 = OpConstant %int 0
2734 %int_4 = OpConstant %int 4
2735 %bool = OpTypeBool
2736 %v4float = OpTypeVector %float 4
2737 %_ptr_Input_v4float = OpTypePointer Input %v4float
2738 %BC = OpVariable %_ptr_Input_v4float Input
2739 %_ptr_Input_float = OpTypePointer Input %float
2740 %int_1 = OpConstant %int 1
2741 %_ptr_Output_float = OpTypePointer Output %float
2742 %fo = OpVariable %_ptr_Output_float Output
2743 %j = OpVariable %_ptr_Private_int Private
2744 %null_expr = OpExtInst %void %ext DebugExpression
2745 %src = OpExtInst %void %ext DebugSource %file_name
2746 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2747 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2748 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2749 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2750 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2751 %bb = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
2752 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2753 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %bb FlagIsLocal
2754 %dbg_j = OpExtInst %void %ext DebugGlobalVariable %j_name %dbg_v4f %src 0 0 %dbg_main %j_name %j FlagIsPrivate
2755 %main = OpFunction %void None %8
2756 %22 = OpLabel
2757 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2758 %f = OpVariable %_ptr_Function_float Function
2759 OpStore %f %float_0
2760 OpStore %j %int_0
2761 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2762 OpBranch %23
2763 %23 = OpLabel
2764 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2765 OpLoopMerge %24 %25 None
2766 OpBranch %26
2767 %26 = OpLabel
2768 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2769 %27 = OpLoad %int %j
2770 %28 = OpSLessThan %bool %27 %int_4
2771 OpBranchConditional %28 %29 %24
2772 %29 = OpLabel
2773 %s3 = OpExtInst %void %ext DebugScope %bb
2774 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %j %null_expr
2775 %30 = OpLoad %float %f
2776 %31 = OpLoad %int %j
2777 %32 = OpAccessChain %_ptr_Input_float %BC %31
2778 %33 = OpLoad %float %32
2779 %34 = OpFAdd %float %30 %33
2780 OpStore %f %34
2781 OpBranch %25
2782 %25 = OpLabel
2783 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2784 %35 = OpLoad %int %j
2785 %36 = OpIAdd %int %35 %int_1
2786 OpStore %j %36
2787 OpBranch %23
2788 %24 = OpLabel
2789 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2790 %37 = OpLoad %float %f
2791 OpStore %fo %37
2792 OpReturn
2793 OpFunctionEnd
2794 )";
2795
2796 SinglePassRunAndMatch<SSARewritePass>(text, true);
2797 }
2798
TEST_F(LocalSSAElimTest,DebugValueForReferenceVariable)2799 TEST_F(LocalSSAElimTest, DebugValueForReferenceVariable) {
2800 // #version 140
2801 //
2802 // in vec4 BC;
2803 // out float fo;
2804 //
2805 // void main()
2806 // {
2807 // float f = 0.0;
2808 // float& x = f;
2809 // for (int i=0; i<4; i++) {
2810 // x = x + BC[i];
2811 // }
2812 // fo = f;
2813 // }
2814
2815 const std::string text = R"(
2816 ; CHECK: [[f_name:%\w+]] = OpString "f"
2817 ; CHECK: [[i_name:%\w+]] = OpString "i"
2818 ; CHECK: [[x_name:%\w+]] = OpString "x"
2819 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2820 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2821 ; CHECK: [[dbg_x:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[x_name]]
2822
2823 ; CHECK: OpStore %f %float_0
2824 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2825 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] %float_0
2826 ; CHECK: OpStore %i %int_0
2827 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2828
2829 ; CHECK-NOT: DebugDeclare
2830
2831 ; CHECK: [[loop_head:%\w+]] = OpLabel
2832 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
2833 ; CHECK: [[phi1:%\w+]] = OpPhi %int %int_0
2834 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2835 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[phi0]]
2836 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2837 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2838 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2839
2840 ; CHECK: [[loop_body]] = OpLabel
2841 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2842
2843 ; CHECK: [[bb]] = OpLabel
2844 ; CHECK: OpStore %f [[f_val:%\w+]]
2845 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
2846 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[f_val]]
2847 ; CHECK: OpBranch [[loop_cont]]
2848
2849 ; CHECK: [[loop_cont]] = OpLabel
2850 ; CHECK: OpStore %i [[i_val:%\w+]]
2851 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
2852 ; CHECK-NEXT: OpBranch [[loop_head]]
2853
2854 ; CHECK: [[loop_merge]] = OpLabel
2855
2856 OpCapability Shader
2857 %1 = OpExtInstImport "GLSL.std.450"
2858 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2859 OpMemoryModel Logical GLSL450
2860 OpEntryPoint Fragment %main "main" %BC %fo
2861 OpExecutionMode %main OriginUpperLeft
2862 %file_name = OpString "test"
2863 OpSource GLSL 140
2864 %float_name = OpString "float"
2865 %main_name = OpString "main"
2866 %f_name = OpString "f"
2867 %i_name = OpString "i"
2868 %x_name = OpString "x"
2869 OpName %main "main"
2870 OpName %f "f"
2871 OpName %i "i"
2872 OpName %BC "BC"
2873 OpName %fo "fo"
2874 %void = OpTypeVoid
2875 %8 = OpTypeFunction %void
2876 %float = OpTypeFloat 32
2877 %_ptr_Function_float = OpTypePointer Function %float
2878 %float_0 = OpConstant %float 0
2879 %int = OpTypeInt 32 1
2880 %uint = OpTypeInt 32 0
2881 %uint_32 = OpConstant %uint 32
2882 %_ptr_Function_int = OpTypePointer Function %int
2883 %int_0 = OpConstant %int 0
2884 %int_4 = OpConstant %int 4
2885 %bool = OpTypeBool
2886 %v4float = OpTypeVector %float 4
2887 %_ptr_Input_v4float = OpTypePointer Input %v4float
2888 %BC = OpVariable %_ptr_Input_v4float Input
2889 %_ptr_Input_float = OpTypePointer Input %float
2890 %int_1 = OpConstant %int 1
2891 %_ptr_Output_float = OpTypePointer Output %float
2892 %fo = OpVariable %_ptr_Output_float Output
2893 %null_expr = OpExtInst %void %ext DebugExpression
2894 %src = OpExtInst %void %ext DebugSource %file_name
2895 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2896 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2897 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2898 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2899 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2900 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2901 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
2902 %dbg_x = OpExtInst %void %ext DebugLocalVariable %x_name %dbg_v4f %src 2 0 %dbg_main FlagIsLocal
2903 %main = OpFunction %void None %8
2904 %22 = OpLabel
2905 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2906 %f = OpVariable %_ptr_Function_float Function
2907 %i = OpVariable %_ptr_Function_int Function
2908 OpStore %f %float_0
2909 OpStore %i %int_0
2910 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2911 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2912 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_x %f %null_expr
2913 OpBranch %23
2914 %23 = OpLabel
2915 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2916 OpLoopMerge %24 %25 None
2917 OpBranch %26
2918 %26 = OpLabel
2919 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2920 %27 = OpLoad %int %i
2921 %28 = OpSLessThan %bool %27 %int_4
2922 OpBranchConditional %28 %29 %24
2923 %29 = OpLabel
2924 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2925 %30 = OpLoad %float %f
2926 %31 = OpLoad %int %i
2927 %32 = OpAccessChain %_ptr_Input_float %BC %31
2928 %33 = OpLoad %float %32
2929 %34 = OpFAdd %float %30 %33
2930 OpStore %f %34
2931 OpBranch %25
2932 %25 = OpLabel
2933 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2934 %35 = OpLoad %int %i
2935 %36 = OpIAdd %int %35 %int_1
2936 OpStore %i %36
2937 OpBranch %23
2938 %24 = OpLabel
2939 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2940 %37 = OpLoad %float %f
2941 OpStore %fo %37
2942 OpReturn
2943 OpFunctionEnd
2944 )";
2945
2946 SinglePassRunAndMatch<SSARewritePass>(text, true);
2947 }
2948
TEST_F(LocalSSAElimTest,DebugValueForReferenceVariableInBB)2949 TEST_F(LocalSSAElimTest, DebugValueForReferenceVariableInBB) {
2950 // #version 140
2951 //
2952 // in vec4 BC;
2953 // out float fo;
2954 //
2955 // void main()
2956 // {
2957 // float f = 0.0;
2958 // for (int i=0; i<4; i++) {
2959 // float& x = f;
2960 // x = x + BC[i];
2961 // {
2962 // x = x + BC[i];
2963 // }
2964 // }
2965 // fo = f;
2966 // }
2967
2968 const std::string text = R"(
2969 ; CHECK: [[f_name:%\w+]] = OpString "f"
2970 ; CHECK: [[i_name:%\w+]] = OpString "i"
2971 ; CHECK: [[x_name:%\w+]] = OpString "x"
2972 ; CHECK: [[dbg_main:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugFunction
2973 ; CHECK: [[dbg_bb:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2974 ; CHECK: [[dbg_bb_child:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2975 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]]
2976 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2977 ; CHECK: [[dbg_x:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[x_name]]
2978
2979 ; CHECK: OpExtInst %void [[ext]] DebugScope [[dbg_main]]
2980 ; CHECK: OpStore %f %float_0
2981 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2982 ; CHECK-NEXT: OpStore %i %int_0
2983 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2984
2985 ; CHECK-NOT: DebugDeclare
2986
2987 ; CHECK: [[loop_head:%\w+]] = OpLabel
2988 ; CHECK: OpExtInst %void [[ext]] DebugScope [[dbg_main]]
2989 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
2990 ; CHECK: [[phi1:%\w+]] = OpPhi %int %int_0
2991 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2992 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[phi0]]
2993 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2994 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2995 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2996
2997 ; CHECK-NEXT: [[loop_body]] = OpLabel
2998 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2999
3000 ; CHECK: [[bb]] = OpLabel
3001 ; CHECK: OpExtInst %void [[ext]] DebugScope [[dbg_bb]]
3002 ; CHECK: OpStore %f [[f_val:%\w+]]
3003 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
3004 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[f_val]]
3005 ; CHECK: OpBranch [[bb_child:%\w+]]
3006
3007 ; CHECK: [[bb_child]] = OpLabel
3008 ; CHECK: OpExtInst %void [[ext]] DebugScope [[dbg_bb_child]]
3009 ; CHECK: OpStore %f [[new_f_val:%\w+]]
3010 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[new_f_val]]
3011 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[new_f_val]]
3012 ; CHECK: OpBranch [[loop_cont]]
3013
3014 ; CHECK: [[loop_cont]] = OpLabel
3015 ; CHECK: OpStore %i [[i_val:%\w+]]
3016 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
3017 ; CHECK-NEXT: OpBranch [[loop_head]]
3018
3019 ; CHECK: [[loop_merge]] = OpLabel
3020
3021 OpCapability Shader
3022 %1 = OpExtInstImport "GLSL.std.450"
3023 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3024 OpMemoryModel Logical GLSL450
3025 OpEntryPoint Fragment %main "main" %BC %fo
3026 OpExecutionMode %main OriginUpperLeft
3027 %file_name = OpString "test"
3028 OpSource GLSL 140
3029 %float_name = OpString "float"
3030 %main_name = OpString "main"
3031 %f_name = OpString "f"
3032 %i_name = OpString "i"
3033 %x_name = OpString "x"
3034 OpName %main "main"
3035 OpName %f "f"
3036 OpName %i "i"
3037 OpName %BC "BC"
3038 OpName %fo "fo"
3039 %void = OpTypeVoid
3040 %8 = OpTypeFunction %void
3041 %float = OpTypeFloat 32
3042 %_ptr_Function_float = OpTypePointer Function %float
3043 %float_0 = OpConstant %float 0
3044 %int = OpTypeInt 32 1
3045 %uint = OpTypeInt 32 0
3046 %uint_32 = OpConstant %uint 32
3047 %_ptr_Function_int = OpTypePointer Function %int
3048 %int_0 = OpConstant %int 0
3049 %int_4 = OpConstant %int 4
3050 %bool = OpTypeBool
3051 %v4float = OpTypeVector %float 4
3052 %_ptr_Input_v4float = OpTypePointer Input %v4float
3053 %BC = OpVariable %_ptr_Input_v4float Input
3054 %_ptr_Input_float = OpTypePointer Input %float
3055 %int_1 = OpConstant %int 1
3056 %_ptr_Output_float = OpTypePointer Output %float
3057 %fo = OpVariable %_ptr_Output_float Output
3058 %null_expr = OpExtInst %void %ext DebugExpression
3059 %src = OpExtInst %void %ext DebugSource %file_name
3060 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3061 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3062 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
3063 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
3064 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3065 %bb = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
3066 %bb_child = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %bb
3067 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
3068 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
3069 %dbg_x = OpExtInst %void %ext DebugLocalVariable %x_name %dbg_v4f %src 2 0 %bb FlagIsLocal
3070 %main = OpFunction %void None %8
3071 %22 = OpLabel
3072 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3073 %f = OpVariable %_ptr_Function_float Function
3074 %i = OpVariable %_ptr_Function_int Function
3075 OpStore %f %float_0
3076 OpStore %i %int_0
3077 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
3078 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
3079 OpBranch %23
3080 %23 = OpLabel
3081 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3082 OpLoopMerge %24 %25 None
3083 OpBranch %26
3084 %26 = OpLabel
3085 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3086 %27 = OpLoad %int %i
3087 %28 = OpSLessThan %bool %27 %int_4
3088 OpBranchConditional %28 %29 %24
3089 %29 = OpLabel
3090 %scope = OpExtInst %void %ext DebugScope %bb
3091 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_x %f %null_expr
3092 %30 = OpLoad %float %f
3093 %31 = OpLoad %int %i
3094 %32 = OpAccessChain %_ptr_Input_float %BC %31
3095 %33 = OpLoad %float %32
3096 %34 = OpFAdd %float %30 %33
3097 OpStore %f %34
3098 OpBranch %38
3099 %38 = OpLabel
3100 %child_scope = OpExtInst %void %ext DebugScope %bb_child
3101 %39 = OpLoad %float %f
3102 %40 = OpFAdd %float %39 %33
3103 OpStore %f %40
3104 OpBranch %25
3105 %25 = OpLabel
3106 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3107 %35 = OpLoad %int %i
3108 %36 = OpIAdd %int %35 %int_1
3109 OpStore %i %36
3110 OpBranch %23
3111 %24 = OpLabel
3112 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3113 %37 = OpLoad %float %f
3114 OpStore %fo %37
3115 OpReturn
3116 OpFunctionEnd
3117 )";
3118
3119 SinglePassRunAndMatch<SSARewritePass>(text, true);
3120 }
3121
TEST_F(LocalSSAElimTest,DebugForLoopUseDebugValueInsteadOfDebugDeclare)3122 TEST_F(LocalSSAElimTest, DebugForLoopUseDebugValueInsteadOfDebugDeclare) {
3123 // #version 140
3124 //
3125 // in vec4 BC;
3126 // out float fo;
3127 //
3128 // struct S {
3129 // float f;
3130 // int i;
3131 // };
3132 //
3133 // void main()
3134 // {
3135 // S foo = {0.0, 0};
3136 // for (; foo.i<4; foo.i++) {
3137 // foo.f = foo.f + BC[foo.i];
3138 // }
3139 // fo = foo.f;
3140 // }
3141
3142 const std::string text = R"(
3143 ; CHECK: [[f_name:%\w+]] = OpString "f"
3144 ; CHECK: [[empty_expr:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugExpression
3145 ; CHECK: [[deref_op:%\w+]] = OpExtInst %void [[ext]] DebugOperation Deref
3146 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref_op]]
3147 ; CHECK: [[dbg_foo:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]]
3148
3149 ; CHECK: OpStore %f %float_0
3150 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] %float_0 [[empty_expr]] %uint_0
3151 ; CHECK-NEXT: OpStore %i %int_0
3152 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] %int_0 [[empty_expr]] %uint_1
3153
3154 ; CHECK: [[loop_head:%\w+]] = OpLabel
3155 ; CHECK: [[phi0:%\w+]] = OpPhi %float %float_0
3156 ; CHECK: [[phi1:%\w+]] = OpPhi %int %int_0
3157 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[phi0]] [[empty_expr]] %uint_0
3158 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[phi1]] [[empty_expr]] %uint_1
3159 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
3160 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
3161
3162 ; CHECK: [[loop_body]] = OpLabel
3163 ; CHECK: OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
3164
3165 ; CHECK: [[bb]] = OpLabel
3166 ; CHECK: OpStore %f [[f_val:%\w+]]
3167 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[f_val]] [[empty_expr]] %uint_0
3168 ; CHECK-NEXT: OpBranch [[loop_cont]]
3169
3170 ; CHECK: [[loop_cont]] = OpLabel
3171 ; CHECK: OpStore %i [[i_val:%\w+]]
3172 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[i_val]] [[empty_expr]] %uint_1
3173 ; CHECK-NEXT: OpBranch [[loop_head]]
3174
3175 OpCapability Shader
3176 %1 = OpExtInstImport "GLSL.std.450"
3177 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3178 OpMemoryModel Logical GLSL450
3179 OpEntryPoint Fragment %main "main" %BC %fo
3180 OpExecutionMode %main OriginUpperLeft
3181 %file_name = OpString "test"
3182 OpSource GLSL 140
3183 %float_name = OpString "float"
3184 %main_name = OpString "main"
3185 %f_name = OpString "f"
3186 OpName %main "main"
3187 OpName %f "f"
3188 OpName %i "i"
3189 OpName %BC "BC"
3190 OpName %fo "fo"
3191 %void = OpTypeVoid
3192 %8 = OpTypeFunction %void
3193 %float = OpTypeFloat 32
3194 %_ptr_Function_float = OpTypePointer Function %float
3195 %float_0 = OpConstant %float 0
3196 %int = OpTypeInt 32 1
3197 %uint = OpTypeInt 32 0
3198 %uint_32 = OpConstant %uint 32
3199 %uint_0 = OpConstant %uint 0
3200 %uint_1 = OpConstant %uint 1
3201 %_ptr_Function_int = OpTypePointer Function %int
3202 %int_0 = OpConstant %int 0
3203 %int_4 = OpConstant %int 4
3204 %bool = OpTypeBool
3205 %v4float = OpTypeVector %float 4
3206 %_ptr_Input_v4float = OpTypePointer Input %v4float
3207 %BC = OpVariable %_ptr_Input_v4float Input
3208 %_ptr_Input_float = OpTypePointer Input %float
3209 %int_1 = OpConstant %int 1
3210 %_ptr_Output_float = OpTypePointer Output %float
3211 %fo = OpVariable %_ptr_Output_float Output
3212 %deref_op = OpExtInst %void %ext DebugOperation Deref
3213 %deref = OpExtInst %void %ext DebugExpression %deref_op
3214 %src = OpExtInst %void %ext DebugSource %file_name
3215 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3216 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3217 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
3218 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
3219 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3220 %dbg_foo = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
3221 %main = OpFunction %void None %8
3222 %22 = OpLabel
3223 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3224 %f = OpVariable %_ptr_Function_float Function
3225 %i = OpVariable %_ptr_Function_int Function
3226 OpStore %f %float_0
3227 OpStore %i %int_0
3228 %decl0 = OpExtInst %void %ext DebugValue %dbg_foo %f %deref %uint_0
3229 %decl1 = OpExtInst %void %ext DebugValue %dbg_foo %i %deref %uint_1
3230 OpBranch %23
3231 %23 = OpLabel
3232 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3233 OpLoopMerge %24 %25 None
3234 OpBranch %26
3235 %26 = OpLabel
3236 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3237 %27 = OpLoad %int %i
3238 %28 = OpSLessThan %bool %27 %int_4
3239 OpBranchConditional %28 %29 %24
3240 %29 = OpLabel
3241 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3242 %30 = OpLoad %float %f
3243 %31 = OpLoad %int %i
3244 %32 = OpAccessChain %_ptr_Input_float %BC %31
3245 %33 = OpLoad %float %32
3246 %34 = OpFAdd %float %30 %33
3247 OpStore %f %34
3248 OpBranch %25
3249 %25 = OpLabel
3250 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3251 %35 = OpLoad %int %i
3252 %36 = OpIAdd %int %35 %int_1
3253 OpStore %i %36
3254 OpBranch %23
3255 %24 = OpLabel
3256 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3257 %37 = OpLoad %float %f
3258 OpStore %fo %37
3259 OpReturn
3260 OpFunctionEnd
3261 )";
3262
3263 SinglePassRunAndMatch<SSARewritePass>(text, true);
3264 }
3265
TEST_F(LocalSSAElimTest,DebugValueNotUsedForDebugDeclare)3266 TEST_F(LocalSSAElimTest, DebugValueNotUsedForDebugDeclare) {
3267 // #version 140
3268 //
3269 // in vec4 BC;
3270 // out float fo;
3271 //
3272 // void main()
3273 // {
3274 // float f = 0.0;
3275 // for (int i=0; i<4; i++) {
3276 // f = f + BC[i];
3277 // }
3278 // fo = f;
3279 // }
3280
3281 const std::string text = R"(
3282 ; CHECK: [[f_name:%\w+]] = OpString "f"
3283 ; CHECK: [[i_name:%\w+]] = OpString "i"
3284 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
3285 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
3286
3287 ; CHECK: OpStore %f %float_0
3288 ; CHECK-NEXT: OpStore %i %int_0
3289 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %f
3290 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %i
3291
3292 ; CHECK-NOT: DebugValue
3293 ; CHECK-NOT: DebugDeclare
3294
3295 OpCapability Shader
3296 %1 = OpExtInstImport "GLSL.std.450"
3297 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3298 OpMemoryModel Logical GLSL450
3299 OpEntryPoint Fragment %main "main" %BC %fo
3300 OpExecutionMode %main OriginUpperLeft
3301 %file_name = OpString "test"
3302 OpSource GLSL 140
3303 %float_name = OpString "float"
3304 %main_name = OpString "main"
3305 %f_name = OpString "f"
3306 %i_name = OpString "i"
3307 OpName %main "main"
3308 OpName %f "f"
3309 OpName %i "i"
3310 OpName %BC "BC"
3311 OpName %fo "fo"
3312 %void = OpTypeVoid
3313 %8 = OpTypeFunction %void
3314 %float = OpTypeFloat 32
3315 %_ptr_Function_float = OpTypePointer Function %float
3316 %float_0 = OpConstant %float 0
3317 %int = OpTypeInt 32 1
3318 %uint = OpTypeInt 32 0
3319 %uint_32 = OpConstant %uint 32
3320 %_ptr_Function_int = OpTypePointer Function %int
3321 %int_0 = OpConstant %int 0
3322 %int_4 = OpConstant %int 4
3323 %bool = OpTypeBool
3324 %v4float = OpTypeVector %float 4
3325 %_ptr_Input_v4float = OpTypePointer Input %v4float
3326 %BC = OpVariable %_ptr_Input_v4float Input
3327 %_ptr_Input_float = OpTypePointer Input %float
3328 %int_1 = OpConstant %int 1
3329 %_ptr_Output_float = OpTypePointer Output %float
3330 %fo = OpVariable %_ptr_Output_float Output
3331 %null_expr = OpExtInst %void %ext DebugExpression
3332 %src = OpExtInst %void %ext DebugSource %file_name
3333 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3334 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3335 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
3336 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
3337 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3338 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
3339 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
3340 %main = OpFunction %void None %8
3341 %22 = OpLabel
3342 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3343 %f = OpVariable %_ptr_Function_float Function
3344 %i = OpVariable %_ptr_Function_int Function
3345 OpStore %f %float_0
3346 OpStore %i %int_0
3347 %decl0 = OpExtInst %void %ext DebugValue %dbg_f %f %null_expr
3348 %decl1 = OpExtInst %void %ext DebugValue %dbg_i %i %null_expr
3349 OpBranch %23
3350 %23 = OpLabel
3351 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3352 OpLoopMerge %24 %25 None
3353 OpBranch %26
3354 %26 = OpLabel
3355 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3356 %27 = OpLoad %int %i
3357 %28 = OpSLessThan %bool %27 %int_4
3358 OpBranchConditional %28 %29 %24
3359 %29 = OpLabel
3360 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3361 %30 = OpLoad %float %f
3362 %31 = OpLoad %int %i
3363 %32 = OpAccessChain %_ptr_Input_float %BC %31
3364 %33 = OpLoad %float %32
3365 %34 = OpFAdd %float %30 %33
3366 OpStore %f %34
3367 OpBranch %25
3368 %25 = OpLabel
3369 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3370 %35 = OpLoad %int %i
3371 %36 = OpIAdd %int %35 %int_1
3372 OpStore %i %36
3373 OpBranch %23
3374 %24 = OpLabel
3375 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3376 %37 = OpLoad %float %f
3377 OpStore %fo %37
3378 OpReturn
3379 OpFunctionEnd
3380 )";
3381
3382 SinglePassRunAndMatch<SSARewritePass>(text, true);
3383 }
3384
TEST_F(LocalSSAElimTest,DebugNestedForLoop)3385 TEST_F(LocalSSAElimTest, DebugNestedForLoop) {
3386 const std::string text = R"(
3387 ; CHECK: = OpFunction
3388 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3389 ; CHECK: OpStore %f %float_0
3390 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f:%\w+]] %float_0
3391
3392 ; CHECK: [[outer_header:%\w+]] = OpLabel
3393 ; CHECK: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[outer_be:%\w+]]
3394 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[outer_f]]
3395
3396 ; CHECK: [[inner_pre_header:%\w+]] = OpLabel
3397 ; CHECK: [[inner_header:%\w+]] = OpLabel
3398 ; CHECK: [[inner_f]] = OpPhi %float [[outer_f]] [[inner_pre_header]] [[f_next:%\w+]] [[inner_be:%\w+]]
3399 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[inner_f]]
3400
3401 ; CHECK: [[inner_be]] = OpLabel
3402 ; CHECK: [[f_next]] = OpFAdd %float [[inner_f]]
3403 ; CHECK-NEXT: OpStore %f [[f_next]]
3404 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_next]]
3405
3406 OpCapability Shader
3407 %1 = OpExtInstImport "GLSL.std.450"
3408 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3409 OpMemoryModel Logical GLSL450
3410 OpEntryPoint Fragment %main "main" %BC %fo
3411 OpExecutionMode %main OriginUpperLeft
3412 %file_name = OpString "test"
3413 %float_name = OpString "float"
3414 %main_name = OpString "main"
3415 %f_name = OpString "f"
3416 OpSource GLSL 450
3417 OpName %main "main"
3418 OpName %f "f"
3419 OpName %i "i"
3420 OpName %j "j"
3421 OpName %BC "BC"
3422 OpName %fo "fo"
3423 OpDecorate %BC Location 0
3424 OpDecorate %fo Location 0
3425 %void = OpTypeVoid
3426 %9 = OpTypeFunction %void
3427 %float = OpTypeFloat 32
3428 %_ptr_Function_float = OpTypePointer Function %float
3429 %float_0 = OpConstant %float 0
3430 %int = OpTypeInt 32 1
3431 %_ptr_Function_int = OpTypePointer Function %int
3432 %int_0 = OpConstant %int 0
3433 %int_4 = OpConstant %int 4
3434 %uint = OpTypeInt 32 0
3435 %uint_32 = OpConstant %uint 32
3436 %bool = OpTypeBool
3437 %v4float = OpTypeVector %float 4
3438 %mat4v4float = OpTypeMatrix %v4float 4
3439 %_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float
3440 %BC = OpVariable %_ptr_Input_mat4v4float Input
3441 %_ptr_Input_float = OpTypePointer Input %float
3442 %int_1 = OpConstant %int 1
3443 %_ptr_Output_float = OpTypePointer Output %float
3444 %fo = OpVariable %_ptr_Output_float Output
3445
3446 ; Debug information
3447 %null_expr = OpExtInst %void %ext DebugExpression
3448 %src = OpExtInst %void %ext DebugSource %file_name
3449 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3450 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3451 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3452 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3453 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3454
3455 %main = OpFunction %void None %9
3456 %24 = OpLabel
3457 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3458 %f = OpVariable %_ptr_Function_float Function
3459 %i = OpVariable %_ptr_Function_int Function
3460 %j = OpVariable %_ptr_Function_int Function
3461
3462 ; DebugDeclare
3463 OpStore %f %float_0
3464 %decl = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
3465
3466 OpStore %i %int_0
3467 OpBranch %25
3468 %25 = OpLabel
3469 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3470 %26 = OpLoad %int %i
3471 %27 = OpSLessThan %bool %26 %int_4
3472 OpLoopMerge %28 %29 None
3473 OpBranchConditional %27 %30 %28
3474 %30 = OpLabel
3475 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3476 OpStore %j %int_0
3477 OpBranch %31
3478 %31 = OpLabel
3479 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3480 %32 = OpLoad %int %j
3481 %33 = OpSLessThan %bool %32 %int_4
3482 OpLoopMerge %50 %34 None
3483 OpBranchConditional %33 %34 %50
3484 %34 = OpLabel
3485 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3486 %35 = OpLoad %float %f
3487 %36 = OpLoad %int %i
3488 %37 = OpLoad %int %j
3489 %38 = OpAccessChain %_ptr_Input_float %BC %36 %37
3490 %39 = OpLoad %float %38
3491 %40 = OpFAdd %float %35 %39
3492 OpStore %f %40
3493 %41 = OpLoad %int %j
3494 %42 = OpIAdd %int %41 %int_1
3495 OpStore %j %42
3496 OpBranch %31
3497 %50 = OpLabel
3498 %s6 = OpExtInst %void %ext DebugScope %dbg_main
3499 OpBranch %29
3500 %29 = OpLabel
3501 %s7 = OpExtInst %void %ext DebugScope %dbg_main
3502 %43 = OpLoad %int %i
3503 %44 = OpIAdd %int %43 %int_1
3504 OpStore %i %44
3505 OpBranch %25
3506 %28 = OpLabel
3507 %s8 = OpExtInst %void %ext DebugScope %dbg_main
3508 %45 = OpLoad %float %f
3509 OpStore %fo %45
3510 OpReturn
3511 OpFunctionEnd
3512 )";
3513
3514 SinglePassRunAndMatch<SSARewritePass>(text, true);
3515 }
3516
TEST_F(LocalSSAElimTest,DebugForLoopWithContinue)3517 TEST_F(LocalSSAElimTest, DebugForLoopWithContinue) {
3518 const std::string text = R"(
3519 ; CHECK: = OpFunction
3520 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3521 ; CHECK: OpStore %f %float_0
3522 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f:%\w+]] %float_0
3523
3524 ; CHECK: [[outer_header:%\w+]] = OpLabel
3525 ; CHECK: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[cont:%\w+]]
3526 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[outer_f]]
3527
3528 ; CHECK: [[f_next:%\w+]] = OpFAdd %float [[outer_f]]
3529 ; CHECK-NEXT: OpStore %f [[f_next]]
3530 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_next]]
3531
3532 ; CHECK: [[cont]] = OpLabel
3533 ; CHECK: [[inner_f]] = OpPhi %float [[outer_f]] {{%\d+}} [[f_next]] {{%\d+}}
3534 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[inner_f]]
3535
3536 OpCapability Shader
3537 %1 = OpExtInstImport "GLSL.std.450"
3538 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3539 OpMemoryModel Logical GLSL450
3540 OpEntryPoint Fragment %main "main" %BC %fo
3541 OpExecutionMode %main OriginUpperLeft
3542 %file_name = OpString "test"
3543 %float_name = OpString "float"
3544 %main_name = OpString "main"
3545 %f_name = OpString "f"
3546 OpSource GLSL 140
3547 OpName %main "main"
3548 OpName %f "f"
3549 OpName %i "i"
3550 OpName %t "t"
3551 OpName %BC "BC"
3552 OpName %fo "fo"
3553 %void = OpTypeVoid
3554 %9 = OpTypeFunction %void
3555 %float = OpTypeFloat 32
3556 %_ptr_Function_float = OpTypePointer Function %float
3557 %float_0 = OpConstant %float 0
3558 %int = OpTypeInt 32 1
3559 %_ptr_Function_int = OpTypePointer Function %int
3560 %int_0 = OpConstant %int 0
3561 %int_4 = OpConstant %int 4
3562 %uint = OpTypeInt 32 0
3563 %uint_32 = OpConstant %uint 32
3564 %bool = OpTypeBool
3565 %v4float = OpTypeVector %float 4
3566 %_ptr_Input_v4float = OpTypePointer Input %v4float
3567 %BC = OpVariable %_ptr_Input_v4float Input
3568 %_ptr_Input_float = OpTypePointer Input %float
3569 %int_1 = OpConstant %int 1
3570 %_ptr_Output_float = OpTypePointer Output %float
3571 %fo = OpVariable %_ptr_Output_float Output
3572
3573 ; Debug information
3574 %null_expr = OpExtInst %void %ext DebugExpression
3575 %src = OpExtInst %void %ext DebugSource %file_name
3576 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3577 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3578 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3579 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3580 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3581
3582 %main = OpFunction %void None %9
3583 %23 = OpLabel
3584 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3585 %f = OpVariable %_ptr_Function_float Function
3586 %i = OpVariable %_ptr_Function_int Function
3587 %t = OpVariable %_ptr_Function_float Function
3588
3589 ; DebugDeclare
3590 OpStore %f %float_0
3591 %decl = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
3592
3593 OpStore %i %int_0
3594 OpBranch %24
3595 %24 = OpLabel
3596 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3597 OpLoopMerge %25 %26 None
3598 OpBranch %27
3599 %27 = OpLabel
3600 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3601 %28 = OpLoad %int %i
3602 %29 = OpSLessThan %bool %28 %int_4
3603 OpBranchConditional %29 %30 %25
3604 %30 = OpLabel
3605 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3606 %31 = OpLoad %int %i
3607 %32 = OpAccessChain %_ptr_Input_float %BC %31
3608 %33 = OpLoad %float %32
3609 OpStore %t %33
3610 %34 = OpLoad %float %t
3611 %35 = OpFOrdLessThan %bool %34 %float_0
3612 OpSelectionMerge %36 None
3613 OpBranchConditional %35 %37 %36
3614 %37 = OpLabel
3615 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3616 OpBranch %26
3617 %36 = OpLabel
3618 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3619 %38 = OpLoad %float %f
3620 %39 = OpLoad %float %t
3621 %40 = OpFAdd %float %38 %39
3622 OpStore %f %40
3623 OpBranch %26
3624 %26 = OpLabel
3625 %s6 = OpExtInst %void %ext DebugScope %dbg_main
3626 %41 = OpLoad %int %i
3627 %42 = OpIAdd %int %41 %int_1
3628 OpStore %i %42
3629 OpBranch %24
3630 %25 = OpLabel
3631 %s7 = OpExtInst %void %ext DebugScope %dbg_main
3632 %43 = OpLoad %float %f
3633 OpStore %fo %43
3634 OpReturn
3635 OpFunctionEnd
3636 )";
3637
3638 SinglePassRunAndMatch<SSARewritePass>(text, true);
3639 }
3640
TEST_F(LocalSSAElimTest,DebugIfElse)3641 TEST_F(LocalSSAElimTest, DebugIfElse) {
3642 const std::string text = R"(
3643 OpCapability Shader
3644 %1 = OpExtInstImport "GLSL.std.450"
3645 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3646 OpMemoryModel Logical GLSL450
3647 OpEntryPoint Fragment %main "main" %f %BaseColor %gl_FragColor
3648 OpExecutionMode %main OriginUpperLeft
3649 %file_name = OpString "test"
3650 %float_name = OpString "float"
3651 %main_name = OpString "main"
3652 %v_name = OpString "v"
3653 OpSource GLSL 140
3654 OpName %main "main"
3655 OpName %f "f"
3656 OpName %v "v"
3657 OpName %BaseColor "BaseColor"
3658 OpName %gl_FragColor "gl_FragColor"
3659 %void = OpTypeVoid
3660 %8 = OpTypeFunction %void
3661 %float = OpTypeFloat 32
3662 %_ptr_Input_float = OpTypePointer Input %float
3663 %f = OpVariable %_ptr_Input_float Input
3664 %float_0 = OpConstant %float 0
3665 %uint = OpTypeInt 32 0
3666 %uint_32 = OpConstant %uint 32
3667 %bool = OpTypeBool
3668 %v4float = OpTypeVector %float 4
3669 %_ptr_Function_v4float = OpTypePointer Function %v4float
3670 %_ptr_Input_v4float = OpTypePointer Input %v4float
3671 %BaseColor = OpVariable %_ptr_Input_v4float Input
3672 %float_0_5 = OpConstant %float 0.5
3673 %float_1 = OpConstant %float 1
3674 %18 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
3675 %_ptr_Output_v4float = OpTypePointer Output %v4float
3676 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
3677
3678 ; Debug information
3679 %null_expr = OpExtInst %void %ext DebugExpression
3680 %src = OpExtInst %void %ext DebugSource %file_name
3681 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3682 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3683 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3684 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3685 %dbg_v = OpExtInst %void %ext DebugLocalVariable %v_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3686
3687 %main = OpFunction %void None %8
3688 %20 = OpLabel
3689 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3690
3691 ; DebugDeclare
3692 %v = OpVariable %_ptr_Function_v4float Function
3693 %decl = OpExtInst %void %ext DebugDeclare %dbg_v %v %null_expr
3694
3695 %21 = OpLoad %float %f
3696 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
3697 OpSelectionMerge %23 None
3698 OpBranchConditional %22 %24 %25
3699
3700 ; CHECK: OpBranchConditional
3701 ; CHECK-NEXT: [[br0:%\w+]] = OpLabel
3702 ; CHECK: OpStore %v [[v0:%\w+]]
3703 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_v:%\w+]] [[v0]]
3704 %24 = OpLabel
3705 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3706 %26 = OpLoad %v4float %BaseColor
3707 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
3708 OpStore %v %27
3709 OpBranch %23
3710
3711 ; CHECK: [[br1:%\w+]] = OpLabel
3712 ; CHECK: OpStore %v [[v1:%\w+]]
3713 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v1]]
3714 %25 = OpLabel
3715 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3716 %28 = OpLoad %v4float %BaseColor
3717 %29 = OpFAdd %v4float %28 %18
3718 OpStore %v %29
3719 OpBranch %23
3720
3721 ; CHECK: [[phi:%\w+]] = OpPhi %v4float [[v0]] [[br0]] [[v1]] [[br1]]
3722 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi]]
3723 %23 = OpLabel
3724 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3725 %30 = OpLoad %v4float %v
3726 OpStore %gl_FragColor %30
3727 OpReturn
3728 OpFunctionEnd
3729 )";
3730
3731 SinglePassRunAndMatch<SSARewritePass>(text, true);
3732 }
3733
TEST_F(LocalSSAElimTest,DebugSwitch)3734 TEST_F(LocalSSAElimTest, DebugSwitch) {
3735 const std::string text = R"(
3736 OpCapability Shader
3737 %1 = OpExtInstImport "GLSL.std.450"
3738 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3739 OpMemoryModel Logical GLSL450
3740 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
3741 OpExecutionMode %main OriginUpperLeft
3742 %file_name = OpString "test"
3743 %float_name = OpString "float"
3744 %main_name = OpString "main"
3745 %v_name = OpString "v"
3746 OpSource GLSL 140
3747 OpName %main "main"
3748 OpName %v "v"
3749 OpName %BaseColor "BaseColor"
3750 OpName %i "i"
3751 OpName %f "f"
3752 OpName %gl_FragColor "gl_FragColor"
3753 %void = OpTypeVoid
3754 %9 = OpTypeFunction %void
3755 %float = OpTypeFloat 32
3756 %v4float = OpTypeVector %float 4
3757 %uint = OpTypeInt 32 0
3758 %uint_32 = OpConstant %uint 32
3759 %_ptr_Function_v4float = OpTypePointer Function %v4float
3760 %_ptr_Input_v4float = OpTypePointer Input %v4float
3761 %BaseColor = OpVariable %_ptr_Input_v4float Input
3762 %int = OpTypeInt 32 1
3763 %_ptr_Function_int = OpTypePointer Function %int
3764 %_ptr_Input_float = OpTypePointer Input %float
3765 %f = OpVariable %_ptr_Input_float Input
3766 %float_0_25 = OpConstant %float 0.25
3767 %float_0_75 = OpConstant %float 0.75
3768 %_ptr_Output_v4float = OpTypePointer Output %v4float
3769 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
3770
3771 ; Debug information
3772 %null_expr = OpExtInst %void %ext DebugExpression
3773 %src = OpExtInst %void %ext DebugSource %file_name
3774 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3775 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3776 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3777 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3778 %dbg_v = OpExtInst %void %ext DebugLocalVariable %v_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3779
3780 %main = OpFunction %void None %9
3781 %20 = OpLabel
3782 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3783 %v = OpVariable %_ptr_Function_v4float Function
3784 %i = OpVariable %_ptr_Function_int Function
3785 %21 = OpLoad %v4float %BaseColor
3786
3787 ; DebugDeclare
3788 OpStore %v %21
3789 %decl = OpExtInst %void %ext DebugDeclare %dbg_v %v %null_expr
3790
3791 ; CHECK: %main = OpFunction %void None
3792 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3793 ; CHECK: OpStore %v [[v0:%\w+]]
3794 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_v:%\w+]] [[v0]]
3795 ; CHECK: OpSwitch {{%\w+}} [[case0:%\w+]] 0 [[case1:%\w+]] 1 [[case2:%\w+]] 2 [[case3:%\w+]]
3796 ; CHECK: OpStore %v [[v1:%\w+]]
3797 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v1]]
3798 ; CHECK: OpStore %v [[v2:%\w+]]
3799 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v2]]
3800 ; CHECK: [[phi0:%\w+]] = OpPhi %v4float [[v0]] [[entry]] [[v2]] [[case2]]
3801 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi0]]
3802 ; CHECK: OpStore %v [[v3:%\w+]]
3803 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v3]]
3804 ; CHECK: [[phi1:%\w+]] = OpPhi %v4float [[v0]] [[case0]] [[v1]] [[case1]] [[v3]] [[case3]]
3805 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi1]]
3806
3807 %22 = OpLoad %float %f
3808 %23 = OpConvertFToS %int %22
3809 OpStore %i %23
3810 %24 = OpLoad %int %i
3811 OpSelectionMerge %25 None
3812 OpSwitch %24 %26 0 %27 1 %28 2 %29
3813 %26 = OpLabel
3814 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3815 OpBranch %25
3816 %27 = OpLabel
3817 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3818 %30 = OpLoad %v4float %v
3819 %31 = OpVectorTimesScalar %v4float %30 %float_0_25
3820 OpStore %v %31
3821 OpBranch %25
3822 %28 = OpLabel
3823 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3824 %32 = OpLoad %v4float %v
3825 %33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
3826 %34 = OpFAdd %v4float %32 %33
3827 OpStore %v %34
3828 OpBranch %29
3829 %29 = OpLabel
3830 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3831 %35 = OpLoad %v4float %v
3832 %36 = OpVectorTimesScalar %v4float %35 %float_0_75
3833 OpStore %v %36
3834 OpBranch %25
3835 %25 = OpLabel
3836 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3837 %37 = OpLoad %v4float %v
3838 OpStore %gl_FragColor %37
3839 OpReturn
3840 OpFunctionEnd
3841 )";
3842
3843 SinglePassRunAndMatch<SSARewritePass>(text, true);
3844 }
3845
TEST_F(LocalSSAElimTest,DebugSwapProblem)3846 TEST_F(LocalSSAElimTest, DebugSwapProblem) {
3847 // #version 140
3848 //
3849 // in float fe;
3850 // out float fo;
3851 //
3852 // void main()
3853 // {
3854 // float f1 = 0.0;
3855 // float f2 = 1.0;
3856 // int ie = int(fe);
3857 // for (int i=0; i<ie; i++) {
3858 // float t = f1;
3859 // f1 = f2;
3860 // f2 = t;
3861 // }
3862 // fo = f1;
3863 // }
3864 //
3865 // Because of the swap in the for loop, it generates the following phi
3866 // instructions:
3867 //
3868 // [[phi_f2]] = OpPhi %float %float_1 [[entry]] [[phi_f1]] ..
3869 // [[phi_f1]] = OpPhi %float %float_0 [[entry]] [[phi_f2]] ..
3870 //
3871 // Since they are used as operands by each other, we want to clearly check
3872 // what DebugValue we have to add for them.
3873
3874 const std::string text = R"(
3875 OpCapability Shader
3876 %1 = OpExtInstImport "GLSL.std.450"
3877 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3878 OpMemoryModel Logical GLSL450
3879 OpEntryPoint Fragment %main "main" %fe %fo
3880 OpExecutionMode %main OriginUpperLeft
3881 OpSource GLSL 140
3882 %file_name = OpString "test"
3883 %float_name = OpString "float"
3884 %main_name = OpString "main"
3885 %t_name = OpString "t"
3886 OpName %main "main"
3887 OpName %f1 "f1"
3888 OpName %f2 "f2"
3889 OpName %ie "ie"
3890 OpName %fe "fe"
3891 OpName %i "i"
3892 OpName %t "t"
3893 OpName %fo "fo"
3894 %void = OpTypeVoid
3895 %11 = OpTypeFunction %void
3896 %float = OpTypeFloat 32
3897 %_ptr_Function_float = OpTypePointer Function %float
3898 %float_0 = OpConstant %float 0
3899 %float_1 = OpConstant %float 1
3900 %int = OpTypeInt 32 1
3901 %_ptr_Function_int = OpTypePointer Function %int
3902 %_ptr_Input_float = OpTypePointer Input %float
3903 %fe = OpVariable %_ptr_Input_float Input
3904 %int_0 = OpConstant %int 0
3905 %bool = OpTypeBool
3906 %int_1 = OpConstant %int 1
3907 %uint = OpTypeInt 32 0
3908 %uint_32 = OpConstant %uint 32
3909 %_ptr_Output_float = OpTypePointer Output %float
3910 %fo = OpVariable %_ptr_Output_float Output
3911
3912 ; Debug information
3913 %null_expr = OpExtInst %void %ext DebugExpression
3914 %src = OpExtInst %void %ext DebugSource %file_name
3915 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3916 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3917 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3918 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3919 %dbg_f1 = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3920 %dbg_f2 = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3921 %dbg_i = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3922
3923 %main = OpFunction %void None %11
3924 %23 = OpLabel
3925 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3926 %f1 = OpVariable %_ptr_Function_float Function
3927 %f2 = OpVariable %_ptr_Function_float Function
3928 %ie = OpVariable %_ptr_Function_int Function
3929 %i = OpVariable %_ptr_Function_int Function
3930 %t = OpVariable %_ptr_Function_float Function
3931 OpStore %f1 %float_0
3932 OpStore %f2 %float_1
3933 %24 = OpLoad %float %fe
3934 %25 = OpConvertFToS %int %24
3935 OpStore %ie %25
3936 OpStore %i %int_0
3937
3938 ; DebugDeclare
3939 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f1 %f1 %null_expr
3940 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_f2 %f2 %null_expr
3941 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
3942
3943 ; CHECK: %main = OpFunction %void None
3944 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3945
3946 ; CHECK: OpStore %f1 %float_0
3947 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f1:%\w+]] %float_0
3948 ; CHECK: OpStore %f2 %float_1
3949 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f2:%\w+]] %float_1
3950 ; CHECK: OpStore %i %int_0
3951 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_i:%\w+]] %int_0
3952
3953 ; CHECK: [[phi_f2:%\w+]] = OpPhi %float %float_1 [[entry]] [[phi_f1:%\w+]]
3954 ; CHECK: [[phi_f1]] = OpPhi %float %float_0 [[entry]] [[phi_f2]]
3955 ; CHECK: [[phi_i:%\w+]] = OpPhi %int %int_0 [[entry]]
3956 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f2]] [[phi_f2]]
3957 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f1]] [[phi_f1]]
3958 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi_i]]
3959
3960 OpBranch %26
3961 %26 = OpLabel
3962 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3963 OpLoopMerge %27 %28 None
3964 OpBranch %29
3965 %29 = OpLabel
3966 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3967 %30 = OpLoad %int %i
3968 %31 = OpLoad %int %ie
3969 %32 = OpSLessThan %bool %30 %31
3970 OpBranchConditional %32 %33 %27
3971 %33 = OpLabel
3972 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3973 %34 = OpLoad %float %f1
3974 OpStore %t %34
3975 %35 = OpLoad %float %f2
3976 OpStore %f1 %35
3977 %36 = OpLoad %float %t
3978 OpStore %f2 %36
3979 OpBranch %28
3980 %28 = OpLabel
3981 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3982 %37 = OpLoad %int %i
3983 %38 = OpIAdd %int %37 %int_1
3984 OpStore %i %38
3985 OpBranch %26
3986 %27 = OpLabel
3987 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3988 %39 = OpLoad %float %f1
3989 OpStore %fo %39
3990 OpReturn
3991 OpFunctionEnd
3992 )";
3993
3994 SinglePassRunAndMatch<SSARewritePass>(text, true);
3995 }
3996
TEST_F(LocalSSAElimTest,RemoveDebugDeclareWithoutLoads)3997 TEST_F(LocalSSAElimTest, RemoveDebugDeclareWithoutLoads) {
3998 // Check that the DebugDeclare for c is removed even though its loads
3999 // had been removed previously by single block store/load optimization.
4000 // In the presence of DebugDeclare, single-block can and does remove loads,
4001 // but cannot change the stores into DebugValues and remove the DebugDeclare
4002 // because it is only a per block optimization, not a function optimization.
4003 // So SSA-rewrite must perform this role.
4004 //
4005 // Texture2D g_tColor;
4006 // SamplerState g_sAniso;
4007 //
4008 // struct PS_INPUT
4009 // {
4010 // float2 vTextureCoords2 : TEXCOORD2;
4011 // float2 vTextureCoords3 : TEXCOORD3;
4012 // };
4013 //
4014 // struct PS_OUTPUT
4015 // {
4016 // float4 vColor : SV_Target0;
4017 // };
4018 //
4019 // PS_OUTPUT MainPs(PS_INPUT i)
4020 // {
4021 // PS_OUTPUT ps_output;
4022 // float4 c;
4023 // c = g_tColor.Sample(g_sAniso, i.vTextureCoords2.xy);
4024 // c += g_tColor.Sample(g_sAniso, i.vTextureCoords3.xy);
4025 // ps_output.vColor = c;
4026 // return ps_output;
4027 // }
4028
4029 const std::string text = R"(
4030 OpCapability Shader
4031 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
4032 OpMemoryModel Logical GLSL450
4033 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %in_var_TEXCOORD3 %out_var_SV_Target0
4034 OpExecutionMode %MainPs OriginUpperLeft
4035 %22 = OpString "foo.frag"
4036 %26 = OpString "PS_OUTPUT"
4037 %30 = OpString "float"
4038 %33 = OpString "vColor"
4039 %35 = OpString "PS_INPUT"
4040 %40 = OpString "vTextureCoords3"
4041 %42 = OpString "vTextureCoords2"
4042 %44 = OpString "@type.2d.image"
4043 %45 = OpString "type.2d.image"
4044 %47 = OpString "Texture2D.TemplateParam"
4045 %51 = OpString "src.MainPs"
4046 %55 = OpString "c"
4047 %57 = OpString "ps_output"
4048 %60 = OpString "i"
4049 %62 = OpString "@type.sampler"
4050 %63 = OpString "type.sampler"
4051 %65 = OpString "g_sAniso"
4052 %67 = OpString "g_tColor"
4053 OpName %type_2d_image "type.2d.image"
4054 OpName %g_tColor "g_tColor"
4055 OpName %type_sampler "type.sampler"
4056 OpName %g_sAniso "g_sAniso"
4057 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
4058 OpName %in_var_TEXCOORD3 "in.var.TEXCOORD3"
4059 OpName %out_var_SV_Target0 "out.var.SV_Target0"
4060 OpName %MainPs "MainPs"
4061 OpName %PS_INPUT "PS_INPUT"
4062 OpMemberName %PS_INPUT 0 "vTextureCoords2"
4063 OpMemberName %PS_INPUT 1 "vTextureCoords3"
4064 OpName %param_var_i "param.var.i"
4065 OpName %PS_OUTPUT "PS_OUTPUT"
4066 OpMemberName %PS_OUTPUT 0 "vColor"
4067 OpName %type_sampled_image "type.sampled.image"
4068 OpDecorate %in_var_TEXCOORD2 Location 0
4069 OpDecorate %in_var_TEXCOORD3 Location 1
4070 OpDecorate %out_var_SV_Target0 Location 0
4071 OpDecorate %g_tColor DescriptorSet 0
4072 OpDecorate %g_tColor Binding 0
4073 OpDecorate %g_sAniso DescriptorSet 0
4074 OpDecorate %g_sAniso Binding 1
4075 %int = OpTypeInt 32 1
4076 %int_0 = OpConstant %int 0
4077 %int_1 = OpConstant %int 1
4078 %uint = OpTypeInt 32 0
4079 %uint_32 = OpConstant %uint 32
4080 %float = OpTypeFloat 32
4081 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
4082 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
4083 %type_sampler = OpTypeSampler
4084 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
4085 %v2float = OpTypeVector %float 2
4086 %_ptr_Input_v2float = OpTypePointer Input %v2float
4087 %v4float = OpTypeVector %float 4
4088 %_ptr_Output_v4float = OpTypePointer Output %v4float
4089 %void = OpTypeVoid
4090 %uint_128 = OpConstant %uint 128
4091 %uint_0 = OpConstant %uint 0
4092 %uint_64 = OpConstant %uint 64
4093 %69 = OpTypeFunction %void
4094 %PS_INPUT = OpTypeStruct %v2float %v2float
4095 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
4096 %PS_OUTPUT = OpTypeStruct %v4float
4097 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
4098 %_ptr_Function_v4float = OpTypePointer Function %v4float
4099 %_ptr_Function_v2float = OpTypePointer Function %v2float
4100 %type_sampled_image = OpTypeSampledImage %type_2d_image
4101 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
4102 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
4103 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
4104 %in_var_TEXCOORD3 = OpVariable %_ptr_Input_v2float Input
4105 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
4106 %43 = OpExtInst %void %1 DebugInfoNone
4107 %59 = OpExtInst %void %1 DebugExpression
4108 %24 = OpExtInst %void %1 DebugSource %22
4109 %25 = OpExtInst %void %1 DebugCompilationUnit 1 4 %24 HLSL
4110 %28 = OpExtInst %void %1 DebugTypeComposite %26 Structure %24 11 1 %25 %26 %uint_128 FlagIsProtected|FlagIsPrivate %29
4111 %31 = OpExtInst %void %1 DebugTypeBasic %30 %uint_32 Float
4112 %32 = OpExtInst %void %1 DebugTypeVector %31 4
4113 %29 = OpExtInst %void %1 DebugTypeMember %33 %32 %24 13 5 %28 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
4114 %36 = OpExtInst %void %1 DebugTypeComposite %35 Structure %24 5 1 %25 %35 %uint_128 FlagIsProtected|FlagIsPrivate %37 %38
4115 %39 = OpExtInst %void %1 DebugTypeVector %31 2
4116 %38 = OpExtInst %void %1 DebugTypeMember %40 %39 %24 8 5 %36 %uint_64 %uint_64 FlagIsProtected|FlagIsPrivate
4117 %37 = OpExtInst %void %1 DebugTypeMember %42 %39 %24 7 5 %36 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
4118 %46 = OpExtInst %void %1 DebugTypeComposite %44 Class %24 0 0 %25 %45 %43 FlagIsProtected|FlagIsPrivate
4119 %50 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %28 %36
4120 %52 = OpExtInst %void %1 DebugFunction %51 %50 %24 16 1 %25 %51 FlagIsProtected|FlagIsPrivate 17 %43
4121 %54 = OpExtInst %void %1 DebugLexicalBlock %24 17 1 %52
4122 %56 = OpExtInst %void %1 DebugLocalVariable %55 %32 %24 20 12 %54 FlagIsLocal
4123 %58 = OpExtInst %void %1 DebugLocalVariable %57 %28 %24 18 15 %54 FlagIsLocal
4124 %61 = OpExtInst %void %1 DebugLocalVariable %60 %36 %24 16 29 %52 FlagIsLocal 1
4125 %64 = OpExtInst %void %1 DebugTypeComposite %62 Structure %24 0 0 %25 %63 %43 FlagIsProtected|FlagIsPrivate
4126 %66 = OpExtInst %void %1 DebugGlobalVariable %65 %64 %24 3 14 %25 %65 %g_sAniso FlagIsDefinition
4127 %68 = OpExtInst %void %1 DebugGlobalVariable %67 %46 %24 1 11 %25 %67 %g_tColor FlagIsDefinition
4128 %MainPs = OpFunction %void None %69
4129 %70 = OpLabel
4130 %135 = OpExtInst %void %1 DebugScope %54
4131 %111 = OpVariable %_ptr_Function_PS_OUTPUT Function
4132 %112 = OpVariable %_ptr_Function_v4float Function
4133 %136 = OpExtInst %void %1 DebugNoScope
4134 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
4135 %74 = OpLoad %v2float %in_var_TEXCOORD2
4136 %75 = OpLoad %v2float %in_var_TEXCOORD3
4137 %76 = OpCompositeConstruct %PS_INPUT %74 %75
4138 OpStore %param_var_i %76
4139 %137 = OpExtInst %void %1 DebugScope %52
4140 %115 = OpExtInst %void %1 DebugDeclare %61 %param_var_i %59
4141 %138 = OpExtInst %void %1 DebugScope %54
4142 %116 = OpExtInst %void %1 DebugDeclare %58 %111 %59
4143 %117 = OpExtInst %void %1 DebugDeclare %56 %112 %59
4144 ;CHECK-NOT: %117 = OpExtInst %void %1 DebugDeclare %56 %112 %59
4145 OpLine %22 21 9
4146 %118 = OpLoad %type_2d_image %g_tColor
4147 OpLine %22 21 29
4148 %119 = OpLoad %type_sampler %g_sAniso
4149 OpLine %22 21 40
4150 %120 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
4151 %121 = OpLoad %v2float %120
4152 OpLine %22 21 9
4153 %122 = OpSampledImage %type_sampled_image %118 %119
4154 %123 = OpImageSampleImplicitLod %v4float %122 %121 None
4155 OpLine %22 21 5
4156 OpStore %112 %123
4157 ;CHECK: %140 = OpExtInst %void %1 DebugValue %56 %123 %59
4158 OpLine %22 22 10
4159 %124 = OpLoad %type_2d_image %g_tColor
4160 OpLine %22 22 30
4161 %125 = OpLoad %type_sampler %g_sAniso
4162 OpLine %22 22 41
4163 %126 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_1
4164 %127 = OpLoad %v2float %126
4165 OpLine %22 22 10
4166 %128 = OpSampledImage %type_sampled_image %124 %125
4167 %129 = OpImageSampleImplicitLod %v4float %128 %127 None
4168 OpLine %22 22 7
4169 %131 = OpFAdd %v4float %123 %129
4170 OpLine %22 22 5
4171 OpStore %112 %131
4172 ;CHECK: %141 = OpExtInst %void %1 DebugValue %56 %131 %59
4173 OpLine %22 23 5
4174 %133 = OpAccessChain %_ptr_Function_v4float %111 %int_0
4175 OpStore %133 %131
4176 OpLine %22 24 12
4177 %134 = OpLoad %PS_OUTPUT %111
4178 %139 = OpExtInst %void %1 DebugNoScope
4179 %79 = OpCompositeExtract %v4float %134 0
4180 OpStore %out_var_SV_Target0 %79
4181 OpReturn
4182 OpFunctionEnd
4183 )";
4184
4185 SetTargetEnv(SPV_ENV_VULKAN_1_2);
4186 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4187 SinglePassRunAndMatch<SSARewritePass>(text, true);
4188 }
4189
4190 // Check support for pointer variables. When pointer variables are used, the
4191 // computation of reaching definitions may need to follow pointer chains.
4192 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/3873 for details.
TEST_F(LocalSSAElimTest,PointerVariables)4193 TEST_F(LocalSSAElimTest, PointerVariables) {
4194 const std::string text = R"(
4195 OpCapability Shader
4196 OpCapability VariablePointers
4197 OpExtension "SPV_KHR_variable_pointers"
4198 OpMemoryModel Logical Simple
4199 OpEntryPoint Fragment %1 "main" %2 %3
4200 OpExecutionMode %1 OriginUpperLeft
4201 %float = OpTypeFloat 32
4202 %void = OpTypeVoid
4203 %6 = OpTypeFunction %void
4204 %_ptr_Input_float = OpTypePointer Input %float
4205 %_ptr_Output_float = OpTypePointer Output %float
4206 %_ptr_Function__ptr_Input_float = OpTypePointer Function %_ptr_Input_float
4207 %2 = OpVariable %_ptr_Input_float Input
4208 %3 = OpVariable %_ptr_Output_float Output
4209 %1 = OpFunction %void None %6
4210 %10 = OpLabel
4211 %11 = OpVariable %_ptr_Function__ptr_Input_float Function
4212 OpStore %11 %2
4213
4214 ; CHECK-NOT: %12 = OpLoad %_ptr_Input_float %11
4215 %12 = OpLoad %_ptr_Input_float %11
4216
4217 ; CHECK: %13 = OpLoad %float %2
4218 %13 = OpLoad %float %12
4219
4220 OpStore %3 %13
4221 OpReturn
4222 OpFunctionEnd
4223 )";
4224
4225 SinglePassRunAndMatch<SSARewritePass>(text, true);
4226 }
4227
TEST_F(LocalSSAElimTest,FunctionDeclaration)4228 TEST_F(LocalSSAElimTest, FunctionDeclaration) {
4229 // Make sure the pass works with a function declaration that is called.
4230 const std::string text = R"(OpCapability Addresses
4231 OpCapability Linkage
4232 OpCapability Kernel
4233 OpCapability Int8
4234 %1 = OpExtInstImport "OpenCL.std"
4235 OpMemoryModel Physical64 OpenCL
4236 OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
4237 OpExecutionMode %2 ContractionOff
4238 OpSource Unknown 0
4239 OpDecorate %3 LinkageAttributes "julia_error_7712" Import
4240 %void = OpTypeVoid
4241 %5 = OpTypeFunction %void
4242 %3 = OpFunction %void None %5
4243 OpFunctionEnd
4244 %2 = OpFunction %void None %5
4245 %6 = OpLabel
4246 %7 = OpFunctionCall %void %3
4247 OpReturn
4248 OpFunctionEnd
4249 )";
4250
4251 SinglePassRunAndCheck<SSARewritePass>(text, text, false);
4252 }
4253
4254 // TODO(greg-lunarg): Add tests to verify handling of these cases:
4255 //
4256 // No optimization in the presence of
4257 // access chains
4258 // function calls
4259 // OpCopyMemory?
4260 // unsupported extensions
4261 // Others?
4262
4263 } // namespace
4264 } // namespace opt
4265 } // namespace spvtools
4266