1 ; RUN: llc < %s -march=xcore | FileCheck %s
2 ; RUN: llc < %s -march=xcore -frame-pointer=all | FileCheck %s -check-prefix=CHECKFP
4 declare ptr @llvm.frameaddress(i32) nounwind readnone
5 declare ptr @llvm.returnaddress(i32) nounwind
6 declare ptr @llvm.eh.dwarf.cfa(i32) nounwind
7 declare void @llvm.eh.return.i32(i32, ptr) nounwind
8 declare void @llvm.eh.unwind.init() nounwind
10 define ptr @FA0() nounwind {
13 ; CHECK: ldaw r0, sp[0]
15 %0 = call ptr @llvm.frameaddress(i32 0)
19 define ptr @FA1() nounwind {
23 ; CHECK-NEXT: ldaw r0, sp[0]
24 ; CHECK-NEXT: retsp 100
25 %0 = alloca [100 x i32]
26 %1 = call ptr @llvm.frameaddress(i32 0)
30 define ptr @RA0() nounwind {
33 ; CHECK: stw lr, sp[0]
34 ; CHECK-NEXT: ldw r0, sp[0]
35 ; CHECK-NEXT: ldw lr, sp[0]
37 %0 = call ptr @llvm.returnaddress(i32 0)
41 define ptr @RA1() nounwind {
45 ; CHECK-NEXT: ldw r0, sp[100]
46 ; CHECK-NEXT: retsp 100
47 %0 = alloca [100 x i32]
48 %1 = call ptr @llvm.returnaddress(i32 0)
52 ; test FRAME_TO_ARGS_OFFSET lowering
53 define ptr @FTAO0() nounwind {
57 ; CHECK-NEXT: ldaw r1, sp[0]
58 ; CHECK-NEXT: add r0, r1, r0
60 %0 = call ptr @llvm.eh.dwarf.cfa(i32 0)
64 define ptr @FTAO1() nounwind {
68 ; CHECK-NEXT: ldc r0, 400
69 ; CHECK-NEXT: ldaw r1, sp[0]
70 ; CHECK-NEXT: add r0, r1, r0
71 ; CHECK-NEXT: retsp 100
72 %0 = alloca [100 x i32]
73 %1 = call ptr @llvm.eh.dwarf.cfa(i32 0)
77 define ptr @EH0(i32 %offset, ptr %handler) {
81 ; CHECK: .cfi_def_cfa_offset 8
82 ; CHECK: .cfi_offset 15, 0
83 ; CHECK: .cfi_offset 1, -8
84 ; CHECK: .cfi_offset 0, -4
86 ; CHECK-NEXT: ldaw r3, sp[0]
87 ; CHECK-NEXT: add r2, r3, r2
88 ; CHECK-NEXT: add r2, r2, r0
89 ; CHECK-NEXT: mov r3, r1
90 ; CHECK-NEXT: ldw r1, sp[0]
91 ; CHECK-NEXT: ldw r0, sp[1]
92 ; CHECK-NEXT: set sp, r2
94 call void @llvm.eh.return.i32(i32 %offset, ptr %handler)
98 declare void @foo(...)
99 define ptr @EH1(i32 %offset, ptr %handler) {
103 ; CHECK: .cfi_def_cfa_offset 20
104 ; CHECK: .cfi_offset 15, 0
105 ; CHECK: .cfi_offset 1, -16
106 ; CHECK: .cfi_offset 0, -12
107 ; CHECK: stw r4, sp[4]
108 ; CHECK: .cfi_offset 4, -4
109 ; CHECK: stw r5, sp[3]
110 ; CHECK: .cfi_offset 5, -8
112 ; CHECK-NEXT: mov r5, r0
114 ; CHECK-NEXT: ldc r0, 20
115 ; CHECK-NEXT: ldaw r1, sp[0]
116 ; CHECK-NEXT: add r0, r1, r0
117 ; CHECK-NEXT: add r2, r0, r5
118 ; CHECK-NEXT: mov r3, r4
119 ; CHECK-NEXT: ldw r5, sp[3]
120 ; CHECK-NEXT: ldw r4, sp[4]
121 ; CHECK-NEXT: ldw r1, sp[1]
122 ; CHECK-NEXT: ldw r0, sp[2]
123 ; CHECK-NEXT: set sp, r2
125 call void (...) @foo()
126 call void @llvm.eh.return.i32(i32 %offset, ptr %handler)
130 @offset = external constant i32
131 @handler = external constant i8
132 define ptr @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) {
137 ; CHECK-NEXT: ldw r0, dp[offset]
138 ; CHECK-NEXT: ldc r1, 12
139 ; CHECK-NEXT: ldaw r2, sp[0]
140 ; CHECK-NEXT: add r1, r2, r1
141 ; CHECK-NEXT: add r2, r1, r0
142 ; CHECK-NEXT: ldaw r3, dp[handler]
143 ; CHECK-NEXT: ldw r1, sp[1]
144 ; CHECK-NEXT: ldw r0, sp[2]
145 ; CHECK-NEXT: set sp, r2
147 call void (...) @foo()
148 %0 = load i32, ptr @offset
149 call void @llvm.eh.return.i32(i32 %0, ptr @handler)
154 ; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6
155 ; But we dont actually spill or restore R0:1
156 ; CHECKFP-LABEL: Unwind0:
158 ; CHECKFP: stw r10, sp[1]
159 ; CHECKFP: ldaw r10, sp[0]
160 ; CHECKFP: stw r4, r10[9]
161 ; CHECKFP: stw r5, r10[8]
162 ; CHECKFP: stw r6, r10[7]
163 ; CHECKFP: stw r7, r10[6]
164 ; CHECKFP: stw r8, r10[5]
165 ; CHECKFP: stw r9, r10[4]
166 ; CHECKFP: ldw r9, r10[4]
167 ; CHECKFP: ldw r8, r10[5]
168 ; CHECKFP: ldw r7, r10[6]
169 ; CHECKFP: ldw r6, r10[7]
170 ; CHECKFP: ldw r5, r10[8]
171 ; CHECKFP: ldw r4, r10[9]
172 ; CHECKFP: set sp, r10
173 ; CHECKFP: ldw r10, sp[1]
176 ; !FP: spill R0:1+R4:10 = entsp 2+7
177 ; But we dont actually spill or restore R0:1
178 ; CHECK-LABEL: Unwind0:
180 ; CHECK: stw r4, sp[8]
181 ; CHECK: stw r5, sp[7]
182 ; CHECK: stw r6, sp[6]
183 ; CHECK: stw r7, sp[5]
184 ; CHECK: stw r8, sp[4]
185 ; CHECK: stw r9, sp[3]
186 ; CHECK: stw r10, sp[2]
187 ; CHECK: ldw r10, sp[2]
188 ; CHECK: ldw r9, sp[3]
189 ; CHECK: ldw r8, sp[4]
190 ; CHECK: ldw r7, sp[5]
191 ; CHECK: ldw r6, sp[6]
192 ; CHECK: ldw r5, sp[7]
193 ; CHECK: ldw r4, sp[8]
195 define void @Unwind0() {
196 call void @llvm.eh.unwind.init()
201 ; FP: spill FP+SR+R0:1+R4:9+LR = entsp 2+2+6 + extsp 1
202 ; But we dont actually spill or restore R0:1
203 ; CHECKFP-LABEL: Unwind1:
205 ; CHECKFP: stw r10, sp[1]
206 ; CHECKFP: ldaw r10, sp[0]
207 ; CHECKFP: stw r4, r10[9]
208 ; CHECKFP: stw r5, r10[8]
209 ; CHECKFP: stw r6, r10[7]
210 ; CHECKFP: stw r7, r10[6]
211 ; CHECKFP: stw r8, r10[5]
212 ; CHECKFP: stw r9, r10[4]
215 ; CHECKFP: ldaw sp, sp[1]
216 ; CHECKFP: ldw r9, r10[4]
217 ; CHECKFP: ldw r8, r10[5]
218 ; CHECKFP: ldw r7, r10[6]
219 ; CHECKFP: ldw r6, r10[7]
220 ; CHECKFP: ldw r5, r10[8]
221 ; CHECKFP: ldw r4, r10[9]
222 ; CHECKFP: set sp, r10
223 ; CHECKFP: ldw r10, sp[1]
226 ; !FP: spill R0:1+R4:10+LR = entsp 2+7+1
227 ; But we dont actually spill or restore R0:1
228 ; CHECK-LABEL: Unwind1:
230 ; CHECK: stw r4, sp[9]
231 ; CHECK: stw r5, sp[8]
232 ; CHECK: stw r6, sp[7]
233 ; CHECK: stw r7, sp[6]
234 ; CHECK: stw r8, sp[5]
235 ; CHECK: stw r9, sp[4]
236 ; CHECK: stw r10, sp[3]
238 ; CHECK: ldw r10, sp[3]
239 ; CHECK: ldw r9, sp[4]
240 ; CHECK: ldw r8, sp[5]
241 ; CHECK: ldw r7, sp[6]
242 ; CHECK: ldw r6, sp[7]
243 ; CHECK: ldw r5, sp[8]
244 ; CHECK: ldw r4, sp[9]
246 define void @Unwind1() {
247 call void (...) @foo()
248 call void @llvm.eh.unwind.init()
252 ; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6
254 ; We only restore R0:1 during eh.return
255 ; CHECKFP-LABEL: UnwindEH:
257 ; CHECKFP: .cfi_def_cfa_offset 40
258 ; CHECKFP: .cfi_offset 15, 0
259 ; CHECKFP: stw r10, sp[1]
260 ; CHECKFP: .cfi_offset 10, -36
261 ; CHECKFP: ldaw r10, sp[0]
262 ; CHECKFP: .cfi_def_cfa_register 10
263 ; CHECKFP: .cfi_offset 1, -32
264 ; CHECKFP: .cfi_offset 0, -28
265 ; CHECKFP: stw r4, r10[9]
266 ; CHECKFP: .cfi_offset 4, -4
267 ; CHECKFP: stw r5, r10[8]
268 ; CHECKFP: .cfi_offset 5, -8
269 ; CHECKFP: stw r6, r10[7]
270 ; CHECKFP: .cfi_offset 6, -12
271 ; CHECKFP: stw r7, r10[6]
272 ; CHECKFP: .cfi_offset 7, -16
273 ; CHECKFP: stw r8, r10[5]
274 ; CHECKFP: .cfi_offset 8, -20
275 ; CHECKFP: stw r9, r10[4]
276 ; CHECKFP: .cfi_offset 9, -24
277 ; CHECKFP: bt r0, .LBB{{[0-9_]+}}
278 ; CHECKFP: ldw r9, r10[4]
279 ; CHECKFP-NEXT: ldw r8, r10[5]
280 ; CHECKFP-NEXT: ldw r7, r10[6]
281 ; CHECKFP-NEXT: ldw r6, r10[7]
282 ; CHECKFP-NEXT: ldw r5, r10[8]
283 ; CHECKFP-NEXT: ldw r4, r10[9]
284 ; CHECKFP-NEXT: set sp, r10
285 ; CHECKFP-NEXT: ldw r10, sp[1]
286 ; CHECKFP-NEXT: retsp 10
287 ; CHECKFP: .LBB{{[0-9_]+}}
288 ; CHECKFP-NEXT: ldc r2, 40
289 ; CHECKFP-NEXT: add r2, r10, r2
290 ; CHECKFP-NEXT: add r2, r2, r0
291 ; CHECKFP-NEXT: mov r3, r1
292 ; CHECKFP-NEXT: ldw r9, r10[4]
293 ; CHECKFP-NEXT: ldw r8, r10[5]
294 ; CHECKFP-NEXT: ldw r7, r10[6]
295 ; CHECKFP-NEXT: ldw r6, r10[7]
296 ; CHECKFP-NEXT: ldw r5, r10[8]
297 ; CHECKFP-NEXT: ldw r4, r10[9]
298 ; CHECKFP-NEXT: ldw r1, sp[2]
299 ; CHECKFP-NEXT: ldw r0, sp[3]
300 ; CHECKFP-NEXT: set sp, r2
301 ; CHECKFP-NEXT: bau r3
303 ; !FP: spill R0:1+R4:10 = entsp 2+7
305 ; We only restore R0:1 during eh.return
306 ; CHECK-LABEL: UnwindEH:
308 ; CHECK: .cfi_def_cfa_offset 36
309 ; CHECK: .cfi_offset 15, 0
310 ; CHECK: .cfi_offset 1, -36
311 ; CHECK: .cfi_offset 0, -32
312 ; CHECK: stw r4, sp[8]
313 ; CHECK: .cfi_offset 4, -4
314 ; CHECK: stw r5, sp[7]
315 ; CHECK: .cfi_offset 5, -8
316 ; CHECK: stw r6, sp[6]
317 ; CHECK: .cfi_offset 6, -12
318 ; CHECK: stw r7, sp[5]
319 ; CHECK: .cfi_offset 7, -16
320 ; CHECK: stw r8, sp[4]
321 ; CHECK: .cfi_offset 8, -20
322 ; CHECK: stw r9, sp[3]
323 ; CHECK: .cfi_offset 9, -24
324 ; CHECK: stw r10, sp[2]
325 ; CHECK: .cfi_offset 10, -28
326 ; CHECK: bt r0, .LBB{{[0-9_]+}}
327 ; CHECK: ldw r10, sp[2]
328 ; CHECK-NEXT: ldw r9, sp[3]
329 ; CHECK-NEXT: ldw r8, sp[4]
330 ; CHECK-NEXT: ldw r7, sp[5]
331 ; CHECK-NEXT: ldw r6, sp[6]
332 ; CHECK-NEXT: ldw r5, sp[7]
333 ; CHECK-NEXT: ldw r4, sp[8]
334 ; CHECK-NEXT: retsp 9
335 ; CHECK: .LBB{{[0-9_]+}}
336 ; CHECK-NEXT: ldc r2, 36
337 ; CHECK-NEXT: ldaw r3, sp[0]
338 ; CHECK-NEXT: add r2, r3, r2
339 ; CHECK-NEXT: add r2, r2, r0
340 ; CHECK-NEXT: mov r3, r1
341 ; CHECK-NEXT: ldw r10, sp[2]
342 ; CHECK-NEXT: ldw r9, sp[3]
343 ; CHECK-NEXT: ldw r8, sp[4]
344 ; CHECK-NEXT: ldw r7, sp[5]
345 ; CHECK-NEXT: ldw r6, sp[6]
346 ; CHECK-NEXT: ldw r5, sp[7]
347 ; CHECK-NEXT: ldw r4, sp[8]
348 ; CHECK-NEXT: ldw r1, sp[0]
349 ; CHECK-NEXT: ldw r0, sp[1]
350 ; CHECK-NEXT: set sp, r2
352 define void @UnwindEH(i32 %offset, ptr %handler) {
353 call void @llvm.eh.unwind.init()
354 %cmp = icmp eq i32 %offset, 0
355 br i1 %cmp, label %normal, label %eh
357 call void @llvm.eh.return.i32(i32 %offset, ptr %handler)