• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021-2024 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14#
15# Checked tests for basic inlining.
16#
17
18#! CHECKER      Instructions limit
19#! RUN          force_jit: true, options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0", entry: "Test1::main"
20#! EVENT        /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/
21#! EVENT_NEXT   /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/
22
23#! CHECKER      Instructions limit at Regular AOT
24#! RUN_PAOC     options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0"
25#! EVENT        /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/
26#! EVENT_NEXT   /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/
27#! RUN          entry: "Test1::main"
28
29#! CHECKER      Instructions max size
30#! RUN          force_jit: true, options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0", entry: "Test1::main"
31#! EVENT        /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/
32#! EVENT_NEXT   /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/
33
34#! CHECKER      Instructions max size at Regular AOT
35#! RUN_PAOC     options: "--compiler-regex=Test1::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0"
36#! EVENT        /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/
37#! EVENT_NEXT   /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/
38#! RUN          entry: "Test1::main"
39
40.record Test1 {}
41
42.function i32 func(i32 a0) {
43    newobj v0, Test1
44    newobj v0, Test1
45    newobj v0, Test1
46    newobj v0, Test1
47    ldai 1
48    add2 a0
49    return
50}
51
52.function i32 small_func(i32 a0) {
53    ldai 1
54    add2 a0
55    return
56}
57
58.function i32 Test1.main() {
59    movi v1, 10
60
61    call.short func, v1
62    call.short small_func, v1
63    add2 v1
64
65    ldai 0
66    return
67}
68
69#! CHECKER      Inline depth limit
70#! RUN          force_jit: true, options: "--compiler-regex=Test1::main_depth --compiler-inlining-max-depth=2 --compiler-inlining-recursive-calls-limit=2", entry: "Test1::main_depth"
71#! EVENTS_COUNT /Inline,Test1::main_depth,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
72#! EVENTS_COUNT /Inline,_GLOBAL::func_rec,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
73
74#! CHECKER      Inline depth limit at Regular AOT
75#! RUN_PAOC     options: "--compiler-regex=Test1::main_depth --compiler-inlining-max-depth=2 --compiler-inlining-recursive-calls-limit=2"
76#! EVENTS_COUNT /Inline,Test1::main_depth,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
77#! EVENTS_COUNT /Inline,_GLOBAL::func_rec,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
78#! RUN          entry: "Test1::main_depth"
79
80.function i32 func_rec(i32 a0) {
81    lda a0
82    jeqz exit
83    subi 1
84    sta a0
85    call.short func_rec, a0
86exit:
87    return
88}
89
90.function i32 Test1.main_depth() {
91    movi v1, 10
92
93    call.short func_rec, v1
94
95    return
96}
97
98#! CHECKER      Check inlined float array
99#! RUN          force_jit: true, options: "--compiler-regex=_GLOBAL::main", entry: "_GLOBAL::main"
100#! EVENT        /Inline,_GLOBAL::main,_GLOBAL::farray,.*STATIC,SUCCESS/
101#! METHOD       "_GLOBAL::main"
102#! PASS_AFTER   "Inline"
103#! INST         "CallStatic.Inlined"
104
105#! CHECKER      Check inlined float array at Regular AOT
106#! RUN_PAOC     options: "--compiler-regex=_GLOBAL::main"
107#! EVENT        /Inline,_GLOBAL::main,_GLOBAL::farray,.*STATIC,SUCCESS/
108#! METHOD       "_GLOBAL::main"
109#! PASS_AFTER   "Inline"
110#! INST         "CallStatic.Inlined"
111#! RUN          entry: "_GLOBAL::main"
112
113#! CHECKER      Check inlined float array at LLVM AOT
114#! RUN_LLVM     options: "--compiler-regex='(_GLOBAL::main|_GLOBAL::farray)' --llvm-dump-before --llvm-dump-after \
115#!                       --llvm-pre-opt=0"
116#! READ_FILE    "console.out"
117#! INST         "LLVM IR module BEFORE LLVM optimizations"
118#! INST_NEXT    /define protected.*_GLOBAL::main/
119#! INST_NEXT    /call.*_GLOBAL::farray/
120#! INST         "LLVM IR module AFTER LLVM optimizations"
121#! INST_NEXT    /define protected.*_GLOBAL::main/
122#! INST_NEXT    /label %"void _GLOBAL::farray/
123#! RUN          entry: "_GLOBAL::main"
124
125.function void farray(f64[] a0) {
126    ldai 2
127    movi v0, 1
128    fstarr.64 a0, v0
129    return.void
130}
131
132.function i32 main() {
133    movi v0, 5
134    newarr v1, v0, f64[]
135    call.short farray, v1
136    ldai 0
137    return
138}
139
140#! CHECKER      Inline function with dead loop
141#! RUN          force_jit: true, options: "--compiler-regex=_GLOBAL::main1", entry: "_GLOBAL::main1"
142#! EVENT        /Inline,_GLOBAL::main1,_GLOBAL::foo1,.*STATIC,SUCCESS/
143#! METHOD       "_GLOBAL::main1"
144#! PASS_AFTER   "Inline"
145#! INST_NOT     "CallStatic.Inlined"
146#! INST_NOT     "Return.Inlined"
147#! INST_NOT     "SaveStateDeoptimize"
148
149#! CHECKER      Inline function with dead loop at Regular AOT
150#! RUN_PAOC     options: "--compiler-regex=_GLOBAL::main1"
151#! EVENT        /Inline,_GLOBAL::main1,_GLOBAL::foo1,.*STATIC,SUCCESS/
152#! METHOD       "_GLOBAL::main1"
153#! PASS_AFTER   "Inline"
154#! INST_NOT     "CallStatic.Inlined"
155#! INST_NOT     "Return.Inlined"
156#! INST_NOT     "SaveStateDeoptimize"
157#! RUN          entry: "_GLOBAL::main1"
158
159#! CHECKER      Inline function with dead loop at LLVM AOT
160#! RUN_LLVM     options: "--compiler-regex='(_GLOBAL::main1|_GLOBAL::foo1)' --llvm-dump-before --llvm-dump-after \
161#!                        --llvm-pre-opt=0"
162#! READ_FILE    "console.out"
163#! INST         "LLVM IR module BEFORE LLVM optimizations"
164#! INST_NEXT    /define protected.*_GLOBAL::main/
165#! INST_NEXT    /call.*_GLOBAL::foo1/
166#! INST         "LLVM IR module AFTER LLVM optimizations"
167#! INST_NEXT    /define protected.*_GLOBAL::main/
168#! INST_NEXT    "ret i32 0"
169#! RUN          entry: "_GLOBAL::main1"
170
171.function i32 foo1() {
172  movi v1, 0
173  ldai 10
174lbl:
175  jle v1, lbl     # jump to 0 offset, never happens
176  ldai 0
177  return
178}
179
180.function i32 main1() {
181  call foo1
182  return
183}
184
185
186#! CHECKER      Change to CallStatic by instructions limit
187#! RUN          force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=12 --compiler-inlining-always-inline-bc-size=0", entry: "Test2::main"
188#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
189#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
190#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
191
192#! CHECKER      Change to CallStatic by instructions limit at Regular AOT
193#! RUN_PAOC     options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=12 --compiler-inlining-always-inline-bc-size=0"
194#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
195#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
196#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
197#! RUN          entry: "Test2::main"
198
199#! CHECKER      Change to CallStatic by instructions limit at LLVM AOT
200#! RUN_LLVM     options: "--compiler-regex=Test2.* --compiler-inlining-max-insts=12 --compiler-inlining-always-inline-bc-size=0 \
201#!                        --llvm-pre-opt=0"
202#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
203#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,DEVIRTUALIZED/
204#! RUN          entry: "Test2::main"
205
206#! CHECKER      Change to CallStatic by instructions max size
207#! RUN          force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0", entry: "Test2::main"
208#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
209#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
210#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
211
212#! CHECKER      Change to CallStatic by instructions size at Regular AOT
213#! RUN_PAOC     options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0"
214#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
215#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
216#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
217#! RUN          entry: "Test2::main"
218
219#! CHECKER      Change to CallStatic by instructions size at LLVM AOT
220#! RUN_LLVM     options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=8 --compiler-inlining-always-inline-bc-size=0 \
221#!                        --llvm-pre-opt=0"
222#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
223#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,DEVIRTUALIZED/
224#! RUN          entry: "Test2::main"
225
226.record Test2 {}
227
228.function i32 Test2.func(Test2 a0, i32 a1) {
229    newobj v0, Test1
230    newobj v0, Test1
231    newobj v0, Test1
232    newobj v0, Test1
233    ldai 1
234    add2 a1
235    return
236}
237
238.function i32 Test2.small_func(Test2 a0, i32 a1) {
239    ldai 1
240    add2 a1
241    return
242}
243
244.function i32 Test2.main() {
245    newobj v0, Test2
246    movi v1, 10
247
248    call.virt Test2.func, v0, v1
249    call.virt Test2.small_func, v0, v1
250    add2 v1
251
252    ldai 0
253    return
254}
255
256#! CHECKER      Do not inline infinite loop
257#! RUN          force_jit: true, entry: "Test3::main"
258#! EVENT        /Inline,Test3::main,Test3::foo1,.*VIRTUAL,SUCCESS/
259#! EVENT        /Inline,Test3::main,_GLOBAL::foo_inf_loop,.*STATIC,INF_LOOP/
260
261#! CHECKER      Do not inline infinite loop at Regular AOT
262#! RUN_PAOC     options: "--compiler-regex=Test3::main"
263#! EVENT        /Inline,Test3::main,Test3::foo1,.*VIRTUAL,SUCCESS/
264#! EVENT        /Inline,Test3::main,_GLOBAL::foo_inf_loop,.*STATIC,INF_LOOP/
265#! RUN          entry: "Test3::main"
266
267#! CHECKER      Do not inline infinite loop at LLVM AOT
268#! RUN_LLVM     options: "--compiler-regex='(Test3::main|Test3::foo1|_GLOBAL::foo_inf_loop)' --llvm-dump-before --llvm-dump-after \
269#!                        --llvm-pre-opt=0"
270#! READ_FILE    "console.out"
271#! INST         "LLVM IR module BEFORE LLVM optimizations"
272#! INST_NEXT    /define protected.*Test3::main/
273#! INST_NEXT    /call.*_GLOBAL::foo_inf_loop/
274#! INST         "LLVM IR module AFTER LLVM optimizations"
275#! INST_NEXT    /define protected.*Test3::main/
276#! INST_NEXT_NOT "resolve_method"
277#! RUN          entry: "Test3::main"
278
279.record Test3 {}
280
281.function i32 Test3.foo1(Test3 a0) {
282    ldai 0
283    return
284}
285
286.function i32 foo_inf_loop(i32 a0) {
287    lda a0
288    jeqz exit
289loop:
290    addi 1
291    sta a0
292    jmp loop
293exit:
294    return
295}
296
297.function i32 Test3.main() {
298  newobj v0, Test3
299  call.virt Test3.foo1, v0
300  jeqz exit
301  sta v1
302  call.short foo_inf_loop, v1
303  ldai 0
304exit:
305  return
306}
307
308#! CHECKER      Inline external files in AOT mode
309#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true --compiler-regex=Test4.*"
310#! METHOD       "Test4::func_A_getConst_static__noinline__"
311#! PASS_AFTER   "IrBuilder"
312#! INST         /CallStatic.*A::getConst/
313#! INST_NOT     "Constant"
314#! PASS_AFTER   "Inline"
315#! INST_NOT     /CallStatic.*A::getConst/
316#! INST         "Constant"
317#! METHOD       "Test4::func_A_getConst_virtual__noinline__"
318#! PASS_AFTER   "IrBuilder"
319#! INST         /CallVirtual.*A::getConst/
320#! INST_NOT     "Constant"
321#! PASS_AFTER   "Inline"
322#! INST_NOT     /CallVirtual.*A::getConst/
323#! INST         "Constant"
324#! METHOD       "Test4::func_A_getParam_static__noinline__"
325#! PASS_AFTER   "IrBuilder"
326#! INST         /CallStatic.*A::getParam/
327#! PASS_AFTER   "Inline"
328#! INST_NOT     /CallStatic.*A::getParam/
329#! METHOD       "Test4::func_A_getParam_virtual__noinline__"
330#! PASS_AFTER   "IrBuilder"
331#! INST         /CallVirtual.*A::getParam/
332#! PASS_AFTER   "Inline"
333#! INST_NOT     /CallVirtual.*A::getParam/
334#! METHOD       "Test4::func_A_getVoid_static__noinline__"
335#! PASS_AFTER   "IrBuilder"
336#! INST         /CallStatic.*A::getVoid/
337#! PASS_AFTER   "Inline"
338#! INST_NOT     /CallStatic.*A::getVoid/
339#! METHOD       "Test4::func_A_getVoid_virtual__noinline__"
340#! PASS_AFTER   "IrBuilder"
341#! INST         /CallVirtual.*A::getVoid/
342#! PASS_AFTER   "Inline"
343#! INST_NOT     /CallVirtual.*A::getVoid/
344#! METHOD       "Test4::func_A_getObj_static__noinline__"
345#! PASS_AFTER   "IrBuilder"
346#! INST         /CallStatic.*A::getObj/
347#! INST_NOT     "LoadObject"
348#! PASS_AFTER   "Inline"
349#! INST_NOT      /CallStatic.*A::getObj/
350#! INST         "LoadObject"
351#! METHOD       "Test4::func_A_getObj_virtual__noinline__"
352#! PASS_AFTER   "IrBuilder"
353#! INST         /CallVirtual.*A::getObj/
354#! INST_NOT     "LoadObject"
355#! PASS_AFTER   "Inline"
356#! INST_NOT     /CallVirtual.*A::getObj/
357#! INST         "LoadObject"
358#! METHOD       "Test4::func_A_setObj_static__noinline__"
359#! PASS_AFTER   "IrBuilder"
360#! INST         /CallStatic.*A::setObj/
361#! INST_NOT     "StoreObject"
362#! PASS_AFTER   "Inline"
363#! INST_NOT     /CallStatic.*A::setObj/
364#! INST         "StoreObject"
365#! METHOD       "Test4::func_A_setObj_virtual__noinline__"
366#! PASS_AFTER   "IrBuilder"
367#! INST         /CallVirtual.*A::setObj/
368#! INST_NOT     "StoreObject"
369#! PASS_AFTER   "Inline"
370#! INST_NOT     /CallVirtual.*A::setObj/
371#! INST         "StoreObject"
372#! METHOD       "Test4::func_A_getObj_wrong_virtual__noinline__"
373#! PASS_AFTER   "IrBuilder"
374#! INST         /CallVirtual.*A::getObj/
375#! INST_NOT     "LoadObject"
376#! PASS_AFTER   "Inline"
377#! INST_NOT      /CallVirtual.*A::getObj/
378#! INST         "LoadObject"
379#! METHOD       "Test4::func_A_setObj_wrong_virtual__noinline__"
380#! PASS_AFTER   "IrBuilder"
381#! INST         /CallVirtual.*A::setObj/
382#! INST_NOT     "StoreObject"
383#! PASS_AFTER   "Inline"
384#! INST_NOT     /CallVirtual.*A::setObj/
385#! INST         "StoreObject"
386#! METHOD       "Test4::func_A_setObj_multiple__noinline__"
387#! PASS_AFTER   "IrBuilder"
388#! INST         /CallStatic.*A::setObj_multiple/
389#! PASS_AFTER   "Inline"
390#! INST_NOT     /CallStatic.*A::setObj_multiple/
391#! METHOD       "Test4::func_A_complexMethod__noinline__"
392#! PASS_AFTER   "IrBuilder"
393#! INST         /CallVirtual.*A::complexMethod/
394#! PASS_AFTER   "Inline"
395#! INST_NOT     /CallVirtual.*A::complexMethod/
396#! METHOD       "Test4::func_A_setObj_unknown_target__noinline__"
397#! PASS_AFTER   "IrBuilder"
398#! INST         /CallStatic.*A::setObj/
399#! PASS_AFTER   "Inline"
400#! INST         /CallStatic.*A::setObj/
401#! RUN          options: "--panda-files=../../inline_external.checked/test.abc", entry: "Test4::main"
402
403#! CHECKER      Inline external files in LLVM AOT mode
404#! RUN_LLVM     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true --compiler-regex=Test4.*"
405#! METHOD       "Test4::func_A_getConst_static__noinline__"
406#! PASS_AFTER   "IrBuilder"
407#! INST         /CallStatic.*A::getConst/
408#! INST_NOT     "Constant"
409#! PASS_AFTER   "Inline"
410#! INST_NOT     /CallStatic.*A::getConst/
411#! INST         "Constant"
412#! METHOD       "Test4::func_A_getConst_virtual__noinline__"
413#! PASS_AFTER   "IrBuilder"
414#! INST         /CallVirtual.*A::getConst/
415#! INST_NOT     "Constant"
416#! PASS_AFTER   "Inline"
417#! INST_NOT     /CallVirtual.*A::getConst/
418#! INST         "Constant"
419#! METHOD       "Test4::func_A_getParam_static__noinline__"
420#! PASS_AFTER   "IrBuilder"
421#! INST         /CallStatic.*A::getParam/
422#! PASS_AFTER   "Inline"
423#! INST_NOT     /CallStatic.*A::getParam/
424#! METHOD       "Test4::func_A_getParam_virtual__noinline__"
425#! PASS_AFTER   "IrBuilder"
426#! INST         /CallVirtual.*A::getParam/
427#! PASS_AFTER   "Inline"
428#! INST_NOT     /CallVirtual.*A::getParam/
429#! METHOD       "Test4::func_A_getVoid_static__noinline__"
430#! PASS_AFTER   "IrBuilder"
431#! INST         /CallStatic.*A::getVoid/
432#! PASS_AFTER   "Inline"
433#! INST_NOT     /CallStatic.*A::getVoid/
434#! METHOD       "Test4::func_A_getVoid_virtual__noinline__"
435#! PASS_AFTER   "IrBuilder"
436#! INST         /CallVirtual.*A::getVoid/
437#! PASS_AFTER   "Inline"
438#! INST_NOT     /CallVirtual.*A::getVoid/
439#! METHOD       "Test4::func_A_getObj_static__noinline__"
440#! PASS_AFTER   "IrBuilder"
441#! INST         /CallStatic.*A::getObj/
442#! INST_NOT     "LoadObject"
443#! PASS_AFTER   "Inline"
444#! INST_NOT      /CallStatic.*A::getObj/
445#! INST         "LoadObject"
446#! METHOD       "Test4::func_A_getObj_virtual__noinline__"
447#! PASS_AFTER   "IrBuilder"
448#! INST         /CallVirtual.*A::getObj/
449#! INST_NOT     "LoadObject"
450#! PASS_AFTER   "Inline"
451#! INST_NOT     /CallVirtual.*A::getObj/
452#! INST         "LoadObject"
453#! METHOD       "Test4::func_A_setObj_static__noinline__"
454#! PASS_AFTER   "IrBuilder"
455#! INST         /CallStatic.*A::setObj/
456#! INST_NOT     "StoreObject"
457#! PASS_AFTER   "Inline"
458#! INST_NOT     /CallStatic.*A::setObj/
459#! INST         "StoreObject"
460#! METHOD       "Test4::func_A_setObj_virtual__noinline__"
461#! PASS_AFTER   "IrBuilder"
462#! INST         /CallVirtual.*A::setObj/
463#! INST_NOT     "StoreObject"
464#! PASS_AFTER   "Inline"
465#! INST_NOT     /CallVirtual.*A::setObj/
466#! INST         "StoreObject"
467#! METHOD       "Test4::func_A_getObj_wrong_virtual__noinline__"
468#! PASS_AFTER   "IrBuilder"
469#! INST         /CallVirtual.*A::getObj/
470#! INST_NOT     "LoadObject"
471#! PASS_AFTER   "Inline"
472#! INST_NOT      /CallVirtual.*A::getObj/
473#! INST         "LoadObject"
474#! METHOD       "Test4::func_A_setObj_wrong_virtual__noinline__"
475#! PASS_AFTER   "IrBuilder"
476#! INST         /CallVirtual.*A::setObj/
477#! INST_NOT     "StoreObject"
478#! PASS_AFTER   "Inline"
479#! INST_NOT     /CallVirtual.*A::setObj/
480#! INST         "StoreObject"
481#! METHOD       "Test4::func_A_setObj_multiple__noinline__"
482#! PASS_AFTER   "IrBuilder"
483#! INST         /CallStatic.*A::setObj_multiple/
484#! PASS_AFTER   "Inline"
485#! INST_NOT     /CallStatic.*A::setObj_multiple/
486#! METHOD       "Test4::func_A_complexMethod__noinline__"
487#! PASS_AFTER   "IrBuilder"
488#! INST         /CallVirtual.*A::complexMethod/
489#! PASS_AFTER   "Inline"
490#! INST_NOT     /CallVirtual.*A::complexMethod/
491#! METHOD       "Test4::func_A_setObj_unknown_target__noinline__"
492#! PASS_AFTER   "IrBuilder"
493#! INST         /CallStatic.*A::setObj/
494#! PASS_AFTER   "Inline"
495#! INST         /CallStatic.*A::setObj/
496#! RUN          options: "--panda-files=../../inline_external.checked/test.abc", entry: "Test4::main"
497
498#! CHECKER      CallVirtual for external method is replaced with CallStatic
499#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true \
500#!                        --compiler-regex=Test4.* --compiler-inlining-max-insts=0 --compiler-inlining-always-inline-bc-size=0"
501#! METHOD       "Test4::func_A_complexMethod__noinline__"
502#! PASS_AFTER   "IrBuilder"
503#! INST         /CallVirtual.*A::complexMethod/
504#! PASS_AFTER   "Inline"
505#! INST         /CallStatic.*A::complexMethod/
506
507#! CHECKER      CallVirtual for external method is not replaced with CallStatic if external inlining is disabled
508#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=true \
509#!                        --compiler-regex=Test4.* --compiler-inlining-max-insts=0 \
510#!                        --compiler-inline-external-methods=false --compiler-inlining-always-inline-bc-size=0"
511#! METHOD       "Test4::func_A_complexMethod__noinline__"
512#! PASS_AFTER   "IrBuilder"
513#! INST         /CallVirtual.*A::complexMethod/
514#! PASS_AFTER   "Inline"
515#! INST_NOT     /CallStatic.*A::complexMethod/
516#! INST         /CallVirtual.*A::complexMethod/
517
518#! CHECKER      Don't inline external files in AOT mode without cha
519#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=false --compiler-regex=Test4.*"
520#! METHOD       "Test4::func_A_getConst_static__noinline__"
521#! PASS_AFTER   "IrBuilder"
522#! INST         /CallStatic.*A::getConst/
523#! INST_NOT     "Constant"
524#! PASS_AFTER   "Inline"
525#! INST         /CallStatic.*A::getConst/
526#! INST_NOT     "Constant"
527
528.record A {
529    i32 data <external>
530}
531.record A.data <external>
532.function i32 A.getConst() <external,static>
533.function i32 A.getConst_virt(A a0) <external>
534.function i32 A.getParam(i32 a0) <external,static>
535.function i32 A.getParam_virt(A a0, i32 a1) <external>
536.function void A.getVoid() <external,static>
537.function void A.getVoid_virt(A a0) <external>
538.function i32 A.getObj(A a0) <external,static>
539.function i32 A.getObj_virt(A a0) <external>
540.function void A.setObj(A a0, i32 a1) <external,static>
541.function void A.setObjConst_virt(A a0) <external>
542.function void A.setObj_virt(A a0, i32 a1) <external>
543.function i32 A.getObj_wrong_virt(A a0, A a1) <external>
544.function void A.setObj_wrong_virt(A a0, i32 a1, A a2) <external>
545.function void A.setObj_multiple(A a0, i32 a1, i32 a2) <external,static>
546.function i32 A.complexMethod(A a0) <external>
547
548.record Test4 {}
549
550.function i32 Test4.func_A_getConst_static__noinline__() <static> {
551    call A.getConst
552    return
553}
554
555.function i32 Test4.func_A_getConst_virtual__noinline__() <static> {
556    newobj v0, A
557    call.virt A.getConst_virt, v0
558    return
559}
560
561.function i32 Test4.func_A_getParam_static__noinline__(i32 a0) <static> {
562    call A.getParam, a0
563    return
564}
565
566.function i32 Test4.func_A_getParam_virtual__noinline__(i32 a0) <static> {
567    newobj v0, A
568    call.virt A.getParam_virt, v0, a0
569    return
570}
571
572.function void Test4.func_A_getVoid_static__noinline__() <static> {
573    call A.getVoid
574    return.void
575}
576
577.function void Test4.func_A_getVoid_virtual__noinline__() <static> {
578    newobj v0, A
579    call.virt A.getVoid_virt, v0
580    return.void
581}
582
583.function i32 Test4.func_A_getObj_static__noinline__() <static> {
584    newobj v0, A
585    ldai 0x5
586    stobj v0, A.data
587    call A.getObj, v0
588    return
589}
590
591.function i32 Test4.func_A_getObj_virtual__noinline__() <static> {
592    newobj v0, A
593    ldai 0x6
594    stobj v0, A.data
595    call.virt A.getObj_virt, v0
596    return
597}
598
599.function i32 Test4.func_A_setObj_static__noinline__() <static> {
600    newobj v0, A
601    movi v1, 0x7
602    call A.setObj, v0, v1
603    ldobj v0, A.data
604    return
605}
606
607.function i32 Test4.func_A_setObj_virtual__noinline__() <static> {
608    newobj v0, A
609    movi v1, 0x8
610    call.virt A.setObj_virt, v0, v1
611    ldobj v0, A.data
612    return
613}
614
615.function i32 Test4.func_A_getObj_wrong_virtual__noinline__() <static> {
616    newobj v0, A
617    newobj v1, A
618    ldai 0x9
619    stobj v0, A.data
620    ldai 0x10
621    stobj v1, A.data
622    call.virt A.getObj_wrong_virt, v0, v1
623    return
624}
625
626.function i32 Test4.func_A_setObj_wrong_virtual__noinline__() <static> {
627    newobj v0, A
628    newobj v2, A
629    movi v1, 0x11
630    call.virt A.setObj_wrong_virt, v0, v1, v2
631    ldobj v2, A.data
632    return
633}
634
635.function i32 Test4.func_A_setObjConst_virtual__noinline__() <static> {
636    newobj v0, A
637    call.virt A.setObjConst_virt, v0
638    ldobj v0, A.data
639    return
640}
641
642.function i32 Test4.func_A_setObj_multiple__noinline__() <static> {
643    newobj v0, A
644    movi v1, 42
645    movi v2, 0
646    call A.setObj_multiple, v0, v1, v2
647    ldobj v0, A.data
648    return
649}
650
651.function i32 Test4.func_A_complexMethod__noinline__() <static> {
652    newobj v0, A
653    call.virt A.complexMethod, v0
654    sta v0
655    ldai 42
656    jeq v0, success
657    ldai 1
658    return
659success:
660    ldai 0
661    return
662}
663
664.function i32 Test4.func_A_setObj_unknown_target__noinline__(A a0) <static> {
665    movi v0, 0
666    call A.setObj, a0, v0
667    ldobj a0, A.data
668    return
669}
670
671.function i32 Test4.func_A_setObj_unknown_target_wrapper__noinline__() <static> {
672    newobj v0, A
673    call Test4.func_A_setObj_unknown_target__noinline__, v0
674    return
675}
676
677.function i32 Test4.main() {
678    movi v0, 0x1
679    call Test4.func_A_getConst_static__noinline__
680    jne v0, error_exit_1
681    movi v0, 0x2
682    call Test4.func_A_getConst_virtual__noinline__
683    jne v0, error_exit_2
684    movi v0, 0x3
685    call Test4.func_A_getParam_static__noinline__, v0
686    jne v0, error_exit_3
687    movi v0, 0x4
688    call Test4.func_A_getParam_virtual__noinline__, v0
689    jne v0, error_exit_4
690    call Test4.func_A_getVoid_static__noinline__, v0
691    call Test4.func_A_getVoid_virtual__noinline__, v0
692    movi v0, 0x5
693    call Test4.func_A_getObj_static__noinline__
694    jne v0, error_exit_5
695    movi v0, 0x6
696    call Test4.func_A_getObj_virtual__noinline__
697    jne v0, error_exit_6
698    movi v0, 0x7
699    call Test4.func_A_setObj_static__noinline__
700    jne v0, error_exit_7
701    movi v0, 0x8
702    call Test4.func_A_setObj_virtual__noinline__
703    jne v0, error_exit_8
704    movi v0, 0x9
705    call Test4.func_A_setObjConst_virtual__noinline__
706    jne v0, error_exit_9
707    movi v0, 0x10
708    call Test4.func_A_getObj_wrong_virtual__noinline__
709    jne v0, error_exit_10
710    movi v0, 0x11
711    call Test4.func_A_setObj_wrong_virtual__noinline__
712    jne v0, error_exit_11
713    call Test4.func_A_setObj_multiple__noinline__
714    jnez error_exit_12
715    call Test4.func_A_complexMethod__noinline__
716    jnez error_exit_13
717    call Test4.func_A_setObj_unknown_target_wrapper__noinline__
718    jnez error_exit_14
719    ldai 0x0
720    return
721error_exit_1:
722    ldai 0x1
723    return
724error_exit_2:
725    ldai 0x2
726error_exit_3:
727    ldai 0x3
728    return
729error_exit_4:
730    ldai 0x4
731    return
732error_exit_5:
733    ldai 0x5
734    return
735error_exit_6:
736    ldai 0x6
737    return
738error_exit_7:
739    ldai 0x7
740    return
741error_exit_8:
742    ldai 0x8
743    return
744error_exit_9:
745    ldai 0x9
746    return
747error_exit_10:
748    ldai 0xa
749    return
750error_exit_11:
751    ldai 0xb
752    return
753error_exit_12:
754    ldai 0xc
755    return
756error_exit_13:
757    ldai 0xd
758    return
759error_exit_14:
760    ldai 0xe
761    return
762}
763
764#! CHECKER      Inline nested calls in AOT mode
765#! RUN_PAOC     options: "--panda-files=../../inline.checked/test.abc --compiler-regex=NestedCalls::main"
766#! EVENT        /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/
767#! EVENT        /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/
768
769#! CHECKER      Inline nested calls in JIT mode
770#! RUN          force_jit: true, entry: "NestedCalls::main", options: "--compiler-regex=NestedCalls::main --compiler-no-cha-inlining"
771#! EVENT        /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/
772#! EVENT        /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/
773.record NestedCalls {}
774.function i32 NestedCalls.outer(NestedCalls a0) {
775    call.virt NestedCalls.inner, a0
776    return
777}
778.function i32 NestedCalls.inner(NestedCalls a0) {
779    ldai 0
780    return
781}
782.function i32 NestedCalls.main() <static> {
783    newobj v0, NestedCalls
784    call.virt NestedCalls.outer, v0
785    return
786}
787
788#! CHECKER           Inline final class
789#! RUN               force_jit: true, options: "", entry: "Test5::main"
790#! EVENT             /Inline,B1::func__noinline__,B1::func,.*VIRTUAL,SUCCESS/
791#! EVENT_NEXT        /Inline,B1::func__noinline__,C1::func,.*VIRTUAL,SUCCESS/
792#! EVENT_NOT         /Inline,B1::func__noinline__,A1::func,.*VIRTUAL,SUCCESS/
793
794#! CHECKER           Inline final class AOT
795#! RUN_PAOC          options: ""
796#! EVENT             /Inline,B1::func__noinline__,B1::func,.*VIRTUAL,SUCCESS/
797#! EVENT_NEXT        /Inline,B1::func__noinline__,C1::func,.*VIRTUAL,SUCCESS/
798#! EVENT_NOT         /Inline,B1::func__noinline__,A1::func,.*VIRTUAL,SUCCESS/
799#! RUN               options: "", entry: "Test5::main"
800
801.record Test5 {}
802.record A1 {}
803.record B1 <extends=A1, final> {}
804.record C1 <final> {}
805
806.function i32 A1.func(A1 a0) {
807    ldai 1
808    return
809}
810
811.function i32 B1.func(B1 a0) {
812    ldai 2
813    return
814}
815
816.function i32 C1.func(C1 a0) {
817    ldai 3
818    return
819}
820
821.function i32 A1.func__noinline__(A1 a0, C1 a1, A1 a2) {
822    ldai 5
823    return
824}
825
826.function i32 B1.func__noinline__(B1 a0, C1 a1, A1 a2) {
827    call.virt A1.func, a0
828    movi v0, 0x2
829    jne v0, error_exit_1
830    call.virt C1.func, a1
831    movi v0, 0x3
832    jne v0, error_exit_2
833    call.virt A1.func, a2
834    movi v0, 0x1
835    jne v0, error_exit_3
836    ldai 0x0
837    return
838error_exit_1:
839    ldai 0x1
840    return
841error_exit_2:
842    ldai 0x2
843    return
844error_exit_3:
845    ldai 0x3
846    return
847}
848
849.function i32 Test5.main() {
850    newobj v0, A1
851    newobj v1, B1
852    newobj v2, C1
853
854    call.virt A1.func__noinline__, v1, v2, v0
855    return
856}
857