1;; Test leaf function detection across different function types.
2;; This test verifies that the is_leaf detection works correctly for:
3;; - True leaf functions (no calls)
4;; - Non-leaf functions (with calls, call_indirect)
5
6test compile precise-output
7set unwind_info=false
8set preserve_frame_pointers=false
9target riscv64
10
11;; Test 1: Simple leaf function - just arithmetic operations
12function %simple_leaf(i32) -> i32 {
13block0(v0: i32):
14    v1 = iconst.i32 10
15    v2 = imul v0, v1
16    return v2
17}
18
19; VCode:
20; block0:
21;   li a1,10
22;   mulw a0,a0,a1
23;   ret
24;
25; Disassembled:
26; block0: ; offset 0x0
27;   addi a1, zero, 0xa
28;   mulw a0, a0, a1
29;   ret
30
31;; Test 2: Leaf function with multiple basic blocks and control flow
32function %leaf_with_branches(i32) -> i32 {
33block0(v0: i32):
34    v1 = iconst.i32 0
35    v2 = icmp sgt v0, v1
36    brif v2, block1, block2
37
38block1:
39    v3 = iconst.i32 2
40    v4 = imul v0, v3
41    jump block3(v4)
42
43block2:
44    v5 = isub v1, v0
45    jump block3(v5)
46
47block3(v6: i32):
48    return v6
49}
50
51; VCode:
52; block0:
53;   li a1,0
54;   sext.w a2,a0
55;   bgt a2,zero,taken(label2),not_taken(label1)
56; block1:
57;   subw a0,a1,a0
58;   j label3
59; block2:
60;   li a1,2
61;   mulw a0,a0,a1
62;   j label3
63; block3:
64;   ret
65;
66; Disassembled:
67; block0: ; offset 0x0
68;   mv a1, zero
69;   sext.w a2, a0
70;   bgtz a2, 0xc
71; block1: ; offset 0xc
72;   subw a0, a1, a0
73;   j 0xc
74; block2: ; offset 0x14
75;   addi a1, zero, 2
76;   mulw a0, a0, a1
77; block3: ; offset 0x1c
78;   ret
79
80;; Test 3: Non-leaf function with direct call
81function %non_leaf_with_call(i32) -> i32 {
82    sig0 = (i32) -> i32
83    fn0 = colocated %simple_leaf sig0
84
85block0(v0: i32):
86    v1 = call fn0(v0)
87    return v1
88}
89
90; VCode:
91;   addi sp,sp,-16
92;   sd ra,8(sp)
93;   sd fp,0(sp)
94;   mv fp,sp
95; block0:
96;   call %simple_leaf
97;   ld ra,8(sp)
98;   ld fp,0(sp)
99;   addi sp,sp,16
100;   ret
101;
102; Disassembled:
103; block0: ; offset 0x0
104;   addi sp, sp, -0x10
105;   sd ra, 8(sp)
106;   sd s0, 0(sp)
107;   mv s0, sp
108; block1: ; offset 0x10
109;   auipc ra, 0 ; reloc_external RiscvCallPlt %simple_leaf 0
110;   jalr ra
111;   ld ra, 8(sp)
112;   ld s0, 0(sp)
113;   addi sp, sp, 0x10
114;   ret
115
116;; Test 4: Non-leaf function with indirect call
117function %non_leaf_with_call_indirect(i32, i64) -> i32 {
118    sig0 = (i32) -> i32
119
120block0(v0: i32, v1: i64):
121    v2 = call_indirect sig0, v1(v0)
122    return v2
123}
124
125; VCode:
126;   addi sp,sp,-16
127;   sd ra,8(sp)
128;   sd fp,0(sp)
129;   mv fp,sp
130; block0:
131;   callind a1
132;   ld ra,8(sp)
133;   ld fp,0(sp)
134;   addi sp,sp,16
135;   ret
136;
137; Disassembled:
138; block0: ; offset 0x0
139;   addi sp, sp, -0x10
140;   sd ra, 8(sp)
141;   sd s0, 0(sp)
142;   mv s0, sp
143; block1: ; offset 0x10
144;   jalr a1
145;   ld ra, 8(sp)
146;   ld s0, 0(sp)
147;   addi sp, sp, 0x10
148;   ret
149
150;; Test 5: Leaf function with memory operations (should still be leaf)
151function %leaf_with_memory(i32, i64) -> i32 {
152block0(v0: i32, v1: i64):
153    store v0, v1
154    v2 = load.i32 v1
155    v3 = iconst.i32 1
156    v4 = iadd v2, v3
157    return v4
158}
159
160; VCode:
161; block0:
162;   sw a0,0(a1)
163;   lw a0,0(a1)
164;   addiw a0,a0,1
165;   ret
166;
167; Disassembled:
168; block0: ; offset 0x0
169;   sw a0, 0(a1) ; trap: heap_oob
170;   lw a0, 0(a1) ; trap: heap_oob
171;   addiw a0, a0, 1
172;   ret
173
174;; Test 6: Leaf function that looks like it might call but doesn't
175function %leaf_no_actual_calls(i32) -> i32 {
176block0(v0: i32):
177    v1 = iconst.i32 42
178    v2 = imul v0, v1
179    v3 = iconst.i32 7
180    v4 = udiv v2, v3
181    v5 = iconst.i32 3
182    v6 = band v4, v5
183    return v6
184}
185
186; VCode:
187; block0:
188;   li a1,42
189;   mulw a0,a0,a1
190;   li a1,7
191;   divuw a0,a0,a1
192;   andi a0,a0,3
193;   ret
194;
195; Disassembled:
196; block0: ; offset 0x0
197;   addi a1, zero, 0x2a
198;   mulw a0, a0, a1
199;   addi a1, zero, 7
200;   divuw a0, a0, a1
201;   andi a0, a0, 3
202;   ret
203