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