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