xref: /llvm-project/llvm/test/CodeGen/XCore/epilogue_prologue.ll (revision 806761a7629df268c8aed49657aeccffa6bca449)
1; RUN: llc < %s -mtriple=xcore | FileCheck %s
2; RUN: llc < %s -mtriple=xcore -frame-pointer=all | FileCheck %s -check-prefix=CHECKFP
3
4; When using SP for small frames, we don't need any scratch registers (SR).
5; When using SP for large frames, we may need two scratch registers.
6; When using FP, for large or small frames, we may need one scratch register.
7
8; FP + small frame: spill FP+SR = entsp 2
9; CHECKFP-LABEL: f1:
10; CHECKFP: entsp 2
11; CHECKFP-NEXT: stw r10, sp[1]
12; CHECKFP-NEXT: ldaw r10, sp[0]
13; CHECKFP: set sp, r10
14; CHECKFP-NEXT: ldw r10, sp[1]
15; CHECKFP-NEXT: retsp 2
16;
17; !FP + small frame: no spills = no stack adjustment needed
18; CHECK-LABEL: f1:
19; CHECK: stw lr, sp[0]
20; CHECK: ldw lr, sp[0]
21; CHECK-NEXT: retsp 0
22define void @f1() nounwind {
23entry:
24  tail call void asm sideeffect "", "~{lr}"() nounwind
25  ret void
26}
27
28
29; FP + small frame: spill FP+SR+R0+LR = entsp 3 + extsp 1
30; CHECKFP-LABEL: f3:
31; CHECKFP: entsp 3
32; CHECKFP-NEXT: stw r10, sp[1]
33; CHECKFP-NEXT: ldaw r10, sp[0]
34; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[2]
35; CHECKFP-NEXT: mov [[REG]], r0
36; CHECKFP-NEXT: extsp 1
37; CHECKFP-NEXT: bl f2
38; CHECKFP-NEXT: ldaw sp, sp[1]
39; CHECKFP-NEXT: mov r0, [[REG]]
40; CHECKFP-NEXT: ldw [[REG]], r10[2]
41; CHECKFP-NEXT: set sp, r10
42; CHECKFP-NEXT: ldw r10, sp[1]
43; CHECKFP-NEXT: retsp 3
44;
45; !FP + small frame: spill R0+LR = entsp 2
46; CHECK-LABEL: f3:
47; CHECK: entsp 2
48; CHECK-NEXT: stw [[REG:r[4-9]+]], sp[1]
49; CHECK-NEXT: mov [[REG]], r0
50; CHECK-NEXT: bl f2
51; CHECK-NEXT: mov r0, [[REG]]
52; CHECK-NEXT: ldw [[REG]], sp[1]
53; CHECK-NEXT: retsp 2
54declare void @f2()
55define i32 @f3(i32 %i) nounwind {
56entry:
57  call void @f2()
58  ret i32 %i
59}
60
61
62; FP + large frame: spill FP+SR = entsp 2 + 100000
63; CHECKFP-LABEL: f4:
64; CHECKFP: entsp 65535
65; CHECKFP-NEXT: .cfi_def_cfa_offset 262140
66; CHECKFP-NEXT: .cfi_offset 15, 0
67; CHECKFP-NEXT: extsp 34467
68; CHECKFP-NEXT: .cfi_def_cfa_offset 400008
69; CHECKFP-NEXT: stw r10, sp[1]
70; CHECKFP-NEXT: .cfi_offset 10, -400004
71; CHECKFP-NEXT: ldaw r10, sp[0]
72; CHECKFP-NEXT: .cfi_def_cfa_register 10
73; CHECKFP-NEXT: set sp, r10
74; CHECKFP-NEXT: ldw r10, sp[1]
75; CHECKFP-NEXT: ldaw sp, sp[65535]
76; CHECKFP-NEXT: retsp 34467
77;
78; !FP + large frame: spill SR+SR = entsp 2 + 100000
79; CHECK-LABEL: f4:
80; CHECK: entsp 65535
81; CHECK-NEXT: .cfi_def_cfa_offset 262140
82; CHECK-NEXT: .cfi_offset 15, 0
83; CHECK-NEXT: extsp 34467
84; CHECK-NEXT: .cfi_def_cfa_offset 400008
85; CHECK-NEXT: ldaw sp, sp[65535]
86; CHECK-NEXT: retsp 34467
87define void @f4() {
88entry:
89  %0 = alloca [100000 x i32]
90  ret void
91}
92
93
94; FP + large frame: spill FP+SR+R4+LR = entsp 3 + 200000  + extsp 1
95; CHECKFP: .section .cp.rodata.cst4,"aMc",@progbits,4
96; CHECKFP-NEXT: .p2align 2
97; CHECKFP-NEXT: .LCPI[[CNST0:[0-9_]+]]:
98; CHECKFP-NEXT: .long 200002
99; CHECKFP-NEXT: .LCPI[[CNST1:[0-9_]+]]:
100; CHECKFP-NEXT: .long 200001
101; CHECKFP-NEXT: .text
102; CHECKFP-LABEL: f6:
103; CHECKFP: entsp 65535
104; CHECKFP-NEXT: .cfi_def_cfa_offset 262140
105; CHECKFP-NEXT: .cfi_offset 15, 0
106; CHECKFP-NEXT: extsp 65535
107; CHECKFP-NEXT: .cfi_def_cfa_offset 524280
108; CHECKFP-NEXT: extsp 65535
109; CHECKFP-NEXT: .cfi_def_cfa_offset 786420
110; CHECKFP-NEXT: extsp 3398
111; CHECKFP-NEXT: .cfi_def_cfa_offset 800012
112; CHECKFP-NEXT: stw r10, sp[1]
113; CHECKFP-NEXT: .cfi_offset 10, -800008
114; CHECKFP-NEXT: ldaw r10, sp[0]
115; CHECKFP-NEXT: .cfi_def_cfa_register 10
116; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
117; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[r1]
118; CHECKFP-NEXT: .cfi_offset 4, -4
119; CHECKFP-NEXT: mov [[REG]], r0
120; CHECKFP-NEXT: extsp 1
121; CHECKFP-NEXT: ldaw r0, r10[2]
122; CHECKFP-NEXT: bl f5
123; CHECKFP-NEXT: ldaw sp, sp[1]
124; CHECKFP-NEXT: ldw r1, cp[.LCPI3_1]
125; CHECKFP-NEXT: ldaw r0, r10[r1]
126; CHECKFP-NEXT: extsp 1
127; CHECKFP-NEXT: bl f5
128; CHECKFP-NEXT: ldaw sp, sp[1]
129; CHECKFP-NEXT: mov r0, [[REG]]
130; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
131; CHECKFP-NEXT: ldw [[REG]], r10[r1]
132; CHECKFP-NEXT: set sp, r10
133; CHECKFP-NEXT: ldw r10, sp[1]
134; CHECKFP-NEXT: ldaw sp, sp[65535]
135; CHECKFP-NEXT: ldaw sp, sp[65535]
136; CHECKFP-NEXT: ldaw sp, sp[65535]
137; CHECKFP-NEXT: retsp 3398
138;
139; !FP + large frame: spill SR+SR+R4+LR = entsp 4 + 200000
140; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4
141; CHECK-NEXT: .p2align 2
142; CHECK-NEXT: .LCPI[[CNST0:[0-9_]+]]:
143; CHECK-NEXT: .long 200003
144; CHECK-NEXT: .LCPI[[CNST1:[0-9_]+]]:
145; CHECK-NEXT: .long 200002
146; CHECK-NEXT: .text
147; CHECK-LABEL: f6:
148; CHECK: entsp 65535
149; CHECK-NEXT: .cfi_def_cfa_offset 262140
150; CHECK-NEXT: .cfi_offset 15, 0
151; CHECK-NEXT: extsp 65535
152; CHECK-NEXT: .cfi_def_cfa_offset 524280
153; CHECK-NEXT: extsp 65535
154; CHECK-NEXT: .cfi_def_cfa_offset 786420
155; CHECK-NEXT: extsp 3399
156; CHECK-NEXT: .cfi_def_cfa_offset 800016
157; CHECK-NEXT: ldaw r1, sp[0]
158; CHECK-NEXT: ldw r2, cp[.LCPI[[CNST0]]]
159; CHECK-NEXT: stw [[REG:r[4-9]+]], r1[r2]
160; CHECK-NEXT: .cfi_offset 4, -4
161; CHECK-NEXT: mov [[REG]], r0
162; CHECK-NEXT: ldaw r0, sp[3]
163; CHECK-NEXT: bl f5
164; CHECK-NEXT: ldaw r0, sp[0]
165; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST1]]]
166; CHECK-NEXT: ldaw r0, r0[r1]
167; CHECK-NEXT: bl f5
168; CHECK-NEXT: mov r0, [[REG]]
169; CHECK-NEXT: ldaw [[REG]], sp[0]
170; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
171; CHECK-NEXT: ldw [[REG]], [[REG]][r1]
172; CHECK-NEXT: ldaw sp, sp[65535]
173; CHECK-NEXT: ldaw sp, sp[65535]
174; CHECK-NEXT: ldaw sp, sp[65535]
175; CHECK-NEXT: retsp 3399
176declare void @f5(ptr)
177define i32 @f6(i32 %i) {
178entry:
179  %0 = alloca [200000 x i32]
180  call void @f5(ptr %0)
181  %1 = getelementptr inbounds [200000 x i32], ptr %0, i32 0, i32 199999
182  call void @f5(ptr %1)
183  ret i32 %i
184}
185
186; FP + large frame: spill FP+SR+LR = entsp 2 + 256  + extsp 1
187; CHECKFP-LABEL: f8:
188; CHECKFP: entsp 258
189; CHECKFP-NEXT: stw r10, sp[1]
190; CHECKFP-NEXT: ldaw r10, sp[0]
191; CHECKFP-NEXT: mkmsk [[REG:r[0-9]+]], 8
192; CHECKFP-NEXT: ldaw r0, r10[[[REG]]]
193; CHECKFP-NEXT: extsp 1
194; CHECKFP-NEXT: bl f5
195; CHECKFP-NEXT: ldaw sp, sp[1]
196; CHECKFP-NEXT: set sp, r10
197; CHECKFP-NEXT: ldw r10, sp[1]
198; CHECKFP-NEXT: retsp 258
199;
200; !FP + large frame: spill SR+SR+LR = entsp 3 + 256
201; CHECK-LABEL: f8:
202; CHECK: entsp 257
203; CHECK-NEXT: ldaw r0, sp[254]
204; CHECK-NEXT: bl f5
205; CHECK-NEXT: retsp 257
206define void @f8() nounwind {
207entry:
208  %0 = alloca [256 x i32]
209  %1 = getelementptr inbounds [256 x i32], ptr %0, i32 0, i32 253
210  call void @f5(ptr %1)
211  ret void
212}
213
214; FP + large frame: spill FP+SR+LR = entsp 2 + 32768  + extsp 1
215; CHECKFP-LABEL: f9:
216; CHECKFP: entsp 32770
217; CHECKFP-NEXT: stw r10, sp[1]
218; CHECKFP-NEXT: ldaw r10, sp[0]
219; CHECKFP-NEXT: ldc [[REG:r[0-9]+]], 32767
220; CHECKFP-NEXT: ldaw r0, r10[[[REG]]]
221; CHECKFP-NEXT: extsp 1
222; CHECKFP-NEXT: bl f5
223; CHECKFP-NEXT: ldaw sp, sp[1]
224; CHECKFP-NEXT: set sp, r10
225; CHECKFP-NEXT: ldw r10, sp[1]
226; CHECKFP-NEXT: retsp 32770
227;
228; !FP + large frame: spill SR+SR+LR = entsp 3 + 32768
229; CHECK-LABEL: f9:
230; CHECK: entsp 32771
231; CHECK-NEXT: ldaw r0, sp[32768]
232; CHECK-NEXT: bl f5
233; CHECK-NEXT: retsp 32771
234define void @f9() nounwind {
235entry:
236  %0 = alloca [32768 x i32]
237  %1 = getelementptr inbounds [32768 x i32], ptr %0, i32 0, i32 32765
238  call void @f5(ptr %1)
239  ret void
240}
241