• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -march=xcore | FileCheck %s
2; RUN: llc < %s -march=xcore -frame-pointer=all | FileCheck %s -check-prefix=CHECKFP
3
4declare i8* @llvm.frameaddress(i32) nounwind readnone
5declare i8* @llvm.returnaddress(i32) nounwind
6declare i8* @llvm.eh.dwarf.cfa(i32) nounwind
7declare void @llvm.eh.return.i32(i32, i8*) nounwind
8declare void @llvm.eh.unwind.init() nounwind
9
10define i8* @FA0() nounwind {
11entry:
12; CHECK-LABEL: FA0
13; CHECK: ldaw r0, sp[0]
14; CHECK-NEXT: retsp 0
15  %0 = call i8* @llvm.frameaddress(i32 0)
16  ret i8* %0
17}
18
19define i8* @FA1() nounwind {
20entry:
21; CHECK-LABEL: FA1
22; CHECK: entsp 100
23; CHECK-NEXT: ldaw r0, sp[0]
24; CHECK-NEXT: retsp 100
25  %0 = alloca [100 x i32]
26  %1 = call i8* @llvm.frameaddress(i32 0)
27  ret i8* %1
28}
29
30define i8* @RA0() nounwind {
31entry:
32; CHECK-LABEL: RA0
33; CHECK: stw lr, sp[0]
34; CHECK-NEXT: ldw r0, sp[0]
35; CHECK-NEXT: ldw lr, sp[0]
36; CHECK-NEXT: retsp 0
37  %0 = call i8* @llvm.returnaddress(i32 0)
38  ret i8* %0
39}
40
41define i8* @RA1() nounwind {
42entry:
43; CHECK-LABEL: RA1
44; CHECK: entsp 100
45; CHECK-NEXT: ldw r0, sp[100]
46; CHECK-NEXT: retsp 100
47  %0 = alloca [100 x i32]
48  %1 = call i8* @llvm.returnaddress(i32 0)
49  ret i8* %1
50}
51
52; test FRAME_TO_ARGS_OFFSET lowering
53define i8* @FTAO0() nounwind {
54entry:
55; CHECK-LABEL: FTAO0
56; CHECK: ldc r0, 0
57; CHECK-NEXT: ldaw r1, sp[0]
58; CHECK-NEXT: add r0, r1, r0
59; CHECK-NEXT: retsp 0
60  %0 = call i8* @llvm.eh.dwarf.cfa(i32 0)
61  ret i8* %0
62}
63
64define i8* @FTAO1() nounwind {
65entry:
66; CHECK-LABEL: FTAO1
67; CHECK: entsp 100
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 i8* @llvm.eh.dwarf.cfa(i32 0)
74  ret i8* %1
75}
76
77define i8* @EH0(i32 %offset, i8* %handler) {
78entry:
79; CHECK-LABEL: EH0
80; CHECK: entsp 2
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
85; CHECK: ldc r2, 8
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
93; CHECK-NEXT: bau r3
94  call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
95  unreachable
96}
97
98declare void @foo(...)
99define i8* @EH1(i32 %offset, i8* %handler) {
100entry:
101; CHECK-LABEL: EH1
102; CHECK: entsp 5
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
111; CHECK: mov r4, r1
112; CHECK-NEXT: mov r5, r0
113; CHECK-NEXT: bl foo
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
124; CHECK-NEXT: bau r3
125  call void (...) @foo()
126  call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
127  unreachable
128}
129
130@offset = external constant i32
131@handler = external constant i8
132define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) {
133entry:
134; CHECK-LABEL: EH2
135; CHECK: entsp 3
136; CHECK: bl foo
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
146; CHECK-NEXT: bau r3
147  call void (...) @foo()
148  %0 = load i32, i32* @offset
149  call void @llvm.eh.return.i32(i32 %0, i8* @handler)
150  unreachable
151}
152
153
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:
157; CHECKFP: entsp 10
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]
174; CHECKFP: retsp 10
175;
176; !FP: spill R0:1+R4:10 = entsp 2+7
177; But we dont actually spill or restore R0:1
178; CHECK-LABEL: Unwind0:
179; CHECK: entsp 9
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]
194; CHECK: retsp 9
195define void @Unwind0() {
196  call void @llvm.eh.unwind.init()
197  ret void
198}
199
200
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:
204; CHECKFP: entsp 10
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]
213; CHECKFP: extsp 1
214; CHECKFP: bl foo
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]
224; CHECKFP: retsp 10
225;
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:
229; CHECK: entsp 10
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]
237; CHECK: bl foo
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]
245; CHECK: retsp 10
246define void @Unwind1() {
247  call void (...) @foo()
248  call void @llvm.eh.unwind.init()
249  ret void
250}
251
252; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6
253; We dont spill R0:1
254; We only restore R0:1 during eh.return
255; CHECKFP-LABEL: UnwindEH:
256; CHECKFP: entsp 10
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
302;
303; !FP: spill R0:1+R4:10 = entsp 2+7
304; We dont spill R0:1
305; We only restore R0:1 during eh.return
306; CHECK-LABEL: UnwindEH:
307; CHECK: entsp 9
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
351; CHECK-NEXT: bau r3
352define void @UnwindEH(i32 %offset, i8* %handler) {
353  call void @llvm.eh.unwind.init()
354  %cmp = icmp eq i32 %offset, 0
355  br i1 %cmp, label %normal, label %eh
356eh:
357  call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
358  unreachable
359normal:
360  ret void
361}
362