• 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 max size
24#! RUN          force_jit: true, options: "--compiler-regex=Test1::main --compiler-inlining-max-size=6", entry: "Test1::main"
25#! EVENT        /Inline,Test1::main,_GLOBAL::func,.*STATIC,LIMIT/
26#! EVENT_NEXT   /Inline,Test1::main,_GLOBAL::small_func,.*STATIC,SUCCESS/
27
28.record Test1 {}
29
30.function i32 func(i32 a0) {
31    newobj v0, Test1
32    newobj v0, Test1
33    ldai 1
34    add2 a0
35    return
36}
37
38.function i32 small_func(i32 a0) {
39    ldai 1
40    add2 a0
41    return
42}
43
44.function i32 Test1.main() {
45    movi v1, 10
46
47    call.short func, v1
48    call.short small_func, v1
49    add2 v1
50
51    ldai 0
52    return
53}
54
55#! CHECKER      Inline depth limit
56#! RUN          force_jit: true, options: "--compiler-regex=Test1::main_depth --compiler-inlining-max-depth=2", entry: "Test1::main_depth"
57#! EVENTS_COUNT /Inline,Test1::main_depth,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
58#! EVENTS_COUNT /Inline,_GLOBAL::func_rec,_GLOBAL::func_rec,.*STATIC,SUCCESS/, 1
59
60.function i32 func_rec(i32 a0) {
61    lda a0
62    jeqz exit
63    subi 1
64    sta a0
65    call.short func_rec, a0
66exit:
67    return
68}
69
70.function i32 Test1.main_depth() {
71    movi v1, 10
72
73    call.short func_rec, v1
74
75    return
76}
77
78#! CHECKER      Check inlined float array
79#! RUN          force_jit: true, options: "--compiler-regex=_GLOBAL::main", entry: "_GLOBAL::main"
80#! EVENT        /Inline,_GLOBAL::main,_GLOBAL::farray,.*STATIC,SUCCESS/
81#! METHOD       "_GLOBAL::main"
82#! PASS_AFTER   "Inline"
83#! INST         "CallStatic.Inlined"
84
85.function void farray(f64[] a0) {
86    ldai 2
87    movi v0, 1
88    fstarr.64 a0, v0
89    return.void
90}
91
92.function i32 main() {
93    movi v0, 5
94    newarr v1, v0, f64[]
95    call.short farray, v1
96    ldai 0
97    return
98}
99
100#! CHECKER      Inline function with dead loop
101#! RUN          force_jit: true, options: "--compiler-regex=_GLOBAL::main1", entry: "_GLOBAL::main1"
102#! EVENT        /Inline,_GLOBAL::main1,_GLOBAL::foo1,.*STATIC,SUCCESS/
103#! METHOD       "_GLOBAL::main1"
104#! PASS_AFTER   "Inline"
105#! INST_NOT     "CallStatic.Inlined"
106#! INST_NOT     "Return.Inlined"
107#! INST_NOT     "SaveStateDeoptimize"
108
109.function i32 foo1() {
110  movi v1, 0
111  ldai 10
112lbl:
113  jle v1, lbl     # jump to 0 offset, never happens
114  ldai 0
115  return
116}
117
118.function i32 main1() {
119  call foo1
120  return
121}
122
123
124#! CHECKER      Change to CallStatic by instructions limit
125#! RUN          force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-insts=12", entry: "Test2::main"
126#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
127#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
128#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
129
130#! CHECKER      Change to CallStatic by instructions max size
131#! RUN          force_jit: true, options: "--compiler-regex=Test2::main --compiler-inlining-max-size=6", entry: "Test2::main"
132#! EVENT        /Inline,Test2::main,Test2::func,.*VIRTUAL,LIMIT/
133#! EVENT_NEXT   /Inline,Test2::main,Test2::func,.*VIRTUAL,DEVIRTUALIZED/
134#! EVENT_NEXT   /Inline,Test2::main,Test2::small_func,.*VIRTUAL,SUCCESS/
135
136.record Test2 {}
137
138.function i32 Test2.func(Test2 a0, i32 a1) {
139    newobj v0, Test1
140    newobj v0, Test1
141    newobj v0, Test1
142    newobj v0, Test1
143    ldai 1
144    add2 a1
145    return
146}
147
148.function i32 Test2.small_func(Test2 a0, i32 a1) {
149    ldai 1
150    add2 a1
151    return
152}
153
154.function i32 Test2.main() {
155    newobj v0, Test2
156    movi v1, 10
157
158    call.virt Test2.func, v0, v1
159    call.virt Test2.small_func, v0, v1
160    add2 v1
161
162    ldai 0
163    return
164}
165
166#! CHECKER      Do not inline infinite loop
167#! RUN          force_jit: true, entry: "Test3::main"
168#! EVENT        /Inline,Test3::main,Test3::foo1,.*VIRTUAL,SUCCESS/
169#! EVENT        /Inline,Test3::main,_GLOBAL::foo_inf_loop,.*STATIC,INF_LOOP/
170
171
172.record Test3 {}
173
174.function i32 Test3.foo1(Test3 a0) {
175    ldai 0
176    return
177}
178
179.function i32 foo_inf_loop(i32 a0) {
180    lda a0
181    jeqz exit
182loop:
183    addi 1
184    sta a0
185    jmp loop
186exit:
187    return
188}
189
190.function i32 Test3.main() {
191  newobj v0, Test3
192  call.virt Test3.foo1, v0
193  jeqz exit
194  sta v1
195  call.short foo_inf_loop, v1
196  ldai 0
197exit:
198  return
199}
200
201#! CHECKER  Inline external files in AOT mode
202#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --compiler-regex=Test4.*"
203#! METHOD       "Test4::func_A_getConst_static__noinline__"
204#! PASS_AFTER   "IrBuilder"
205#! INST         /CallStatic.*A::getConst/
206#! INST_NOT     "Constant"
207#! PASS_AFTER   "Inline"
208#! INST_NOT     /CallStatic.*A::getConst/
209#! INST         "Constant"
210#! METHOD       "Test4::func_A_getConst_virtual__noinline__"
211#! PASS_AFTER   "IrBuilder"
212#! INST         /CallVirtual.*A::getConst/
213#! INST_NOT     "Constant"
214#! PASS_AFTER   "Inline"
215#! INST_NOT     /CallVirtual.*A::getConst/
216#! INST         "Constant"
217#! METHOD       "Test4::func_A_getParam_static__noinline__"
218#! PASS_AFTER   "IrBuilder"
219#! INST         /CallStatic.*A::getParam/
220#! PASS_AFTER   "Inline"
221#! INST_NOT     /CallStatic.*A::getParam/
222#! METHOD       "Test4::func_A_getParam_virtual__noinline__"
223#! PASS_AFTER   "IrBuilder"
224#! INST         /CallVirtual.*A::getParam/
225#! PASS_AFTER   "Inline"
226#! INST_NOT     /CallVirtual.*A::getParam/
227#! METHOD       "Test4::func_A_getVoid_static__noinline__"
228#! PASS_AFTER   "IrBuilder"
229#! INST         /CallStatic.*A::getVoid/
230#! PASS_AFTER   "Inline"
231#! INST_NOT     /CallStatic.*A::getVoid/
232#! METHOD       "Test4::func_A_getVoid_virtual__noinline__"
233#! PASS_AFTER   "IrBuilder"
234#! INST         /CallVirtual.*A::getVoid/
235#! PASS_AFTER   "Inline"
236#! INST_NOT     /CallVirtual.*A::getVoid/
237#! METHOD       "Test4::func_A_getObj_static__noinline__"
238#! PASS_AFTER   "IrBuilder"
239#! INST         /CallStatic.*A::getObj/
240#! INST_NOT     "LoadObject"
241#! PASS_AFTER   "Inline"
242#! INST_NOT      /CallStatic.*A::getObj/
243#! INST         "LoadObject"
244#! METHOD       "Test4::func_A_getObj_virtual__noinline__"
245#! PASS_AFTER   "IrBuilder"
246#! INST         /CallVirtual.*A::getObj/
247#! INST_NOT     "LoadObject"
248#! PASS_AFTER   "Inline"
249#! INST_NOT     /CallVirtual.*A::getObj/
250#! INST         "LoadObject"
251#! METHOD       "Test4::func_A_setObj_static__noinline__"
252#! PASS_AFTER   "IrBuilder"
253#! INST         /CallStatic.*A::setObj/
254#! INST_NOT     "StoreObject"
255#! PASS_AFTER   "Inline"
256#! INST_NOT     /CallStatic.*A::setObj/
257#! INST         "StoreObject"
258#! METHOD       "Test4::func_A_setObj_virtual__noinline__"
259#! PASS_AFTER   "IrBuilder"
260#! INST         /CallVirtual.*A::setObj/
261#! INST_NOT     "StoreObject"
262#! PASS_AFTER   "Inline"
263#! INST_NOT     /CallVirtual.*A::setObj/
264#! INST         "StoreObject"
265#! METHOD       "Test4::func_A_getObj_wrong_virtual__noinline__"
266#! PASS_AFTER   "IrBuilder"
267#! INST         /CallVirtual.*A::getObj/
268#! INST_NOT     "LoadObject"
269#! PASS_AFTER   "Inline"
270#! INST_NOT      /CallVirtual.*A::getObj/
271#! INST         "LoadObject"
272#! METHOD       "Test4::func_A_setObj_wrong_virtual__noinline__"
273#! PASS_AFTER   "IrBuilder"
274#! INST         /CallVirtual.*A::setObj/
275#! INST_NOT     "StoreObject"
276#! PASS_AFTER   "Inline"
277#! INST_NOT     /CallVirtual.*A::setObj/
278#! INST         "StoreObject"
279#! METHOD       "Test4::func_A_setObj_multiple__noinline__"
280#! PASS_AFTER   "IrBuilder"
281#! INST         /CallStatic.*A::setObj_multiple/
282#! PASS_AFTER   "Inline"
283#! INST_NOT     /CallStatic.*A::setObj_multiple/
284#! METHOD       "Test4::func_A_complexMethod__noinline__"
285#! PASS_AFTER   "IrBuilder"
286#! INST         /CallVirtual.*A::complexMethod/
287#! PASS_AFTER   "Inline"
288#! INST_NOT     /CallVirtual.*A::complexMethod/
289#! METHOD       "Test4::func_A_setObj_unknown_target__noinline__"
290#! PASS_AFTER   "IrBuilder"
291#! INST         /CallStatic.*A::setObj/
292#! PASS_AFTER   "Inline"
293#! INST         /CallStatic.*A::setObj/
294#! RUN          options: "--panda-files=../../inline_external.checked/test.abc", entry: "Test4::main"
295
296#! CHECKER  Don't inline external files in AOT mode without cha
297#! RUN_PAOC     options: "--panda-files=../../inline_external.checked/test.abc --paoc-use-cha=false --compiler-regex=Test4.*"
298#! METHOD       "Test4::func_A_getConst_static__noinline__"
299#! PASS_AFTER   "IrBuilder"
300#! INST         /CallStatic.*A::getConst/
301#! INST_NOT     "Constant"
302#! PASS_AFTER   "Inline"
303#! INST         /CallStatic.*A::getConst/
304#! INST_NOT     "Constant"
305
306.record A {
307    i32 data <external>
308}
309.record A.data <external>
310.function i32 A.getConst() <external,static>
311.function i32 A.getConst_virt(A a0) <external>
312.function i32 A.getParam(i32 a0) <external,static>
313.function i32 A.getParam_virt(A a0, i32 a1) <external>
314.function void A.getVoid() <external,static>
315.function void A.getVoid_virt(A a0) <external>
316.function i32 A.getObj(A a0) <external,static>
317.function i32 A.getObj_virt(A a0) <external>
318.function void A.setObj(A a0, i32 a1) <external,static>
319.function void A.setObjConst_virt(A a0) <external>
320.function void A.setObj_virt(A a0, i32 a1) <external>
321.function i32 A.getObj_wrong_virt(A a0, A a1) <external>
322.function void A.setObj_wrong_virt(A a0, i32 a1, A a2) <external>
323.function void A.setObj_multiple(A a0, i32 a1, i32 a2) <external,static>
324.function i32 A.complexMethod(A a0) <external>
325
326.record Test4 {}
327
328.function i32 Test4.func_A_getConst_static__noinline__() <static> {
329    call A.getConst
330    return
331}
332
333.function i32 Test4.func_A_getConst_virtual__noinline__() <static> {
334    newobj v0, A
335    call.virt A.getConst_virt, v0
336    return
337}
338
339.function i32 Test4.func_A_getParam_static__noinline__(i32 a0) <static> {
340    call A.getParam, a0
341    return
342}
343
344.function i32 Test4.func_A_getParam_virtual__noinline__(i32 a0) <static> {
345    newobj v0, A
346    call.virt A.getParam_virt, v0, a0
347    return
348}
349
350.function void Test4.func_A_getVoid_static__noinline__() <static> {
351    call A.getVoid
352    return.void
353}
354
355.function void Test4.func_A_getVoid_virtual__noinline__() <static> {
356    newobj v0, A
357    call.virt A.getVoid_virt, v0
358    return.void
359}
360
361.function i32 Test4.func_A_getObj_static__noinline__() <static> {
362    newobj v0, A
363    ldai 0x5
364    stobj v0, A.data
365    call A.getObj, v0
366    return
367}
368
369.function i32 Test4.func_A_getObj_virtual__noinline__() <static> {
370    newobj v0, A
371    ldai 0x6
372    stobj v0, A.data
373    call.virt A.getObj_virt, v0
374    return
375}
376
377.function i32 Test4.func_A_setObj_static__noinline__() <static> {
378    newobj v0, A
379    movi v1, 0x7
380    call A.setObj, v0, v1
381    ldobj v0, A.data
382    return
383}
384
385.function i32 Test4.func_A_setObj_virtual__noinline__() <static> {
386    newobj v0, A
387    movi v1, 0x8
388    call.virt A.setObj_virt, v0, v1
389    ldobj v0, A.data
390    return
391}
392
393.function i32 Test4.func_A_getObj_wrong_virtual__noinline__() <static> {
394    newobj v0, A
395    newobj v1, A
396    ldai 0x9
397    stobj v0, A.data
398    ldai 0x10
399    stobj v1, A.data
400    call.virt A.getObj_wrong_virt, v0, v1
401    return
402}
403
404.function i32 Test4.func_A_setObj_wrong_virtual__noinline__() <static> {
405    newobj v0, A
406    newobj v2, A
407    movi v1, 0x11
408    call.virt A.setObj_wrong_virt, v0, v1, v2
409    ldobj v2, A.data
410    return
411}
412
413.function i32 Test4.func_A_setObjConst_virtual__noinline__() <static> {
414    newobj v0, A
415    call.virt A.setObjConst_virt, v0
416    ldobj v0, A.data
417    return
418}
419
420.function i32 Test4.func_A_setObj_multiple__noinline__() <static> {
421    newobj v0, A
422    movi v1, 42
423    movi v2, 0
424    call A.setObj_multiple, v0, v1, v2
425    ldobj v0, A.data
426    return
427}
428
429.function i32 Test4.func_A_complexMethod__noinline__() <static> {
430    newobj v0, A
431    call.virt A.complexMethod, v0
432    sta v0
433    ldai 42
434    jeq v0, success
435    ldai 1
436    return
437success:
438    ldai 0
439    return
440}
441
442.function i32 Test4.func_A_setObj_unknown_target__noinline__(A a0) <static> {
443    movi v0, 0
444    call A.setObj, a0, v0
445    ldobj a0, A.data
446    return
447}
448
449.function i32 Test4.func_A_setObj_unknown_target_wrapper__noinline__() <static> {
450    newobj v0, A
451    call Test4.func_A_setObj_unknown_target__noinline__, v0
452    return
453}
454
455.function i32 Test4.main() {
456    movi v0, 0x1
457    call Test4.func_A_getConst_static__noinline__
458    jne v0, error_exit_1
459    movi v0, 0x2
460    call Test4.func_A_getConst_virtual__noinline__
461    jne v0, error_exit_2
462    movi v0, 0x3
463    call Test4.func_A_getParam_static__noinline__, v0
464    jne v0, error_exit_3
465    movi v0, 0x4
466    call Test4.func_A_getParam_virtual__noinline__, v0
467    jne v0, error_exit_4
468    call Test4.func_A_getVoid_static__noinline__, v0
469    call Test4.func_A_getVoid_virtual__noinline__, v0
470    movi v0, 0x5
471    call Test4.func_A_getObj_static__noinline__
472    jne v0, error_exit_5
473    movi v0, 0x6
474    call Test4.func_A_getObj_virtual__noinline__
475    jne v0, error_exit_6
476    movi v0, 0x7
477    call Test4.func_A_setObj_static__noinline__
478    jne v0, error_exit_7
479    movi v0, 0x8
480    call Test4.func_A_setObj_virtual__noinline__
481    jne v0, error_exit_8
482    movi v0, 0x9
483    call Test4.func_A_setObjConst_virtual__noinline__
484    jne v0, error_exit_9
485    movi v0, 0x10
486    call Test4.func_A_getObj_wrong_virtual__noinline__
487    jne v0, error_exit_10
488    movi v0, 0x11
489    call Test4.func_A_setObj_wrong_virtual__noinline__
490    jne v0, error_exit_11
491    call Test4.func_A_setObj_multiple__noinline__
492    jnez error_exit_12
493    call Test4.func_A_complexMethod__noinline__
494    jnez error_exit_13
495    call Test4.func_A_setObj_unknown_target_wrapper__noinline__
496    jnez error_exit_14
497    ldai 0x0
498    return
499error_exit_1:
500    ldai 0x1
501    return
502error_exit_2:
503    ldai 0x2
504error_exit_3:
505    ldai 0x3
506    return
507error_exit_4:
508    ldai 0x4
509    return
510error_exit_5:
511    ldai 0x5
512    return
513error_exit_6:
514    ldai 0x6
515    return
516error_exit_7:
517    ldai 0x7
518    return
519error_exit_8:
520    ldai 0x8
521    return
522error_exit_9:
523    ldai 0x9
524    return
525error_exit_10:
526    ldai 0xa
527    return
528error_exit_11:
529    ldai 0xb
530    return
531error_exit_12:
532    ldai 0xc
533    return
534error_exit_13:
535    ldai 0xd
536    return
537error_exit_14:
538    ldai 0xe
539    return
540}
541
542#! CHECKER  Inline nested calls in AOT mode
543#! RUN_PAOC options: "--panda-files=../../inline.checked/test.abc --compiler-regex=NestedCalls::main"
544#! EVENT    /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/
545#! EVENT    /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/
546
547#! CHECKER  Inline nested calls in JIT mode
548#! RUN      force_jit: true, entry: "NestedCalls::main", options: "--compiler-regex=NestedCalls::main --compiler-no-cha-inlining"
549#! EVENT    /Inline,NestedCalls::outer,NestedCalls::inner,.*,VIRTUAL,SUCCESS/
550#! EVENT    /Inline,NestedCalls::main,NestedCalls::outer,.*,VIRTUAL,SUCCESS/
551.record NestedCalls {}
552.function i32 NestedCalls.outer(NestedCalls a0) {
553    call.virt NestedCalls.inner, a0
554    return
555}
556.function i32 NestedCalls.inner(NestedCalls a0) {
557    ldai 0
558    return
559}
560.function i32 NestedCalls.main() <static> {
561    newobj v0, NestedCalls
562    call.virt NestedCalls.outer, v0
563    return
564}