• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 Valve Corporation
2 // Copyright (c) 2017 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <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,AddDebugValueForFunctionParameterWithPhi)2168 TEST_F(LocalSSAElimTest, AddDebugValueForFunctionParameterWithPhi) {
2169   // Test the distribution of DebugValue for a parameter of an inlined function
2170   // and the visibility of Phi instruction. The ssa-rewrite pass must add
2171   // DebugValue for the value assignment of function argument even when it is an
2172   // inlined function. It has to check the visibility Phi through all its value
2173   // operands. See the DebugValue for "int i" of "foo()" in the following code.
2174   //
2175   // struct VS_OUTPUT {
2176   //   float4 pos : SV_POSITION;
2177   //   float4 color : COLOR;
2178   // };
2179   //
2180   // float4 foo(int i, float4 pos) {
2181   //   while (i < pos.x) {
2182   //     pos = pos.x + i;
2183   //     ++i;
2184   //   }
2185   //   return pos;
2186   // }
2187   //
2188   // VS_OUTPUT main(float4 pos : POSITION,
2189   //                float4 color : COLOR) {
2190   //   VS_OUTPUT vout;
2191   //   vout.pos = foo(4, pos);
2192   //   vout.color = color;
2193   //   return vout;
2194   // }
2195   const std::string text = R"(
2196                OpCapability Shader
2197           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
2198                OpMemoryModel Logical GLSL450
2199                OpEntryPoint Vertex %main "main" %in_var_POSITION %in_var_COLOR %gl_Position %out_var_COLOR
2200           %7 = OpString "vertex.hlsl"
2201           %8 = OpString "float"
2202           %9 = OpString "VS_OUTPUT"
2203          %10 = OpString "color"
2204          %11 = OpString "pos"
2205          %12 = OpString "int"
2206          %13 = OpString "foo"
2207          %14 = OpString ""
2208          %15 = OpString "i"
2209          %16 = OpString "main"
2210          %17 = OpString "vout"
2211                OpName %in_var_POSITION "in.var.POSITION"
2212                OpName %in_var_COLOR "in.var.COLOR"
2213                OpName %out_var_COLOR "out.var.COLOR"
2214                OpName %main "main"
2215                OpName %param_var_pos "param.var.pos"
2216                OpName %param_var_color "param.var.color"
2217                OpName %VS_OUTPUT "VS_OUTPUT"
2218                OpMemberName %VS_OUTPUT 0 "pos"
2219                OpMemberName %VS_OUTPUT 1 "color"
2220                OpDecorate %gl_Position BuiltIn Position
2221                OpDecorate %in_var_POSITION Location 0
2222                OpDecorate %in_var_COLOR Location 1
2223                OpDecorate %out_var_COLOR Location 0
2224         %int = OpTypeInt 32 1
2225       %int_4 = OpConstant %int 4
2226       %int_0 = OpConstant %int 0
2227       %int_1 = OpConstant %int 1
2228        %uint = OpTypeInt 32 0
2229     %uint_32 = OpConstant %uint 32
2230       %float = OpTypeFloat 32
2231     %v4float = OpTypeVector %float 4
2232 %_ptr_Input_v4float = OpTypePointer Input %v4float
2233 %_ptr_Output_v4float = OpTypePointer Output %v4float
2234        %void = OpTypeVoid
2235    %uint_256 = OpConstant %uint 256
2236    %uint_128 = OpConstant %uint 128
2237      %uint_0 = OpConstant %uint 0
2238          %50 = OpTypeFunction %void
2239 %_ptr_Function_v4float = OpTypePointer Function %v4float
2240   %VS_OUTPUT = OpTypeStruct %v4float %v4float
2241 %_ptr_Function_int = OpTypePointer Function %int
2242 %_ptr_Function_float = OpTypePointer Function %float
2243        %bool = OpTypeBool
2244 %in_var_POSITION = OpVariable %_ptr_Input_v4float Input
2245 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
2246 %gl_Position = OpVariable %_ptr_Output_v4float Output
2247 %out_var_COLOR = OpVariable %_ptr_Output_v4float Output
2248         %156 = OpExtInst %void %1 DebugInfoNone
2249          %77 = OpExtInst %void %1 DebugExpression
2250          %58 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 Float
2251          %59 = OpExtInst %void %1 DebugTypeVector %58 4
2252          %60 = OpExtInst %void %1 DebugSource %7
2253          %61 = OpExtInst %void %1 DebugCompilationUnit 1 4 %60 HLSL
2254          %62 = OpExtInst %void %1 DebugTypeComposite %9 Structure %60 1 8 %61 %9 %uint_256 FlagIsProtected|FlagIsPrivate %63 %64
2255          %64 = OpExtInst %void %1 DebugTypeMember %10 %59 %60 3 10 %62 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
2256          %63 = OpExtInst %void %1 DebugTypeMember %11 %59 %60 2 10 %62 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
2257          %65 = OpExtInst %void %1 DebugTypeBasic %12 %uint_32 Signed
2258          %66 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %59 %65 %59
2259          %67 = OpExtInst %void %1 DebugFunction %13 %66 %60 6 1 %61 %14 FlagIsProtected|FlagIsPrivate 6 %156
2260          %68 = OpExtInst %void %1 DebugLexicalBlock %60 6 31 %67
2261          %69 = OpExtInst %void %1 DebugLexicalBlock %60 7 21 %68
2262          %70 = OpExtInst %void %1 DebugLocalVariable %11 %59 %60 6 26 %67 FlagIsLocal 2
2263 
2264 ; CHECK: [[color_name:%\w+]] = OpString "color"
2265 ; CHECK: [[pos_name:%\w+]] = OpString "pos"
2266 ; CHECK: [[i_name:%\w+]] = OpString "i"
2267 ; CHECK: [[null_expr:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugExpression
2268 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]] {{%\w+}} {{%\w+}} 6 16 {{%\w+}} FlagIsLocal 1
2269 ; CHECK: [[dbg_color:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[color_name]] {{%\w+}} {{%\w+}} 15 23
2270 ; CHECK: [[dbg_pos:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[pos_name]] {{%\w+}} {{%\w+}} 14 23
2271          %71 = OpExtInst %void %1 DebugLocalVariable %15 %65 %60 6 16 %67 FlagIsLocal 1
2272          %72 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %62 %59 %59
2273          %73 = OpExtInst %void %1 DebugFunction %16 %72 %60 14 1 %61 %14 FlagIsProtected|FlagIsPrivate 15 %156
2274          %74 = OpExtInst %void %1 DebugLexicalBlock %60 15 38 %73
2275          %75 = OpExtInst %void %1 DebugLocalVariable %17 %62 %60 16 13 %74 FlagIsLocal
2276          %76 = OpExtInst %void %1 DebugLocalVariable %10 %59 %60 15 23 %73 FlagIsLocal 2
2277          %78 = OpExtInst %void %1 DebugLocalVariable %11 %59 %60 14 23 %73 FlagIsLocal 1
2278         %155 = OpExtInst %void %1 DebugInlinedAt 17 %74
2279        %main = OpFunction %void None %50
2280          %79 = OpLabel
2281         %168 = OpExtInst %void %1 DebugScope %74
2282 
2283 ; CHECK: [[i:%\w+]] = OpVariable %_ptr_Function_int Function
2284         %120 = OpVariable %_ptr_Function_int Function
2285         %121 = OpVariable %_ptr_Function_v4float Function
2286         %169 = OpExtInst %void %1 DebugNoScope
2287 %param_var_pos = OpVariable %_ptr_Function_v4float Function
2288 %param_var_color = OpVariable %_ptr_Function_v4float Function
2289                OpLine %7 100 105
2290          %80 = OpLoad %v4float %in_var_POSITION
2291                OpStore %param_var_pos %80
2292                OpNoLine
2293                OpLine %7 200 205
2294          %81 = OpLoad %v4float %in_var_COLOR
2295                OpStore %param_var_color %81
2296                OpNoLine
2297         %170 = OpExtInst %void %1 DebugScope %73
2298 
2299 ; CHECK: OpLine {{%\w+}} 100 105
2300 ; CHECK: DebugValue [[dbg_pos]]
2301         %124 = OpExtInst %void %1 DebugDeclare %78 %param_var_pos %77
2302 ; CHECK: OpLine {{%\w+}} 200 205
2303 ; CHECK: DebugValue [[dbg_color]]
2304         %125 = OpExtInst %void %1 DebugDeclare %76 %param_var_color %77
2305 
2306         %171 = OpExtInst %void %1 DebugScope %74
2307                OpLine %7 17 18
2308 
2309 ; CHECK: OpStore {{%\w+}} %int_4
2310 ; CHECK: DebugValue [[dbg_i]] %int_4 [[null_expr]]
2311                OpStore %120 %int_4
2312                OpStore %121 %80
2313         %172 = OpExtInst %void %1 DebugScope %67 %155
2314         %135 = OpExtInst %void %1 DebugDeclare %71 %120 %77
2315         %136 = OpExtInst %void %1 DebugDeclare %70 %121 %77
2316         %173 = OpExtInst %void %1 DebugScope %68 %155
2317                OpLine %7 7 3
2318                OpBranch %137
2319         %174 = OpExtInst %void %1 DebugNoScope
2320         %137 = OpLabel
2321 
2322 ; CHECK: [[phi:%\w+]] = OpPhi %int %int_4
2323 ; CHECK: DebugValue [[dbg_i]] [[phi]] [[null_expr]]
2324         %175 = OpExtInst %void %1 DebugScope %68 %155
2325                OpLine %7 7 10
2326         %138 = OpLoad %int %120
2327         %139 = OpConvertSToF %float %138
2328                OpLine %7 7 14
2329         %140 = OpAccessChain %_ptr_Function_float %121 %int_0
2330         %141 = OpLoad %float %140
2331                OpLine %7 7 12
2332         %142 = OpFOrdLessThan %bool %139 %141
2333                OpLine %7 7 3
2334         %176 = OpExtInst %void %1 DebugNoScope
2335                OpLoopMerge %153 %152 None
2336                OpBranchConditional %142 %143 %153
2337         %177 = OpExtInst %void %1 DebugNoScope
2338         %143 = OpLabel
2339         %178 = OpExtInst %void %1 DebugScope %69 %155
2340                OpLine %7 8 11
2341         %144 = OpAccessChain %_ptr_Function_float %121 %int_0
2342         %145 = OpLoad %float %144
2343                OpLine %7 8 19
2344         %146 = OpLoad %int %120
2345         %147 = OpConvertSToF %float %146
2346                OpLine %7 8 17
2347         %148 = OpFAdd %float %145 %147
2348                OpLine %7 8 11
2349         %149 = OpCompositeConstruct %v4float %148 %148 %148 %148
2350                OpLine %7 8 5
2351                OpStore %121 %149
2352                OpLine %7 9 5
2353         %151 = OpIAdd %int %146 %int_1
2354                OpLine %7 9 7
2355 
2356 ; CHECK: OpStore [[i]] [[value:%\w+]]
2357 ; CHECK: DebugValue [[dbg_i]] [[value]] [[null_expr]]
2358                OpStore %120 %151
2359         %179 = OpExtInst %void %1 DebugScope %68 %155
2360                OpLine %7 10 3
2361                OpBranch %152
2362         %180 = OpExtInst %void %1 DebugNoScope
2363         %152 = OpLabel
2364         %181 = OpExtInst %void %1 DebugScope %68 %155
2365                OpBranch %137
2366         %182 = OpExtInst %void %1 DebugNoScope
2367         %153 = OpLabel
2368         %183 = OpExtInst %void %1 DebugScope %68 %155
2369                OpLine %7 11 10
2370         %154 = OpLoad %v4float %121
2371         %184 = OpExtInst %void %1 DebugScope %74
2372         %167 = OpExtInst %void %1 DebugValue %75 %154 %77 %int_0
2373         %166 = OpExtInst %void %1 DebugValue %75 %81 %77 %int_1
2374                OpLine %7 19 10
2375         %165 = OpCompositeConstruct %VS_OUTPUT %154 %81
2376         %185 = OpExtInst %void %1 DebugNoScope
2377          %83 = OpCompositeExtract %v4float %165 0
2378                OpStore %gl_Position %83
2379          %84 = OpCompositeExtract %v4float %165 1
2380                OpStore %out_var_COLOR %84
2381                OpReturn
2382                OpFunctionEnd
2383 )";
2384 
2385   SinglePassRunAndMatch<SSARewritePass>(text, true);
2386 }
2387 
TEST_F(LocalSSAElimTest,DebugValueWithIndexesInForLoop)2388 TEST_F(LocalSSAElimTest, DebugValueWithIndexesInForLoop) {
2389   // #version 140
2390   //
2391   // in vec4 BC;
2392   // out float fo;
2393   //
2394   // struct T {
2395   //   float a;
2396   //   float f;
2397   // };
2398   //
2399   // struct value {
2400   //   int x;
2401   //   int y;
2402   //   T z;
2403   // };
2404   //
2405   // void main()
2406   // {
2407   //     value v;
2408   //     v.z.f = 0.0;
2409   //     for (int i=0; i<4; i++) {
2410   //       v.z.f = v.z.f + BC[i];
2411   //     }
2412   //     fo = v.z.f;
2413   // }
2414 
2415   const std::string text = R"(
2416 ; CHECK: [[f_name:%\w+]] = OpString "f"
2417 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2418 
2419 ; CHECK:      OpStore %f %float_0
2420 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0 [[null_expr:%\d+]] %int_2 %int_1
2421 
2422 ; CHECK-NOT:  DebugDeclare
2423 
2424 ; CHECK:      [[loop_head:%\w+]] = OpLabel
2425 ; CHECK:      [[phi0:%\w+]] = OpPhi %float %float_0
2426 ; CHECK:      OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]] [[null_expr]] %int_2 %int_1
2427 ; CHECK:      OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2428 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2429 
2430 ; CHECK-NEXT: [[loop_body]] = OpLabel
2431 ; CHECK:      OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2432 
2433 ; CHECK:      [[bb]] = OpLabel
2434 ; CHECK:      OpStore %f [[f_val:%\w+]]
2435 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]] [[null_expr]] %int_2 %int_1
2436 ; CHECK-NEXT: OpBranch [[loop_cont]]
2437 
2438 ; CHECK: [[loop_cont]] = OpLabel
2439 ; CHECK: OpBranch [[loop_head]]
2440 
2441 ; CHECK: [[loop_merge]] = OpLabel
2442 
2443 OpCapability Shader
2444 %1 = OpExtInstImport "GLSL.std.450"
2445 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2446 OpMemoryModel Logical GLSL450
2447 OpEntryPoint Fragment %main "main" %BC %fo
2448 OpExecutionMode %main OriginUpperLeft
2449 %file_name = OpString "test"
2450 OpSource GLSL 140
2451 %float_name = OpString "float"
2452 %main_name = OpString "main"
2453 %f_name = OpString "f"
2454 %i_name = OpString "i"
2455 OpName %main "main"
2456 OpName %f "f"
2457 OpName %i "i"
2458 OpName %BC "BC"
2459 OpName %fo "fo"
2460 %void = OpTypeVoid
2461 %8 = OpTypeFunction %void
2462 %float = OpTypeFloat 32
2463 %_ptr_Function_float = OpTypePointer Function %float
2464 %float_0 = OpConstant %float 0
2465 %int = OpTypeInt 32 1
2466 %uint = OpTypeInt 32 0
2467 %uint_32 = OpConstant %uint 32
2468 %_ptr_Function_int = OpTypePointer Function %int
2469 %int_0 = OpConstant %int 0
2470 %int_4 = OpConstant %int 4
2471 %bool = OpTypeBool
2472 %v4float = OpTypeVector %float 4
2473 %_ptr_Input_v4float = OpTypePointer Input %v4float
2474 %BC = OpVariable %_ptr_Input_v4float Input
2475 %_ptr_Input_float = OpTypePointer Input %float
2476 %int_1 = OpConstant %int 1
2477 %int_2 = OpConstant %int 2
2478 %_ptr_Output_float = OpTypePointer Output %float
2479 %fo = OpVariable %_ptr_Output_float Output
2480 %deref = OpExtInst %void %ext DebugOperation Deref
2481 %null_expr = OpExtInst %void %ext DebugExpression
2482 %deref_expr = OpExtInst %void %ext DebugExpression %deref
2483 %src = OpExtInst %void %ext DebugSource %file_name
2484 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2485 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2486 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2487 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2488 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2489 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2490 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2491 %main = OpFunction %void None %8
2492 %22 = OpLabel
2493 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2494 %f = OpVariable %_ptr_Function_float Function
2495 %i = OpVariable %_ptr_Function_int Function
2496 OpStore %f %float_0
2497 OpStore %i %int_0
2498 %decl0 = OpExtInst %void %ext DebugValue %dbg_f %f %deref_expr %int_2 %int_1
2499 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2500 OpBranch %23
2501 %23 = OpLabel
2502 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2503 OpLoopMerge %24 %25 None
2504 OpBranch %26
2505 %26 = OpLabel
2506 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2507 %27 = OpLoad %int %i
2508 %28 = OpSLessThan %bool %27 %int_4
2509 OpBranchConditional %28 %29 %24
2510 %29 = OpLabel
2511 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2512 %30 = OpLoad %float %f
2513 %31 = OpLoad %int %i
2514 %32 = OpAccessChain %_ptr_Input_float %BC %31
2515 %33 = OpLoad %float %32
2516 %34 = OpFAdd %float %30 %33
2517 OpStore %f %34
2518 OpBranch %25
2519 %25 = OpLabel
2520 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2521 %35 = OpLoad %int %i
2522 %36 = OpIAdd %int %35 %int_1
2523 OpStore %i %36
2524 OpBranch %23
2525 %24 = OpLabel
2526 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2527 %37 = OpLoad %float %f
2528 OpStore %fo %37
2529 OpReturn
2530 OpFunctionEnd
2531 )";
2532 
2533   SinglePassRunAndMatch<SSARewritePass>(text, true);
2534 }
2535 
TEST_F(LocalSSAElimTest,PartiallyKillDebugDeclare)2536 TEST_F(LocalSSAElimTest, PartiallyKillDebugDeclare) {
2537   // For a reference variable e.g., int i in the following example,
2538   // we do not propagate DebugValue for a store or phi instruction
2539   // out of the variable's scope. In that case, we should not remove
2540   // DebugDeclare for the variable that we did not add its DebugValue.
2541   //
2542   // #version 140
2543   //
2544   // in vec4 BC;
2545   // out float fo;
2546   //
2547   // int j;
2548   // void main()
2549   // {
2550   //     float f = 0.0;
2551   //     for (j=0; j<4; j++) {
2552   //       int& i = j;
2553   //       f = f + BC[i];
2554   //     }
2555   //     fo = f;
2556   // }
2557 
2558   const std::string text = R"(
2559 ; CHECK: [[f_name:%\w+]] = OpString "f"
2560 ; CHECK: [[i_name:%\w+]] = OpString "i"
2561 ; CHECK: [[fn:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugFunction
2562 ; CHECK: [[bb:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2563 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]] {{%\w+}} {{%\w+}} 0 0 [[fn]]
2564 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]] {{%\w+}} {{%\w+}} 0 0 [[bb]]
2565 
2566 ; CHECK:      OpStore %f %float_0
2567 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2568 ; CHECK-NOT:  DebugDeclare [[dbg_f]]
2569 ; CHECK:      OpExtInst %void [[ext]] DebugDeclare [[dbg_i]] %j
2570 
2571 OpCapability Shader
2572 %1 = OpExtInstImport "GLSL.std.450"
2573 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2574 OpMemoryModel Logical GLSL450
2575 OpEntryPoint Fragment %main "main" %BC %fo
2576 OpExecutionMode %main OriginUpperLeft
2577 %file_name = OpString "test"
2578 OpSource GLSL 140
2579 %float_name = OpString "float"
2580 %main_name = OpString "main"
2581 %f_name = OpString "f"
2582 %i_name = OpString "i"
2583 %j_name = OpString "j"
2584 OpName %main "main"
2585 OpName %f "f"
2586 OpName %j "j"
2587 OpName %BC "BC"
2588 OpName %fo "fo"
2589 %void = OpTypeVoid
2590 %8 = OpTypeFunction %void
2591 %float = OpTypeFloat 32
2592 %_ptr_Function_float = OpTypePointer Function %float
2593 %float_0 = OpConstant %float 0
2594 %int = OpTypeInt 32 1
2595 %uint = OpTypeInt 32 0
2596 %uint_32 = OpConstant %uint 32
2597 %_ptr_Function_int = OpTypePointer Function %int
2598 %_ptr_Private_int = OpTypePointer Private %int
2599 %int_0 = OpConstant %int 0
2600 %int_4 = OpConstant %int 4
2601 %bool = OpTypeBool
2602 %v4float = OpTypeVector %float 4
2603 %_ptr_Input_v4float = OpTypePointer Input %v4float
2604 %BC = OpVariable %_ptr_Input_v4float Input
2605 %_ptr_Input_float = OpTypePointer Input %float
2606 %int_1 = OpConstant %int 1
2607 %_ptr_Output_float = OpTypePointer Output %float
2608 %fo = OpVariable %_ptr_Output_float Output
2609 %j = OpVariable %_ptr_Private_int Private
2610 %null_expr = OpExtInst %void %ext DebugExpression
2611 %src = OpExtInst %void %ext DebugSource %file_name
2612 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2613 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2614 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2615 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2616 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2617 %bb = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
2618 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2619 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %bb FlagIsLocal
2620 %dbg_j = OpExtInst %void %ext DebugGlobalVariable %j_name %dbg_v4f %src 0 0 %dbg_main %j_name %j FlagIsPrivate
2621 %main = OpFunction %void None %8
2622 %22 = OpLabel
2623 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2624 %f = OpVariable %_ptr_Function_float Function
2625 OpStore %f %float_0
2626 OpStore %j %int_0
2627 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2628 OpBranch %23
2629 %23 = OpLabel
2630 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2631 OpLoopMerge %24 %25 None
2632 OpBranch %26
2633 %26 = OpLabel
2634 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2635 %27 = OpLoad %int %j
2636 %28 = OpSLessThan %bool %27 %int_4
2637 OpBranchConditional %28 %29 %24
2638 %29 = OpLabel
2639 %s3 = OpExtInst %void %ext DebugScope %bb
2640 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %j %null_expr
2641 %30 = OpLoad %float %f
2642 %31 = OpLoad %int %j
2643 %32 = OpAccessChain %_ptr_Input_float %BC %31
2644 %33 = OpLoad %float %32
2645 %34 = OpFAdd %float %30 %33
2646 OpStore %f %34
2647 OpBranch %25
2648 %25 = OpLabel
2649 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2650 %35 = OpLoad %int %j
2651 %36 = OpIAdd %int %35 %int_1
2652 OpStore %j %36
2653 OpBranch %23
2654 %24 = OpLabel
2655 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2656 %37 = OpLoad %float %f
2657 OpStore %fo %37
2658 OpReturn
2659 OpFunctionEnd
2660 )";
2661 
2662   SinglePassRunAndMatch<SSARewritePass>(text, true);
2663 }
2664 
TEST_F(LocalSSAElimTest,DebugValueForReferenceVariable)2665 TEST_F(LocalSSAElimTest, DebugValueForReferenceVariable) {
2666   // #version 140
2667   //
2668   // in vec4 BC;
2669   // out float fo;
2670   //
2671   // void main()
2672   // {
2673   //     float f = 0.0;
2674   //     float& x = f;
2675   //     for (int i=0; i<4; i++) {
2676   //       x = x + BC[i];
2677   //     }
2678   //     fo = f;
2679   // }
2680 
2681   const std::string text = R"(
2682 ; CHECK: [[f_name:%\w+]] = OpString "f"
2683 ; CHECK: [[i_name:%\w+]] = OpString "i"
2684 ; CHECK: [[x_name:%\w+]] = OpString "x"
2685 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
2686 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2687 ; CHECK: [[dbg_x:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[x_name]]
2688 
2689 ; CHECK:      OpStore %f %float_0
2690 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2691 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_x]] %float_0
2692 ; CHECK:      OpStore %i %int_0
2693 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2694 
2695 ; CHECK-NOT:  DebugDeclare
2696 
2697 ; CHECK:      [[loop_head:%\w+]] = OpLabel
2698 ; CHECK:      [[phi0:%\w+]] = OpPhi %float %float_0
2699 ; CHECK:      [[phi1:%\w+]] = OpPhi %int %int_0
2700 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2701 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[phi0]]
2702 ; CHECK:      OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2703 ; CHECK:      OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2704 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2705 
2706 ; CHECK:      [[loop_body]] = OpLabel
2707 ; CHECK:      OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2708 
2709 ; CHECK:      [[bb]] = OpLabel
2710 ; CHECK:      OpStore %f [[f_val:%\w+]]
2711 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
2712 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[f_val]]
2713 ; CHECK:      OpBranch [[loop_cont]]
2714 
2715 ; CHECK:      [[loop_cont]] = OpLabel
2716 ; CHECK:      OpStore %i [[i_val:%\w+]]
2717 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
2718 ; CHECK-NEXT: OpBranch [[loop_head]]
2719 
2720 ; CHECK:      [[loop_merge]] = OpLabel
2721 
2722 OpCapability Shader
2723 %1 = OpExtInstImport "GLSL.std.450"
2724 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2725 OpMemoryModel Logical GLSL450
2726 OpEntryPoint Fragment %main "main" %BC %fo
2727 OpExecutionMode %main OriginUpperLeft
2728 %file_name = OpString "test"
2729 OpSource GLSL 140
2730 %float_name = OpString "float"
2731 %main_name = OpString "main"
2732 %f_name = OpString "f"
2733 %i_name = OpString "i"
2734 %x_name = OpString "x"
2735 OpName %main "main"
2736 OpName %f "f"
2737 OpName %i "i"
2738 OpName %BC "BC"
2739 OpName %fo "fo"
2740 %void = OpTypeVoid
2741 %8 = OpTypeFunction %void
2742 %float = OpTypeFloat 32
2743 %_ptr_Function_float = OpTypePointer Function %float
2744 %float_0 = OpConstant %float 0
2745 %int = OpTypeInt 32 1
2746 %uint = OpTypeInt 32 0
2747 %uint_32 = OpConstant %uint 32
2748 %_ptr_Function_int = OpTypePointer Function %int
2749 %int_0 = OpConstant %int 0
2750 %int_4 = OpConstant %int 4
2751 %bool = OpTypeBool
2752 %v4float = OpTypeVector %float 4
2753 %_ptr_Input_v4float = OpTypePointer Input %v4float
2754 %BC = OpVariable %_ptr_Input_v4float Input
2755 %_ptr_Input_float = OpTypePointer Input %float
2756 %int_1 = OpConstant %int 1
2757 %_ptr_Output_float = OpTypePointer Output %float
2758 %fo = OpVariable %_ptr_Output_float Output
2759 %null_expr = OpExtInst %void %ext DebugExpression
2760 %src = OpExtInst %void %ext DebugSource %file_name
2761 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2762 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2763 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2764 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2765 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2766 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2767 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
2768 %dbg_x = OpExtInst %void %ext DebugLocalVariable %x_name %dbg_v4f %src 2 0 %dbg_main FlagIsLocal
2769 %main = OpFunction %void None %8
2770 %22 = OpLabel
2771 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2772 %f = OpVariable %_ptr_Function_float Function
2773 %i = OpVariable %_ptr_Function_int Function
2774 OpStore %f %float_0
2775 OpStore %i %int_0
2776 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2777 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2778 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_x %f %null_expr
2779 OpBranch %23
2780 %23 = OpLabel
2781 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2782 OpLoopMerge %24 %25 None
2783 OpBranch %26
2784 %26 = OpLabel
2785 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2786 %27 = OpLoad %int %i
2787 %28 = OpSLessThan %bool %27 %int_4
2788 OpBranchConditional %28 %29 %24
2789 %29 = OpLabel
2790 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2791 %30 = OpLoad %float %f
2792 %31 = OpLoad %int %i
2793 %32 = OpAccessChain %_ptr_Input_float %BC %31
2794 %33 = OpLoad %float %32
2795 %34 = OpFAdd %float %30 %33
2796 OpStore %f %34
2797 OpBranch %25
2798 %25 = OpLabel
2799 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2800 %35 = OpLoad %int %i
2801 %36 = OpIAdd %int %35 %int_1
2802 OpStore %i %36
2803 OpBranch %23
2804 %24 = OpLabel
2805 %s5 = OpExtInst %void %ext DebugScope %dbg_main
2806 %37 = OpLoad %float %f
2807 OpStore %fo %37
2808 OpReturn
2809 OpFunctionEnd
2810 )";
2811 
2812   SinglePassRunAndMatch<SSARewritePass>(text, true);
2813 }
2814 
TEST_F(LocalSSAElimTest,DebugValueForReferenceVariableInBB)2815 TEST_F(LocalSSAElimTest, DebugValueForReferenceVariableInBB) {
2816   // #version 140
2817   //
2818   // in vec4 BC;
2819   // out float fo;
2820   //
2821   // void main()
2822   // {
2823   //     float f = 0.0;
2824   //     for (int i=0; i<4; i++) {
2825   //       float& x = f;
2826   //       x = x + BC[i];
2827   //       {
2828   //         x = x + BC[i];
2829   //       }
2830   //     }
2831   //     fo = f;
2832   // }
2833 
2834   const std::string text = R"(
2835 ; CHECK: [[f_name:%\w+]] = OpString "f"
2836 ; CHECK: [[i_name:%\w+]] = OpString "i"
2837 ; CHECK: [[x_name:%\w+]] = OpString "x"
2838 ; CHECK: [[dbg_main:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugFunction
2839 ; CHECK: [[dbg_bb:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2840 ; CHECK: [[dbg_bb_child:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
2841 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]]
2842 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
2843 ; CHECK: [[dbg_x:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[x_name]]
2844 
2845 ; CHECK:      OpExtInst %void [[ext]] DebugScope [[dbg_main]]
2846 ; CHECK:      OpStore %f %float_0
2847 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
2848 ; CHECK-NEXT: OpStore %i %int_0
2849 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %int_0
2850 
2851 ; CHECK-NOT:  DebugDeclare
2852 
2853 ; CHECK:      [[loop_head:%\w+]] = OpLabel
2854 ; CHECK:      OpExtInst %void [[ext]] DebugScope [[dbg_main]]
2855 ; CHECK:      [[phi0:%\w+]] = OpPhi %float %float_0
2856 ; CHECK:      [[phi1:%\w+]] = OpPhi %int %int_0
2857 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[phi0]]
2858 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[phi0]]
2859 ; CHECK-DAG: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi1]]
2860 ; CHECK:      OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
2861 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
2862 
2863 ; CHECK-NEXT: [[loop_body]] = OpLabel
2864 ; CHECK:      OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
2865 
2866 ; CHECK:      [[bb]] = OpLabel
2867 ; CHECK:      OpExtInst %void [[ext]] DebugScope [[dbg_bb]]
2868 ; CHECK:      OpStore %f [[f_val:%\w+]]
2869 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_val]]
2870 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[f_val]]
2871 ; CHECK:      OpBranch [[bb_child:%\w+]]
2872 
2873 ; CHECK:      [[bb_child]] = OpLabel
2874 ; CHECK:      OpExtInst %void [[ext]] DebugScope [[dbg_bb_child]]
2875 ; CHECK:      OpStore %f [[new_f_val:%\w+]]
2876 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[new_f_val]]
2877 ; CHECK-DAG:  OpExtInst %void [[ext]] DebugValue [[dbg_x]] [[new_f_val]]
2878 ; CHECK:      OpBranch [[loop_cont]]
2879 
2880 ; CHECK:      [[loop_cont]] = OpLabel
2881 ; CHECK:      OpStore %i [[i_val:%\w+]]
2882 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[i_val]]
2883 ; CHECK-NEXT: OpBranch [[loop_head]]
2884 
2885 ; CHECK:      [[loop_merge]] = OpLabel
2886 
2887 OpCapability Shader
2888 %1 = OpExtInstImport "GLSL.std.450"
2889 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2890 OpMemoryModel Logical GLSL450
2891 OpEntryPoint Fragment %main "main" %BC %fo
2892 OpExecutionMode %main OriginUpperLeft
2893 %file_name = OpString "test"
2894 OpSource GLSL 140
2895 %float_name = OpString "float"
2896 %main_name = OpString "main"
2897 %f_name = OpString "f"
2898 %i_name = OpString "i"
2899 %x_name = OpString "x"
2900 OpName %main "main"
2901 OpName %f "f"
2902 OpName %i "i"
2903 OpName %BC "BC"
2904 OpName %fo "fo"
2905 %void = OpTypeVoid
2906 %8 = OpTypeFunction %void
2907 %float = OpTypeFloat 32
2908 %_ptr_Function_float = OpTypePointer Function %float
2909 %float_0 = OpConstant %float 0
2910 %int = OpTypeInt 32 1
2911 %uint = OpTypeInt 32 0
2912 %uint_32 = OpConstant %uint 32
2913 %_ptr_Function_int = OpTypePointer Function %int
2914 %int_0 = OpConstant %int 0
2915 %int_4 = OpConstant %int 4
2916 %bool = OpTypeBool
2917 %v4float = OpTypeVector %float 4
2918 %_ptr_Input_v4float = OpTypePointer Input %v4float
2919 %BC = OpVariable %_ptr_Input_v4float Input
2920 %_ptr_Input_float = OpTypePointer Input %float
2921 %int_1 = OpConstant %int 1
2922 %_ptr_Output_float = OpTypePointer Output %float
2923 %fo = OpVariable %_ptr_Output_float Output
2924 %null_expr = OpExtInst %void %ext DebugExpression
2925 %src = OpExtInst %void %ext DebugSource %file_name
2926 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
2927 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
2928 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
2929 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
2930 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
2931 %bb = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
2932 %bb_child = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %bb
2933 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
2934 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
2935 %dbg_x = OpExtInst %void %ext DebugLocalVariable %x_name %dbg_v4f %src 2 0 %bb FlagIsLocal
2936 %main = OpFunction %void None %8
2937 %22 = OpLabel
2938 %s0 = OpExtInst %void %ext DebugScope %dbg_main
2939 %f = OpVariable %_ptr_Function_float Function
2940 %i = OpVariable %_ptr_Function_int Function
2941 OpStore %f %float_0
2942 OpStore %i %int_0
2943 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
2944 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %i %null_expr
2945 OpBranch %23
2946 %23 = OpLabel
2947 %s1 = OpExtInst %void %ext DebugScope %dbg_main
2948 OpLoopMerge %24 %25 None
2949 OpBranch %26
2950 %26 = OpLabel
2951 %s2 = OpExtInst %void %ext DebugScope %dbg_main
2952 %27 = OpLoad %int %i
2953 %28 = OpSLessThan %bool %27 %int_4
2954 OpBranchConditional %28 %29 %24
2955 %29 = OpLabel
2956 %scope = OpExtInst %void %ext DebugScope %bb
2957 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_x %f %null_expr
2958 %30 = OpLoad %float %f
2959 %31 = OpLoad %int %i
2960 %32 = OpAccessChain %_ptr_Input_float %BC %31
2961 %33 = OpLoad %float %32
2962 %34 = OpFAdd %float %30 %33
2963 OpStore %f %34
2964 OpBranch %38
2965 %38 = OpLabel
2966 %child_scope = OpExtInst %void %ext DebugScope %bb_child
2967 %39 = OpLoad %float %f
2968 %40 = OpFAdd %float %39 %33
2969 OpStore %f %40
2970 OpBranch %25
2971 %25 = OpLabel
2972 %s3 = OpExtInst %void %ext DebugScope %dbg_main
2973 %35 = OpLoad %int %i
2974 %36 = OpIAdd %int %35 %int_1
2975 OpStore %i %36
2976 OpBranch %23
2977 %24 = OpLabel
2978 %s4 = OpExtInst %void %ext DebugScope %dbg_main
2979 %37 = OpLoad %float %f
2980 OpStore %fo %37
2981 OpReturn
2982 OpFunctionEnd
2983 )";
2984 
2985   SinglePassRunAndMatch<SSARewritePass>(text, true);
2986 }
2987 
TEST_F(LocalSSAElimTest,DebugForLoopUseDebugValueInsteadOfDebugDeclare)2988 TEST_F(LocalSSAElimTest, DebugForLoopUseDebugValueInsteadOfDebugDeclare) {
2989   // #version 140
2990   //
2991   // in vec4 BC;
2992   // out float fo;
2993   //
2994   // struct S {
2995   //     float f;
2996   //     int i;
2997   // };
2998   //
2999   // void main()
3000   // {
3001   //     S foo = {0.0, 0};
3002   //     for (; foo.i<4; foo.i++) {
3003   //       foo.f = foo.f + BC[foo.i];
3004   //     }
3005   //     fo = foo.f;
3006   // }
3007 
3008   const std::string text = R"(
3009 ; CHECK: [[f_name:%\w+]] = OpString "f"
3010 ; CHECK: [[empty_expr:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugExpression
3011 ; CHECK: [[deref_op:%\w+]] = OpExtInst %void [[ext]] DebugOperation Deref
3012 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref_op]]
3013 ; CHECK: [[dbg_foo:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]]
3014 
3015 ; CHECK:      OpStore %f %float_0
3016 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] %float_0 [[empty_expr]] %uint_0
3017 ; CHECK-NEXT: OpStore %i %int_0
3018 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] %int_0 [[empty_expr]] %uint_1
3019 
3020 ; CHECK:      [[loop_head:%\w+]] = OpLabel
3021 ; CHECK:      [[phi0:%\w+]] = OpPhi %float %float_0
3022 ; CHECK:      [[phi1:%\w+]] = OpPhi %int %int_0
3023 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[phi0]] [[empty_expr]] %uint_0
3024 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[phi1]] [[empty_expr]] %uint_1
3025 ; CHECK:      OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]] None
3026 ; CHECK-NEXT: OpBranch [[loop_body:%\w+]]
3027 
3028 ; CHECK:      [[loop_body]] = OpLabel
3029 ; CHECK:      OpBranchConditional {{%\w+}} [[bb:%\w+]] [[loop_merge]]
3030 
3031 ; CHECK:      [[bb]] = OpLabel
3032 ; CHECK:      OpStore %f [[f_val:%\w+]]
3033 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[f_val]] [[empty_expr]] %uint_0
3034 ; CHECK-NEXT: OpBranch [[loop_cont]]
3035 
3036 ; CHECK:      [[loop_cont]] = OpLabel
3037 ; CHECK:      OpStore %i [[i_val:%\w+]]
3038 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_foo]] [[i_val]] [[empty_expr]] %uint_1
3039 ; CHECK-NEXT: OpBranch [[loop_head]]
3040 
3041 OpCapability Shader
3042 %1 = OpExtInstImport "GLSL.std.450"
3043 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3044 OpMemoryModel Logical GLSL450
3045 OpEntryPoint Fragment %main "main" %BC %fo
3046 OpExecutionMode %main OriginUpperLeft
3047 %file_name = OpString "test"
3048 OpSource GLSL 140
3049 %float_name = OpString "float"
3050 %main_name = OpString "main"
3051 %f_name = OpString "f"
3052 OpName %main "main"
3053 OpName %f "f"
3054 OpName %i "i"
3055 OpName %BC "BC"
3056 OpName %fo "fo"
3057 %void = OpTypeVoid
3058 %8 = OpTypeFunction %void
3059 %float = OpTypeFloat 32
3060 %_ptr_Function_float = OpTypePointer Function %float
3061 %float_0 = OpConstant %float 0
3062 %int = OpTypeInt 32 1
3063 %uint = OpTypeInt 32 0
3064 %uint_32 = OpConstant %uint 32
3065 %uint_0 = OpConstant %uint 0
3066 %uint_1 = OpConstant %uint 1
3067 %_ptr_Function_int = OpTypePointer Function %int
3068 %int_0 = OpConstant %int 0
3069 %int_4 = OpConstant %int 4
3070 %bool = OpTypeBool
3071 %v4float = OpTypeVector %float 4
3072 %_ptr_Input_v4float = OpTypePointer Input %v4float
3073 %BC = OpVariable %_ptr_Input_v4float Input
3074 %_ptr_Input_float = OpTypePointer Input %float
3075 %int_1 = OpConstant %int 1
3076 %_ptr_Output_float = OpTypePointer Output %float
3077 %fo = OpVariable %_ptr_Output_float Output
3078 %deref_op = OpExtInst %void %ext DebugOperation Deref
3079 %deref = OpExtInst %void %ext DebugExpression %deref_op
3080 %src = OpExtInst %void %ext DebugSource %file_name
3081 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3082 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3083 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
3084 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
3085 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3086 %dbg_foo = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
3087 %main = OpFunction %void None %8
3088 %22 = OpLabel
3089 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3090 %f = OpVariable %_ptr_Function_float Function
3091 %i = OpVariable %_ptr_Function_int Function
3092 OpStore %f %float_0
3093 OpStore %i %int_0
3094 %decl0 = OpExtInst %void %ext DebugValue %dbg_foo %f %deref %uint_0
3095 %decl1 = OpExtInst %void %ext DebugValue %dbg_foo %i %deref %uint_1
3096 OpBranch %23
3097 %23 = OpLabel
3098 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3099 OpLoopMerge %24 %25 None
3100 OpBranch %26
3101 %26 = OpLabel
3102 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3103 %27 = OpLoad %int %i
3104 %28 = OpSLessThan %bool %27 %int_4
3105 OpBranchConditional %28 %29 %24
3106 %29 = OpLabel
3107 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3108 %30 = OpLoad %float %f
3109 %31 = OpLoad %int %i
3110 %32 = OpAccessChain %_ptr_Input_float %BC %31
3111 %33 = OpLoad %float %32
3112 %34 = OpFAdd %float %30 %33
3113 OpStore %f %34
3114 OpBranch %25
3115 %25 = OpLabel
3116 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3117 %35 = OpLoad %int %i
3118 %36 = OpIAdd %int %35 %int_1
3119 OpStore %i %36
3120 OpBranch %23
3121 %24 = OpLabel
3122 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3123 %37 = OpLoad %float %f
3124 OpStore %fo %37
3125 OpReturn
3126 OpFunctionEnd
3127 )";
3128 
3129   SinglePassRunAndMatch<SSARewritePass>(text, true);
3130 }
3131 
TEST_F(LocalSSAElimTest,DebugValueNotUsedForDebugDeclare)3132 TEST_F(LocalSSAElimTest, DebugValueNotUsedForDebugDeclare) {
3133   // #version 140
3134   //
3135   // in vec4 BC;
3136   // out float fo;
3137   //
3138   // void main()
3139   // {
3140   //     float f = 0.0;
3141   //     for (int i=0; i<4; i++) {
3142   //       f = f + BC[i];
3143   //     }
3144   //     fo = f;
3145   // }
3146 
3147   const std::string text = R"(
3148 ; CHECK: [[f_name:%\w+]] = OpString "f"
3149 ; CHECK: [[i_name:%\w+]] = OpString "i"
3150 ; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugLocalVariable [[f_name]]
3151 ; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]]
3152 
3153 ; CHECK:      OpStore %f %float_0
3154 ; CHECK-NEXT: OpStore %i %int_0
3155 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %f
3156 ; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_i]] %i
3157 
3158 ; CHECK-NOT:  DebugValue
3159 ; CHECK-NOT:  DebugDeclare
3160 
3161 OpCapability Shader
3162 %1 = OpExtInstImport "GLSL.std.450"
3163 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3164 OpMemoryModel Logical GLSL450
3165 OpEntryPoint Fragment %main "main" %BC %fo
3166 OpExecutionMode %main OriginUpperLeft
3167 %file_name = OpString "test"
3168 OpSource GLSL 140
3169 %float_name = OpString "float"
3170 %main_name = OpString "main"
3171 %f_name = OpString "f"
3172 %i_name = OpString "i"
3173 OpName %main "main"
3174 OpName %f "f"
3175 OpName %i "i"
3176 OpName %BC "BC"
3177 OpName %fo "fo"
3178 %void = OpTypeVoid
3179 %8 = OpTypeFunction %void
3180 %float = OpTypeFloat 32
3181 %_ptr_Function_float = OpTypePointer Function %float
3182 %float_0 = OpConstant %float 0
3183 %int = OpTypeInt 32 1
3184 %uint = OpTypeInt 32 0
3185 %uint_32 = OpConstant %uint 32
3186 %_ptr_Function_int = OpTypePointer Function %int
3187 %int_0 = OpConstant %int 0
3188 %int_4 = OpConstant %int 4
3189 %bool = OpTypeBool
3190 %v4float = OpTypeVector %float 4
3191 %_ptr_Input_v4float = OpTypePointer Input %v4float
3192 %BC = OpVariable %_ptr_Input_v4float Input
3193 %_ptr_Input_float = OpTypePointer Input %float
3194 %int_1 = OpConstant %int 1
3195 %_ptr_Output_float = OpTypePointer Output %float
3196 %fo = OpVariable %_ptr_Output_float Output
3197 %null_expr = OpExtInst %void %ext DebugExpression
3198 %src = OpExtInst %void %ext DebugSource %file_name
3199 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3200 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3201 %dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
3202 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
3203 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3204 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
3205 %dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 1 0 %dbg_main FlagIsLocal
3206 %main = OpFunction %void None %8
3207 %22 = OpLabel
3208 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3209 %f = OpVariable %_ptr_Function_float Function
3210 %i = OpVariable %_ptr_Function_int Function
3211 OpStore %f %float_0
3212 OpStore %i %int_0
3213 %decl0 = OpExtInst %void %ext DebugValue %dbg_f %f %null_expr
3214 %decl1 = OpExtInst %void %ext DebugValue %dbg_i %i %null_expr
3215 OpBranch %23
3216 %23 = OpLabel
3217 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3218 OpLoopMerge %24 %25 None
3219 OpBranch %26
3220 %26 = OpLabel
3221 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3222 %27 = OpLoad %int %i
3223 %28 = OpSLessThan %bool %27 %int_4
3224 OpBranchConditional %28 %29 %24
3225 %29 = OpLabel
3226 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3227 %30 = OpLoad %float %f
3228 %31 = OpLoad %int %i
3229 %32 = OpAccessChain %_ptr_Input_float %BC %31
3230 %33 = OpLoad %float %32
3231 %34 = OpFAdd %float %30 %33
3232 OpStore %f %34
3233 OpBranch %25
3234 %25 = OpLabel
3235 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3236 %35 = OpLoad %int %i
3237 %36 = OpIAdd %int %35 %int_1
3238 OpStore %i %36
3239 OpBranch %23
3240 %24 = OpLabel
3241 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3242 %37 = OpLoad %float %f
3243 OpStore %fo %37
3244 OpReturn
3245 OpFunctionEnd
3246 )";
3247 
3248   SinglePassRunAndMatch<SSARewritePass>(text, true);
3249 }
3250 
TEST_F(LocalSSAElimTest,DebugNestedForLoop)3251 TEST_F(LocalSSAElimTest, DebugNestedForLoop) {
3252   const std::string text = R"(
3253 ; CHECK: = OpFunction
3254 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3255 ; CHECK: OpStore %f %float_0
3256 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f:%\w+]] %float_0
3257 
3258 ; CHECK: [[outer_header:%\w+]] = OpLabel
3259 ; CHECK: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[outer_be:%\w+]]
3260 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[outer_f]]
3261 
3262 ; CHECK: [[inner_pre_header:%\w+]] = OpLabel
3263 ; CHECK: [[inner_header:%\w+]] = OpLabel
3264 ; CHECK: [[inner_f]] = OpPhi %float [[outer_f]] [[inner_pre_header]] [[f_next:%\w+]] [[inner_be:%\w+]]
3265 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[inner_f]]
3266 
3267 ; CHECK: [[inner_be]] = OpLabel
3268 ; CHECK: [[f_next]] = OpFAdd %float [[inner_f]]
3269 ; CHECK-NEXT: OpStore %f [[f_next]]
3270 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_next]]
3271 
3272 OpCapability Shader
3273 %1 = OpExtInstImport "GLSL.std.450"
3274 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3275 OpMemoryModel Logical GLSL450
3276 OpEntryPoint Fragment %main "main" %BC %fo
3277 OpExecutionMode %main OriginUpperLeft
3278 %file_name = OpString "test"
3279 %float_name = OpString "float"
3280 %main_name = OpString "main"
3281 %f_name = OpString "f"
3282 OpSource GLSL 450
3283 OpName %main "main"
3284 OpName %f "f"
3285 OpName %i "i"
3286 OpName %j "j"
3287 OpName %BC "BC"
3288 OpName %fo "fo"
3289 OpDecorate %BC Location 0
3290 OpDecorate %fo Location 0
3291 %void = OpTypeVoid
3292 %9 = OpTypeFunction %void
3293 %float = OpTypeFloat 32
3294 %_ptr_Function_float = OpTypePointer Function %float
3295 %float_0 = OpConstant %float 0
3296 %int = OpTypeInt 32 1
3297 %_ptr_Function_int = OpTypePointer Function %int
3298 %int_0 = OpConstant %int 0
3299 %int_4 = OpConstant %int 4
3300 %uint = OpTypeInt 32 0
3301 %uint_32 = OpConstant %uint 32
3302 %bool = OpTypeBool
3303 %v4float = OpTypeVector %float 4
3304 %mat4v4float = OpTypeMatrix %v4float 4
3305 %_ptr_Input_mat4v4float = OpTypePointer Input %mat4v4float
3306 %BC = OpVariable %_ptr_Input_mat4v4float Input
3307 %_ptr_Input_float = OpTypePointer Input %float
3308 %int_1 = OpConstant %int 1
3309 %_ptr_Output_float = OpTypePointer Output %float
3310 %fo = OpVariable %_ptr_Output_float Output
3311 
3312 ; Debug information
3313 %null_expr = OpExtInst %void %ext DebugExpression
3314 %src = OpExtInst %void %ext DebugSource %file_name
3315 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3316 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3317 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3318 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3319 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3320 
3321 %main = OpFunction %void None %9
3322 %24 = OpLabel
3323 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3324 %f = OpVariable %_ptr_Function_float Function
3325 %i = OpVariable %_ptr_Function_int Function
3326 %j = OpVariable %_ptr_Function_int Function
3327 
3328 ; DebugDeclare
3329 OpStore %f %float_0
3330 %decl = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
3331 
3332 OpStore %i %int_0
3333 OpBranch %25
3334 %25 = OpLabel
3335 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3336 %26 = OpLoad %int %i
3337 %27 = OpSLessThan %bool %26 %int_4
3338 OpLoopMerge %28 %29 None
3339 OpBranchConditional %27 %30 %28
3340 %30 = OpLabel
3341 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3342 OpStore %j %int_0
3343 OpBranch %31
3344 %31 = OpLabel
3345 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3346 %32 = OpLoad %int %j
3347 %33 = OpSLessThan %bool %32 %int_4
3348 OpLoopMerge %50 %34 None
3349 OpBranchConditional %33 %34 %50
3350 %34 = OpLabel
3351 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3352 %35 = OpLoad %float %f
3353 %36 = OpLoad %int %i
3354 %37 = OpLoad %int %j
3355 %38 = OpAccessChain %_ptr_Input_float %BC %36 %37
3356 %39 = OpLoad %float %38
3357 %40 = OpFAdd %float %35 %39
3358 OpStore %f %40
3359 %41 = OpLoad %int %j
3360 %42 = OpIAdd %int %41 %int_1
3361 OpStore %j %42
3362 OpBranch %31
3363 %50 = OpLabel
3364 %s6 = OpExtInst %void %ext DebugScope %dbg_main
3365 OpBranch %29
3366 %29 = OpLabel
3367 %s7 = OpExtInst %void %ext DebugScope %dbg_main
3368 %43 = OpLoad %int %i
3369 %44 = OpIAdd %int %43 %int_1
3370 OpStore %i %44
3371 OpBranch %25
3372 %28 = OpLabel
3373 %s8 = OpExtInst %void %ext DebugScope %dbg_main
3374 %45 = OpLoad %float %f
3375 OpStore %fo %45
3376 OpReturn
3377 OpFunctionEnd
3378 )";
3379 
3380   SinglePassRunAndMatch<SSARewritePass>(text, true);
3381 }
3382 
TEST_F(LocalSSAElimTest,DebugForLoopWithContinue)3383 TEST_F(LocalSSAElimTest, DebugForLoopWithContinue) {
3384   const std::string text = R"(
3385 ; CHECK: = OpFunction
3386 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3387 ; CHECK: OpStore %f %float_0
3388 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f:%\w+]] %float_0
3389 
3390 ; CHECK: [[outer_header:%\w+]] = OpLabel
3391 ; CHECK: [[outer_f:%\w+]] = OpPhi %float %float_0 [[entry]] [[inner_f:%\w+]] [[cont:%\w+]]
3392 ; CHECK: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[outer_f]]
3393 
3394 ; CHECK: [[f_next:%\w+]] = OpFAdd %float [[outer_f]]
3395 ; CHECK-NEXT: OpStore %f [[f_next]]
3396 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[f_next]]
3397 
3398 ; CHECK: [[cont]] = OpLabel
3399 ; CHECK: [[inner_f]] = OpPhi %float [[outer_f]] {{%\d+}} [[f_next]] {{%\d+}}
3400 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f]] [[inner_f]]
3401 
3402 OpCapability Shader
3403 %1 = OpExtInstImport "GLSL.std.450"
3404 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3405 OpMemoryModel Logical GLSL450
3406 OpEntryPoint Fragment %main "main" %BC %fo
3407 OpExecutionMode %main OriginUpperLeft
3408 %file_name = OpString "test"
3409 %float_name = OpString "float"
3410 %main_name = OpString "main"
3411 %f_name = OpString "f"
3412 OpSource GLSL 140
3413 OpName %main "main"
3414 OpName %f "f"
3415 OpName %i "i"
3416 OpName %t "t"
3417 OpName %BC "BC"
3418 OpName %fo "fo"
3419 %void = OpTypeVoid
3420 %9 = OpTypeFunction %void
3421 %float = OpTypeFloat 32
3422 %_ptr_Function_float = OpTypePointer Function %float
3423 %float_0 = OpConstant %float 0
3424 %int = OpTypeInt 32 1
3425 %_ptr_Function_int = OpTypePointer Function %int
3426 %int_0 = OpConstant %int 0
3427 %int_4 = OpConstant %int 4
3428 %uint = OpTypeInt 32 0
3429 %uint_32 = OpConstant %uint 32
3430 %bool = OpTypeBool
3431 %v4float = OpTypeVector %float 4
3432 %_ptr_Input_v4float = OpTypePointer Input %v4float
3433 %BC = OpVariable %_ptr_Input_v4float Input
3434 %_ptr_Input_float = OpTypePointer Input %float
3435 %int_1 = OpConstant %int 1
3436 %_ptr_Output_float = OpTypePointer Output %float
3437 %fo = OpVariable %_ptr_Output_float Output
3438 
3439 ; Debug information
3440 %null_expr = OpExtInst %void %ext DebugExpression
3441 %src = OpExtInst %void %ext DebugSource %file_name
3442 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3443 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3444 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3445 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3446 %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3447 
3448 %main = OpFunction %void None %9
3449 %23 = OpLabel
3450 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3451 %f = OpVariable %_ptr_Function_float Function
3452 %i = OpVariable %_ptr_Function_int Function
3453 %t = OpVariable %_ptr_Function_float Function
3454 
3455 ; DebugDeclare
3456 OpStore %f %float_0
3457 %decl = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
3458 
3459 OpStore %i %int_0
3460 OpBranch %24
3461 %24 = OpLabel
3462 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3463 OpLoopMerge %25 %26 None
3464 OpBranch %27
3465 %27 = OpLabel
3466 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3467 %28 = OpLoad %int %i
3468 %29 = OpSLessThan %bool %28 %int_4
3469 OpBranchConditional %29 %30 %25
3470 %30 = OpLabel
3471 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3472 %31 = OpLoad %int %i
3473 %32 = OpAccessChain %_ptr_Input_float %BC %31
3474 %33 = OpLoad %float %32
3475 OpStore %t %33
3476 %34 = OpLoad %float %t
3477 %35 = OpFOrdLessThan %bool %34 %float_0
3478 OpSelectionMerge %36 None
3479 OpBranchConditional %35 %37 %36
3480 %37 = OpLabel
3481 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3482 OpBranch %26
3483 %36 = OpLabel
3484 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3485 %38 = OpLoad %float %f
3486 %39 = OpLoad %float %t
3487 %40 = OpFAdd %float %38 %39
3488 OpStore %f %40
3489 OpBranch %26
3490 %26 = OpLabel
3491 %s6 = OpExtInst %void %ext DebugScope %dbg_main
3492 %41 = OpLoad %int %i
3493 %42 = OpIAdd %int %41 %int_1
3494 OpStore %i %42
3495 OpBranch %24
3496 %25 = OpLabel
3497 %s7 = OpExtInst %void %ext DebugScope %dbg_main
3498 %43 = OpLoad %float %f
3499 OpStore %fo %43
3500 OpReturn
3501 OpFunctionEnd
3502 )";
3503 
3504   SinglePassRunAndMatch<SSARewritePass>(text, true);
3505 }
3506 
TEST_F(LocalSSAElimTest,DebugIfElse)3507 TEST_F(LocalSSAElimTest, DebugIfElse) {
3508   const std::string text = R"(
3509 OpCapability Shader
3510 %1 = OpExtInstImport "GLSL.std.450"
3511 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3512 OpMemoryModel Logical GLSL450
3513 OpEntryPoint Fragment %main "main" %f %BaseColor %gl_FragColor
3514 OpExecutionMode %main OriginUpperLeft
3515 %file_name = OpString "test"
3516 %float_name = OpString "float"
3517 %main_name = OpString "main"
3518 %v_name = OpString "v"
3519 OpSource GLSL 140
3520 OpName %main "main"
3521 OpName %f "f"
3522 OpName %v "v"
3523 OpName %BaseColor "BaseColor"
3524 OpName %gl_FragColor "gl_FragColor"
3525 %void = OpTypeVoid
3526 %8 = OpTypeFunction %void
3527 %float = OpTypeFloat 32
3528 %_ptr_Input_float = OpTypePointer Input %float
3529 %f = OpVariable %_ptr_Input_float Input
3530 %float_0 = OpConstant %float 0
3531 %uint = OpTypeInt 32 0
3532 %uint_32 = OpConstant %uint 32
3533 %bool = OpTypeBool
3534 %v4float = OpTypeVector %float 4
3535 %_ptr_Function_v4float = OpTypePointer Function %v4float
3536 %_ptr_Input_v4float = OpTypePointer Input %v4float
3537 %BaseColor = OpVariable %_ptr_Input_v4float Input
3538 %float_0_5 = OpConstant %float 0.5
3539 %float_1 = OpConstant %float 1
3540 %18 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
3541 %_ptr_Output_v4float = OpTypePointer Output %v4float
3542 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
3543 
3544 ; Debug information
3545 %null_expr = OpExtInst %void %ext DebugExpression
3546 %src = OpExtInst %void %ext DebugSource %file_name
3547 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3548 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3549 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3550 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3551 %dbg_v = OpExtInst %void %ext DebugLocalVariable %v_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3552 
3553 %main = OpFunction %void None %8
3554 %20 = OpLabel
3555 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3556 
3557 ; DebugDeclare
3558 %v = OpVariable %_ptr_Function_v4float Function
3559 %decl = OpExtInst %void %ext DebugDeclare %dbg_v %v %null_expr
3560 
3561 %21 = OpLoad %float %f
3562 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
3563 OpSelectionMerge %23 None
3564 OpBranchConditional %22 %24 %25
3565 
3566 ; CHECK: OpBranchConditional
3567 ; CHECK-NEXT: [[br0:%\w+]] = OpLabel
3568 ; CHECK: OpStore %v [[v0:%\w+]]
3569 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_v:%\w+]] [[v0]]
3570 %24 = OpLabel
3571 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3572 %26 = OpLoad %v4float %BaseColor
3573 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
3574 OpStore %v %27
3575 OpBranch %23
3576 
3577 ; CHECK: [[br1:%\w+]] = OpLabel
3578 ; CHECK: OpStore %v [[v1:%\w+]]
3579 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v1]]
3580 %25 = OpLabel
3581 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3582 %28 = OpLoad %v4float %BaseColor
3583 %29 = OpFAdd %v4float %28 %18
3584 OpStore %v %29
3585 OpBranch %23
3586 
3587 ; CHECK: [[phi:%\w+]] = OpPhi %v4float [[v0]] [[br0]] [[v1]] [[br1]]
3588 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi]]
3589 %23 = OpLabel
3590 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3591 %30 = OpLoad %v4float %v
3592 OpStore %gl_FragColor %30
3593 OpReturn
3594 OpFunctionEnd
3595 )";
3596 
3597   SinglePassRunAndMatch<SSARewritePass>(text, true);
3598 }
3599 
TEST_F(LocalSSAElimTest,DebugSwitch)3600 TEST_F(LocalSSAElimTest, DebugSwitch) {
3601   const std::string text = R"(
3602 OpCapability Shader
3603 %1 = OpExtInstImport "GLSL.std.450"
3604 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3605 OpMemoryModel Logical GLSL450
3606 OpEntryPoint Fragment %main "main" %BaseColor %f %gl_FragColor
3607 OpExecutionMode %main OriginUpperLeft
3608 %file_name = OpString "test"
3609 %float_name = OpString "float"
3610 %main_name = OpString "main"
3611 %v_name = OpString "v"
3612 OpSource GLSL 140
3613 OpName %main "main"
3614 OpName %v "v"
3615 OpName %BaseColor "BaseColor"
3616 OpName %i "i"
3617 OpName %f "f"
3618 OpName %gl_FragColor "gl_FragColor"
3619 %void = OpTypeVoid
3620 %9 = OpTypeFunction %void
3621 %float = OpTypeFloat 32
3622 %v4float = OpTypeVector %float 4
3623 %uint = OpTypeInt 32 0
3624 %uint_32 = OpConstant %uint 32
3625 %_ptr_Function_v4float = OpTypePointer Function %v4float
3626 %_ptr_Input_v4float = OpTypePointer Input %v4float
3627 %BaseColor = OpVariable %_ptr_Input_v4float Input
3628 %int = OpTypeInt 32 1
3629 %_ptr_Function_int = OpTypePointer Function %int
3630 %_ptr_Input_float = OpTypePointer Input %float
3631 %f = OpVariable %_ptr_Input_float Input
3632 %float_0_25 = OpConstant %float 0.25
3633 %float_0_75 = OpConstant %float 0.75
3634 %_ptr_Output_v4float = OpTypePointer Output %v4float
3635 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
3636 
3637 ; Debug information
3638 %null_expr = OpExtInst %void %ext DebugExpression
3639 %src = OpExtInst %void %ext DebugSource %file_name
3640 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3641 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3642 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3643 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3644 %dbg_v = OpExtInst %void %ext DebugLocalVariable %v_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3645 
3646 %main = OpFunction %void None %9
3647 %20 = OpLabel
3648 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3649 %v = OpVariable %_ptr_Function_v4float Function
3650 %i = OpVariable %_ptr_Function_int Function
3651 %21 = OpLoad %v4float %BaseColor
3652 
3653 ; DebugDeclare
3654 OpStore %v %21
3655 %decl = OpExtInst %void %ext DebugDeclare %dbg_v %v %null_expr
3656 
3657 ; CHECK: %main = OpFunction %void None
3658 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3659 ; CHECK: OpStore %v [[v0:%\w+]]
3660 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_v:%\w+]] [[v0]]
3661 ; CHECK: OpSwitch {{%\w+}} [[case0:%\w+]] 0 [[case1:%\w+]] 1 [[case2:%\w+]] 2 [[case3:%\w+]]
3662 ; CHECK: OpStore %v [[v1:%\w+]]
3663 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v1]]
3664 ; CHECK: OpStore %v [[v2:%\w+]]
3665 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v2]]
3666 ; CHECK: [[phi0:%\w+]] = OpPhi %v4float [[v0]] [[entry]] [[v2]] [[case2]]
3667 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi0]]
3668 ; CHECK: OpStore %v [[v3:%\w+]]
3669 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[v3]]
3670 ; CHECK: [[phi1:%\w+]] = OpPhi %v4float [[v0]] [[case0]] [[v1]] [[case1]] [[v3]] [[case3]]
3671 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_v]] [[phi1]]
3672 
3673 %22 = OpLoad %float %f
3674 %23 = OpConvertFToS %int %22
3675 OpStore %i %23
3676 %24 = OpLoad %int %i
3677 OpSelectionMerge %25 None
3678 OpSwitch %24 %26 0 %27 1 %28 2 %29
3679 %26 = OpLabel
3680 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3681 OpBranch %25
3682 %27 = OpLabel
3683 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3684 %30 = OpLoad %v4float %v
3685 %31 = OpVectorTimesScalar %v4float %30 %float_0_25
3686 OpStore %v %31
3687 OpBranch %25
3688 %28 = OpLabel
3689 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3690 %32 = OpLoad %v4float %v
3691 %33 = OpCompositeConstruct %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
3692 %34 = OpFAdd %v4float %32 %33
3693 OpStore %v %34
3694 OpBranch %29
3695 %29 = OpLabel
3696 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3697 %35 = OpLoad %v4float %v
3698 %36 = OpVectorTimesScalar %v4float %35 %float_0_75
3699 OpStore %v %36
3700 OpBranch %25
3701 %25 = OpLabel
3702 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3703 %37 = OpLoad %v4float %v
3704 OpStore %gl_FragColor %37
3705 OpReturn
3706 OpFunctionEnd
3707 )";
3708 
3709   SinglePassRunAndMatch<SSARewritePass>(text, true);
3710 }
3711 
TEST_F(LocalSSAElimTest,DebugSwapProblem)3712 TEST_F(LocalSSAElimTest, DebugSwapProblem) {
3713   // #version 140
3714   //
3715   // in float fe;
3716   // out float fo;
3717   //
3718   // void main()
3719   // {
3720   //     float f1 = 0.0;
3721   //     float f2 = 1.0;
3722   //     int ie = int(fe);
3723   //     for (int i=0; i<ie; i++) {
3724   //       float t = f1;
3725   //       f1 = f2;
3726   //       f2 = t;
3727   //     }
3728   //     fo = f1;
3729   // }
3730   //
3731   // Because of the swap in the for loop, it generates the following phi
3732   // instructions:
3733   //
3734   // [[phi_f2]] = OpPhi %float %float_1 [[entry]] [[phi_f1]] ..
3735   // [[phi_f1]] = OpPhi %float %float_0 [[entry]] [[phi_f2]] ..
3736   //
3737   // Since they are used as operands by each other, we want to clearly check
3738   // what DebugValue we have to add for them.
3739 
3740   const std::string text = R"(
3741 OpCapability Shader
3742 %1 = OpExtInstImport "GLSL.std.450"
3743 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
3744 OpMemoryModel Logical GLSL450
3745 OpEntryPoint Fragment %main "main" %fe %fo
3746 OpExecutionMode %main OriginUpperLeft
3747 OpSource GLSL 140
3748 %file_name = OpString "test"
3749 %float_name = OpString "float"
3750 %main_name = OpString "main"
3751 %t_name = OpString "t"
3752 OpName %main "main"
3753 OpName %f1 "f1"
3754 OpName %f2 "f2"
3755 OpName %ie "ie"
3756 OpName %fe "fe"
3757 OpName %i "i"
3758 OpName %t "t"
3759 OpName %fo "fo"
3760 %void = OpTypeVoid
3761 %11 = OpTypeFunction %void
3762 %float = OpTypeFloat 32
3763 %_ptr_Function_float = OpTypePointer Function %float
3764 %float_0 = OpConstant %float 0
3765 %float_1 = OpConstant %float 1
3766 %int = OpTypeInt 32 1
3767 %_ptr_Function_int = OpTypePointer Function %int
3768 %_ptr_Input_float = OpTypePointer Input %float
3769 %fe = OpVariable %_ptr_Input_float Input
3770 %int_0 = OpConstant %int 0
3771 %bool = OpTypeBool
3772 %int_1 = OpConstant %int 1
3773 %uint = OpTypeInt 32 0
3774 %uint_32 = OpConstant %uint 32
3775 %_ptr_Output_float = OpTypePointer Output %float
3776 %fo = OpVariable %_ptr_Output_float Output
3777 
3778 ; Debug information
3779 %null_expr = OpExtInst %void %ext DebugExpression
3780 %src = OpExtInst %void %ext DebugSource %file_name
3781 %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
3782 %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
3783 %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
3784 %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
3785 %dbg_f1 = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3786 %dbg_f2 = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3787 %dbg_i = OpExtInst %void %ext DebugLocalVariable %t_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal
3788 
3789 %main = OpFunction %void None %11
3790 %23 = OpLabel
3791 %s0 = OpExtInst %void %ext DebugScope %dbg_main
3792 %f1 = OpVariable %_ptr_Function_float Function
3793 %f2 = OpVariable %_ptr_Function_float Function
3794 %ie = OpVariable %_ptr_Function_int Function
3795 %i = OpVariable %_ptr_Function_int Function
3796 %t = OpVariable %_ptr_Function_float Function
3797 OpStore %f1 %float_0
3798 OpStore %f2 %float_1
3799 %24 = OpLoad %float %fe
3800 %25 = OpConvertFToS %int %24
3801 OpStore %ie %25
3802 OpStore %i %int_0
3803 
3804 ; DebugDeclare
3805 %decl0 = OpExtInst %void %ext DebugDeclare %dbg_f1 %f1 %null_expr
3806 %decl1 = OpExtInst %void %ext DebugDeclare %dbg_f2 %f2 %null_expr
3807 %decl2 = OpExtInst %void %ext DebugDeclare %dbg_i  %i  %null_expr
3808 
3809 ; CHECK: %main = OpFunction %void None
3810 ; CHECK-NEXT: [[entry:%\w+]] = OpLabel
3811 
3812 ; CHECK: OpStore %f1 %float_0
3813 ; CHECK-NEXT: = OpExtInst %void [[ext:%\w+]] DebugValue [[dbg_f1:%\w+]] %float_0
3814 ; CHECK: OpStore %f2 %float_1
3815 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f2:%\w+]] %float_1
3816 ; CHECK: OpStore %i %int_0
3817 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_i:%\w+]] %int_0
3818 
3819 ; CHECK: [[phi_f2:%\w+]] = OpPhi %float %float_1 [[entry]] [[phi_f1:%\w+]]
3820 ; CHECK: [[phi_f1]] = OpPhi %float %float_0 [[entry]] [[phi_f2]]
3821 ; CHECK: [[phi_i:%\w+]] = OpPhi %int %int_0 [[entry]]
3822 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f2]] [[phi_f2]]
3823 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_f1]] [[phi_f1]]
3824 ; CHECK-NEXT: = OpExtInst %void [[ext]] DebugValue [[dbg_i]] [[phi_i]]
3825 
3826 OpBranch %26
3827 %26 = OpLabel
3828 %s1 = OpExtInst %void %ext DebugScope %dbg_main
3829 OpLoopMerge %27 %28 None
3830 OpBranch %29
3831 %29 = OpLabel
3832 %s2 = OpExtInst %void %ext DebugScope %dbg_main
3833 %30 = OpLoad %int %i
3834 %31 = OpLoad %int %ie
3835 %32 = OpSLessThan %bool %30 %31
3836 OpBranchConditional %32 %33 %27
3837 %33 = OpLabel
3838 %s3 = OpExtInst %void %ext DebugScope %dbg_main
3839 %34 = OpLoad %float %f1
3840 OpStore %t %34
3841 %35 = OpLoad %float %f2
3842 OpStore %f1 %35
3843 %36 = OpLoad %float %t
3844 OpStore %f2 %36
3845 OpBranch %28
3846 %28 = OpLabel
3847 %s4 = OpExtInst %void %ext DebugScope %dbg_main
3848 %37 = OpLoad %int %i
3849 %38 = OpIAdd %int %37 %int_1
3850 OpStore %i %38
3851 OpBranch %26
3852 %27 = OpLabel
3853 %s5 = OpExtInst %void %ext DebugScope %dbg_main
3854 %39 = OpLoad %float %f1
3855 OpStore %fo %39
3856 OpReturn
3857 OpFunctionEnd
3858 )";
3859 
3860   SinglePassRunAndMatch<SSARewritePass>(text, true);
3861 }
3862 
TEST_F(LocalSSAElimTest,RemoveDebugDeclareWithoutLoads)3863 TEST_F(LocalSSAElimTest, RemoveDebugDeclareWithoutLoads) {
3864   // Check that the DebugDeclare for c is removed even though its loads
3865   // had been removed previously by single block store/load optimization.
3866   // In the presence of DebugDeclare, single-block can and does remove loads,
3867   // but cannot change the stores into DebugValues and remove the DebugDeclare
3868   // because it is only a per block optimization, not a function optimization.
3869   // So SSA-rewrite must perform this role.
3870   //
3871   // Texture2D g_tColor;
3872   // SamplerState g_sAniso;
3873   //
3874   // struct PS_INPUT
3875   // {
3876   //   float2 vTextureCoords2 : TEXCOORD2;
3877   //   float2 vTextureCoords3 : TEXCOORD3;
3878   // };
3879   //
3880   // struct PS_OUTPUT
3881   // {
3882   //   float4 vColor : SV_Target0;
3883   // };
3884   //
3885   // PS_OUTPUT MainPs(PS_INPUT i)
3886   // {
3887   //   PS_OUTPUT ps_output;
3888   //   float4 c;
3889   //   c = g_tColor.Sample(g_sAniso, i.vTextureCoords2.xy);
3890   //   c += g_tColor.Sample(g_sAniso, i.vTextureCoords3.xy);
3891   //   ps_output.vColor = c;
3892   //   return ps_output;
3893   // }
3894 
3895   const std::string text = R"(
3896                OpCapability Shader
3897           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
3898                OpMemoryModel Logical GLSL450
3899                OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %in_var_TEXCOORD3 %out_var_SV_Target0
3900                OpExecutionMode %MainPs OriginUpperLeft
3901          %22 = OpString "foo.frag"
3902          %26 = OpString "PS_OUTPUT"
3903          %30 = OpString "float"
3904          %33 = OpString "vColor"
3905          %35 = OpString "PS_INPUT"
3906          %40 = OpString "vTextureCoords3"
3907          %42 = OpString "vTextureCoords2"
3908          %44 = OpString "@type.2d.image"
3909          %45 = OpString "type.2d.image"
3910          %47 = OpString "Texture2D.TemplateParam"
3911          %51 = OpString "src.MainPs"
3912          %55 = OpString "c"
3913          %57 = OpString "ps_output"
3914          %60 = OpString "i"
3915          %62 = OpString "@type.sampler"
3916          %63 = OpString "type.sampler"
3917          %65 = OpString "g_sAniso"
3918          %67 = OpString "g_tColor"
3919                OpName %type_2d_image "type.2d.image"
3920                OpName %g_tColor "g_tColor"
3921                OpName %type_sampler "type.sampler"
3922                OpName %g_sAniso "g_sAniso"
3923                OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2"
3924                OpName %in_var_TEXCOORD3 "in.var.TEXCOORD3"
3925                OpName %out_var_SV_Target0 "out.var.SV_Target0"
3926                OpName %MainPs "MainPs"
3927                OpName %PS_INPUT "PS_INPUT"
3928                OpMemberName %PS_INPUT 0 "vTextureCoords2"
3929                OpMemberName %PS_INPUT 1 "vTextureCoords3"
3930                OpName %param_var_i "param.var.i"
3931                OpName %PS_OUTPUT "PS_OUTPUT"
3932                OpMemberName %PS_OUTPUT 0 "vColor"
3933                OpName %type_sampled_image "type.sampled.image"
3934                OpDecorate %in_var_TEXCOORD2 Location 0
3935                OpDecorate %in_var_TEXCOORD3 Location 1
3936                OpDecorate %out_var_SV_Target0 Location 0
3937                OpDecorate %g_tColor DescriptorSet 0
3938                OpDecorate %g_tColor Binding 0
3939                OpDecorate %g_sAniso DescriptorSet 0
3940                OpDecorate %g_sAniso Binding 1
3941         %int = OpTypeInt 32 1
3942       %int_0 = OpConstant %int 0
3943       %int_1 = OpConstant %int 1
3944        %uint = OpTypeInt 32 0
3945     %uint_32 = OpConstant %uint 32
3946       %float = OpTypeFloat 32
3947 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
3948 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
3949 %type_sampler = OpTypeSampler
3950 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
3951     %v2float = OpTypeVector %float 2
3952 %_ptr_Input_v2float = OpTypePointer Input %v2float
3953     %v4float = OpTypeVector %float 4
3954 %_ptr_Output_v4float = OpTypePointer Output %v4float
3955        %void = OpTypeVoid
3956    %uint_128 = OpConstant %uint 128
3957      %uint_0 = OpConstant %uint 0
3958     %uint_64 = OpConstant %uint 64
3959          %69 = OpTypeFunction %void
3960    %PS_INPUT = OpTypeStruct %v2float %v2float
3961 %_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT
3962   %PS_OUTPUT = OpTypeStruct %v4float
3963 %_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT
3964 %_ptr_Function_v4float = OpTypePointer Function %v4float
3965 %_ptr_Function_v2float = OpTypePointer Function %v2float
3966 %type_sampled_image = OpTypeSampledImage %type_2d_image
3967    %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
3968    %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
3969 %in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input
3970 %in_var_TEXCOORD3 = OpVariable %_ptr_Input_v2float Input
3971 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
3972          %43 = OpExtInst %void %1 DebugInfoNone
3973          %59 = OpExtInst %void %1 DebugExpression
3974          %24 = OpExtInst %void %1 DebugSource %22
3975          %25 = OpExtInst %void %1 DebugCompilationUnit 1 4 %24 HLSL
3976          %28 = OpExtInst %void %1 DebugTypeComposite %26 Structure %24 11 1 %25 %26 %uint_128 FlagIsProtected|FlagIsPrivate %29
3977          %31 = OpExtInst %void %1 DebugTypeBasic %30 %uint_32 Float
3978          %32 = OpExtInst %void %1 DebugTypeVector %31 4
3979          %29 = OpExtInst %void %1 DebugTypeMember %33 %32 %24 13 5 %28 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
3980          %36 = OpExtInst %void %1 DebugTypeComposite %35 Structure %24 5 1 %25 %35 %uint_128 FlagIsProtected|FlagIsPrivate %37 %38
3981          %39 = OpExtInst %void %1 DebugTypeVector %31 2
3982          %38 = OpExtInst %void %1 DebugTypeMember %40 %39 %24 8 5 %36 %uint_64 %uint_64 FlagIsProtected|FlagIsPrivate
3983          %37 = OpExtInst %void %1 DebugTypeMember %42 %39 %24 7 5 %36 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate
3984          %46 = OpExtInst %void %1 DebugTypeComposite %44 Class %24 0 0 %25 %45 %43 FlagIsProtected|FlagIsPrivate
3985          %50 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %28 %36
3986          %52 = OpExtInst %void %1 DebugFunction %51 %50 %24 16 1 %25 %51 FlagIsProtected|FlagIsPrivate 17 %43
3987          %54 = OpExtInst %void %1 DebugLexicalBlock %24 17 1 %52
3988          %56 = OpExtInst %void %1 DebugLocalVariable %55 %32 %24 20 12 %54 FlagIsLocal
3989          %58 = OpExtInst %void %1 DebugLocalVariable %57 %28 %24 18 15 %54 FlagIsLocal
3990          %61 = OpExtInst %void %1 DebugLocalVariable %60 %36 %24 16 29 %52 FlagIsLocal 1
3991          %64 = OpExtInst %void %1 DebugTypeComposite %62 Structure %24 0 0 %25 %63 %43 FlagIsProtected|FlagIsPrivate
3992          %66 = OpExtInst %void %1 DebugGlobalVariable %65 %64 %24 3 14 %25 %65 %g_sAniso FlagIsDefinition
3993          %68 = OpExtInst %void %1 DebugGlobalVariable %67 %46 %24 1 11 %25 %67 %g_tColor FlagIsDefinition
3994      %MainPs = OpFunction %void None %69
3995          %70 = OpLabel
3996         %135 = OpExtInst %void %1 DebugScope %54
3997         %111 = OpVariable %_ptr_Function_PS_OUTPUT Function
3998         %112 = OpVariable %_ptr_Function_v4float Function
3999         %136 = OpExtInst %void %1 DebugNoScope
4000 %param_var_i = OpVariable %_ptr_Function_PS_INPUT Function
4001          %74 = OpLoad %v2float %in_var_TEXCOORD2
4002          %75 = OpLoad %v2float %in_var_TEXCOORD3
4003          %76 = OpCompositeConstruct %PS_INPUT %74 %75
4004                OpStore %param_var_i %76
4005         %137 = OpExtInst %void %1 DebugScope %52
4006         %115 = OpExtInst %void %1 DebugDeclare %61 %param_var_i %59
4007         %138 = OpExtInst %void %1 DebugScope %54
4008         %116 = OpExtInst %void %1 DebugDeclare %58 %111 %59
4009         %117 = OpExtInst %void %1 DebugDeclare %56 %112 %59
4010 ;CHECK-NOT: %117 = OpExtInst %void %1 DebugDeclare %56 %112 %59
4011                OpLine %22 21 9
4012         %118 = OpLoad %type_2d_image %g_tColor
4013                OpLine %22 21 29
4014         %119 = OpLoad %type_sampler %g_sAniso
4015                OpLine %22 21 40
4016         %120 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0
4017         %121 = OpLoad %v2float %120
4018                OpLine %22 21 9
4019         %122 = OpSampledImage %type_sampled_image %118 %119
4020         %123 = OpImageSampleImplicitLod %v4float %122 %121 None
4021                OpLine %22 21 5
4022                OpStore %112 %123
4023 ;CHECK: %140 = OpExtInst %void %1 DebugValue %56 %123 %59
4024                OpLine %22 22 10
4025         %124 = OpLoad %type_2d_image %g_tColor
4026                OpLine %22 22 30
4027         %125 = OpLoad %type_sampler %g_sAniso
4028                OpLine %22 22 41
4029         %126 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_1
4030         %127 = OpLoad %v2float %126
4031                OpLine %22 22 10
4032         %128 = OpSampledImage %type_sampled_image %124 %125
4033         %129 = OpImageSampleImplicitLod %v4float %128 %127 None
4034                OpLine %22 22 7
4035         %131 = OpFAdd %v4float %123 %129
4036                OpLine %22 22 5
4037                OpStore %112 %131
4038 ;CHECK: %141 = OpExtInst %void %1 DebugValue %56 %131 %59
4039                OpLine %22 23 5
4040         %133 = OpAccessChain %_ptr_Function_v4float %111 %int_0
4041                OpStore %133 %131
4042                OpLine %22 24 12
4043         %134 = OpLoad %PS_OUTPUT %111
4044         %139 = OpExtInst %void %1 DebugNoScope
4045          %79 = OpCompositeExtract %v4float %134 0
4046                OpStore %out_var_SV_Target0 %79
4047                OpReturn
4048                OpFunctionEnd
4049 )";
4050 
4051   SetTargetEnv(SPV_ENV_VULKAN_1_2);
4052   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4053   SinglePassRunAndMatch<SSARewritePass>(text, true);
4054 }
4055 
4056 // Check support for pointer variables. When pointer variables are used, the
4057 // computation of reaching definitions may need to follow pointer chains.
4058 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/3873 for details.
TEST_F(LocalSSAElimTest,PointerVariables)4059 TEST_F(LocalSSAElimTest, PointerVariables) {
4060   const std::string text = R"(
4061                OpCapability Shader
4062                OpCapability VariablePointers
4063                OpExtension "SPV_KHR_variable_pointers"
4064                OpMemoryModel Logical Simple
4065                OpEntryPoint Fragment %1 "main" %2 %3
4066                OpExecutionMode %1 OriginUpperLeft
4067       %float = OpTypeFloat 32
4068        %void = OpTypeVoid
4069           %6 = OpTypeFunction %void
4070 %_ptr_Input_float = OpTypePointer Input %float
4071 %_ptr_Output_float = OpTypePointer Output %float
4072 %_ptr_Function__ptr_Input_float = OpTypePointer Function %_ptr_Input_float
4073           %2 = OpVariable %_ptr_Input_float Input
4074           %3 = OpVariable %_ptr_Output_float Output
4075           %1 = OpFunction %void None %6
4076          %10 = OpLabel
4077          %11 = OpVariable %_ptr_Function__ptr_Input_float Function
4078                OpStore %11 %2
4079 
4080 ; CHECK-NOT: %12 = OpLoad %_ptr_Input_float %11
4081          %12 = OpLoad %_ptr_Input_float %11
4082 
4083 ; CHECK: %13 = OpLoad %float %2
4084          %13 = OpLoad %float %12
4085 
4086                OpStore %3 %13
4087                OpReturn
4088                OpFunctionEnd
4089 )";
4090 
4091   SinglePassRunAndMatch<SSARewritePass>(text, true);
4092 }
4093 
4094 // TODO(greg-lunarg): Add tests to verify handling of these cases:
4095 //
4096 //    No optimization in the presence of
4097 //      access chains
4098 //      function calls
4099 //      OpCopyMemory?
4100 //      unsupported extensions
4101 //    Others?
4102 
4103 }  // namespace
4104 }  // namespace opt
4105 }  // namespace spvtools
4106