xref: /llvm-project/llvm/test/CodeGen/ARM/swifterror.ll (revision 4a2bd78f5b0d0661c23dff9c4b93a393a49dbf9a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s
3; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s
4; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-linux-androideabi | FileCheck --check-prefix=CHECK-ANDROID %s
5
6declare ptr @malloc(i64)
7declare void @free(ptr)
8%swift_error = type { i64, i8 }
9%struct.S = type { i32, i32, i32, i32, i32, i32 }
10
11; This tests the basic usage of a swifterror parameter. "foo" is the function
12; that takes a swifterror parameter and "caller" is the caller of "foo".
13define float @foo(ptr swifterror %error_ptr_ref) {
14; CHECK-APPLE-LABEL: foo:
15; CHECK-APPLE:       @ %bb.0: @ %entry
16; CHECK-APPLE-NEXT:    push {lr}
17; CHECK-APPLE-NEXT:    mov r0, #16
18; CHECK-APPLE-NEXT:    mov r1, #0
19; CHECK-APPLE-NEXT:    bl _malloc
20; CHECK-APPLE-NEXT:    mov r8, r0
21; CHECK-APPLE-NEXT:    mov r0, #1
22; CHECK-APPLE-NEXT:    strb r0, [r8, #8]
23; CHECK-APPLE-NEXT:    mov r0, #1065353216
24; CHECK-APPLE-NEXT:    pop {lr}
25; CHECK-APPLE-NEXT:    bx lr
26;
27; CHECK-O0-LABEL: foo:
28; CHECK-O0:       @ %bb.0: @ %entry
29; CHECK-O0-NEXT:    push {r7, lr}
30; CHECK-O0-NEXT:    mov r7, sp
31; CHECK-O0-NEXT:    mov r0, #16
32; CHECK-O0-NEXT:    mov r1, #0
33; CHECK-O0-NEXT:    bl _malloc
34; CHECK-O0-NEXT:    mov r1, r0
35; CHECK-O0-NEXT:    mov r8, r1
36; CHECK-O0-NEXT:    mov r0, #1
37; CHECK-O0-NEXT:    strb r0, [r1, #8]
38; CHECK-O0-NEXT:    mov r0, #1065353216
39; CHECK-O0-NEXT:    pop {r7, pc}
40;
41; CHECK-ANDROID-LABEL: foo:
42; CHECK-ANDROID:       @ %bb.0: @ %entry
43; CHECK-ANDROID-NEXT:    .save {r11, lr}
44; CHECK-ANDROID-NEXT:    push {r11, lr}
45; CHECK-ANDROID-NEXT:    mov r0, #16
46; CHECK-ANDROID-NEXT:    mov r1, #0
47; CHECK-ANDROID-NEXT:    bl malloc
48; CHECK-ANDROID-NEXT:    mov r8, r0
49; CHECK-ANDROID-NEXT:    mov r0, #1
50; CHECK-ANDROID-NEXT:    strb r0, [r8, #8]
51; CHECK-ANDROID-NEXT:    mov r0, #1065353216
52; CHECK-ANDROID-NEXT:    pop {r11, pc}
53
54entry:
55  %call = call ptr @malloc(i64 16)
56  store ptr %call, ptr %error_ptr_ref
57  %tmp = getelementptr inbounds i8, ptr %call, i64 8
58  store i8 1, ptr %tmp
59  ret float 1.0
60}
61
62; "caller" calls "foo" that takes a swifterror parameter.
63define float @caller(ptr %error_ref) {
64; CHECK-APPLE-LABEL: caller:
65; CHECK-APPLE:       @ %bb.0: @ %entry
66; CHECK-APPLE-NEXT:    push {r4, r8, lr}
67; CHECK-APPLE-NEXT:    sub sp, sp, #4
68; CHECK-APPLE-NEXT:    mov r8, #0
69; CHECK-APPLE-NEXT:    mov r4, r0
70; CHECK-APPLE-NEXT:    bl _foo
71; CHECK-APPLE-NEXT:    mov r0, r8
72; CHECK-APPLE-NEXT:    cmp r8, #0
73; CHECK-APPLE-NEXT:    ldrbeq r1, [r0, #8]
74; CHECK-APPLE-NEXT:    strbeq r1, [r4]
75; CHECK-APPLE-NEXT:    bl _free
76; CHECK-APPLE-NEXT:    mov r0, #1065353216
77; CHECK-APPLE-NEXT:    add sp, sp, #4
78; CHECK-APPLE-NEXT:    pop {r4, r8, pc}
79;
80; CHECK-O0-LABEL: caller:
81; CHECK-O0:       @ %bb.0: @ %entry
82; CHECK-O0-NEXT:    push	{r7, r8, lr}
83; CHECK-O0-NEXT:    add	r7, sp, #4
84; CHECK-O0-NEXT:    sub	sp, sp, #12
85; CHECK-O0-NEXT:    @ implicit-def: $r1
86; CHECK-O0-NEXT:    str	r0, [sp]                        @ 4-byte Spill
87; CHECK-O0-NEXT:    mov	r8, #0
88; CHECK-O0-NEXT:    bl	_foo
89; CHECK-O0-NEXT:    str	r8, [sp, #4]                    @ 4-byte Spill
90; CHECK-O0-NEXT:    movw	r0, #0
91; CHECK-O0-NEXT:    cmp	r8, r0
92; CHECK-O0-NEXT:    bne	LBB1_2
93; CHECK-O0-NEXT:  @ %bb.1: @ %cont
94; CHECK-O0-NEXT:    ldr r1, [sp] @ 4-byte Reload
95; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
96; CHECK-O0-NEXT:    ldrb r0, [r0, #8]
97; CHECK-O0-NEXT:    strb r0, [r1]
98; CHECK-O0-NEXT:  LBB1_2: @ %handler
99; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
100; CHECK-O0-NEXT:    bl _free
101; CHECK-O0-NEXT:    mov r0, #1065353216
102; CHECK-O0-NEXT:    sub sp, r7, #4
103; CHECK-O0-NEXT:    pop	{r7, r8, pc}
104;
105; CHECK-ANDROID-LABEL: caller:
106; CHECK-ANDROID:       @ %bb.0: @ %entry
107; CHECK-ANDROID-NEXT:    .save {r4, r8, r11, lr}
108; CHECK-ANDROID-NEXT:    push {r4, r8, r11, lr}
109; CHECK-ANDROID-NEXT:    .pad #8
110; CHECK-ANDROID-NEXT:    sub sp, sp, #8
111; CHECK-ANDROID-NEXT:    mov r8, #0
112; CHECK-ANDROID-NEXT:    mov r4, r0
113; CHECK-ANDROID-NEXT:    bl foo
114; CHECK-ANDROID-NEXT:    mov r0, r8
115; CHECK-ANDROID-NEXT:    cmp r8, #0
116; CHECK-ANDROID-NEXT:    ldrbeq r1, [r0, #8]
117; CHECK-ANDROID-NEXT:    strbeq r1, [r4]
118; CHECK-ANDROID-NEXT:    bl free
119; CHECK-ANDROID-NEXT:    mov r0, #1065353216
120; CHECK-ANDROID-NEXT:    add sp, sp, #8
121; CHECK-ANDROID-NEXT:    pop {r4, r8, r11, pc}
122; Access part of the error object and save it to error_ref
123
124; spill r0
125; reload r0
126entry:
127  %error_ptr_ref = alloca swifterror ptr
128  store ptr null, ptr %error_ptr_ref
129  %call = call float @foo(ptr swifterror %error_ptr_ref)
130  %error_from_foo = load ptr, ptr %error_ptr_ref
131  %had_error_from_foo = icmp ne ptr %error_from_foo, null
132  br i1 %had_error_from_foo, label %handler, label %cont
133cont:
134  %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
135  %t = load i8, ptr %v1
136  store i8 %t, ptr %error_ref
137  br label %handler
138handler:
139  call void @free(ptr %error_from_foo)
140  ret float 1.0
141}
142
143; "caller2" is the caller of "foo", it calls "foo" inside a loop.
144define float @caller2(ptr %error_ref) {
145; CHECK-APPLE-LABEL: caller2:
146; CHECK-APPLE:       @ %bb.0: @ %entry
147; CHECK-APPLE-NEXT:    push {r4, r8, lr}
148; CHECK-APPLE-NEXT:    vpush {d8}
149; CHECK-APPLE-NEXT:    sub sp, sp, #4
150; CHECK-APPLE-NEXT:    vmov.f32 s16, #1.000000e+00
151; CHECK-APPLE-NEXT:    mov r4, r0
152; CHECK-APPLE-NEXT:  LBB2_1: @ %bb_loop
153; CHECK-APPLE-NEXT:    @ =>This Inner Loop Header: Depth=1
154; CHECK-APPLE-NEXT:    mov r8, #0
155; CHECK-APPLE-NEXT:    bl _foo
156; CHECK-APPLE-NEXT:    cmp r8, #0
157; CHECK-APPLE-NEXT:    bne LBB2_4
158; CHECK-APPLE-NEXT:  @ %bb.2: @ %cont
159; CHECK-APPLE-NEXT:    @ in Loop: Header=BB2_1 Depth=1
160; CHECK-APPLE-NEXT:    vmov s0, r0
161; CHECK-APPLE-NEXT:    vcmp.f32 s0, s16
162; CHECK-APPLE-NEXT:    vmrs APSR_nzcv, fpscr
163; CHECK-APPLE-NEXT:    ble LBB2_1
164; CHECK-APPLE-NEXT:  @ %bb.3: @ %bb_end
165; CHECK-APPLE-NEXT:    ldrb r0, [r8, #8]
166; CHECK-APPLE-NEXT:    strb r0, [r4]
167; CHECK-APPLE-NEXT:  LBB2_4: @ %handler
168; CHECK-APPLE-NEXT:    mov r0, r8
169; CHECK-APPLE-NEXT:    bl _free
170; CHECK-APPLE-NEXT:    mov r0, #1065353216
171; CHECK-APPLE-NEXT:    add sp, sp, #4
172; CHECK-APPLE-NEXT:    vpop {d8}
173; CHECK-APPLE-NEXT:    pop {r4, r8, pc}
174;
175; CHECK-O0-LABEL: caller2:
176; CHECK-O0:       @ %bb.0: @ %entry
177; CHECK-O0-NEXT:    push	{r7, r8, lr}
178; CHECK-O0-NEXT:    add	r7, sp, #4
179; CHECK-O0-NEXT:    sub	sp, sp, #16
180; CHECK-O0-NEXT:    @ implicit-def: $r1
181; CHECK-O0-NEXT:    str	r0, [sp, #8] @ 4-byte Spill
182; CHECK-O0-NEXT:  LBB2_1: @ %bb_loop
183; CHECK-O0-NEXT:    @ =>This Inner Loop Header: Depth=1
184; CHECK-O0-NEXT:    mov r8, #0
185; CHECK-O0-NEXT:    bl _foo
186; CHECK-O0-NEXT:    vmov s0, r0
187; CHECK-O0-NEXT:    vstr s0, [sp] @ 4-byte Spill
188; CHECK-O0-NEXT:    str r8, [sp, #4] @ 4-byte Spill
189; CHECK-O0-NEXT:    movw r0, #0
190; CHECK-O0-NEXT:    cmp r8, r0
191; CHECK-O0-NEXT:    bne LBB2_4
192; CHECK-O0-NEXT:  @ %bb.2: @ %cont
193; CHECK-O0-NEXT:    @ in Loop: Header=BB2_1 Depth=1
194; CHECK-O0-NEXT:    vldr s0, [sp] @ 4-byte Reload
195; CHECK-O0-NEXT:    vmov.f32 s2, #1.000000e+00
196; CHECK-O0-NEXT:    vcmp.f32 s0, s2
197; CHECK-O0-NEXT:    vmrs APSR_nzcv, fpscr
198; CHECK-O0-NEXT:    ble LBB2_1
199; CHECK-O0-NEXT:  @ %bb.3: @ %bb_end
200; CHECK-O0-NEXT:    ldr r1, [sp, #8] @ 4-byte Reload
201; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
202; CHECK-O0-NEXT:    ldrb r0, [r0, #8]
203; CHECK-O0-NEXT:    strb r0, [r1]
204; CHECK-O0-NEXT:  LBB2_4: @ %handler
205; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
206; CHECK-O0-NEXT:    bl _free
207; CHECK-O0-NEXT:    mov r0, #1065353216
208; CHECK-O0-NEXT:    sub sp, r7, #4
209; CHECK-O0-NEXT:    pop	{r7, r8, pc}
210;
211; CHECK-ANDROID-LABEL: caller2:
212; CHECK-ANDROID:       @ %bb.0: @ %entry
213; CHECK-ANDROID-NEXT:    .save {r4, r8, r11, lr}
214; CHECK-ANDROID-NEXT:    push {r4, r8, r11, lr}
215; CHECK-ANDROID-NEXT:    .vsave {d8}
216; CHECK-ANDROID-NEXT:    vpush {d8}
217; CHECK-ANDROID-NEXT:    .pad #8
218; CHECK-ANDROID-NEXT:    sub sp, sp, #8
219; CHECK-ANDROID-NEXT:    vmov.f32 s16, #1.000000e+00
220; CHECK-ANDROID-NEXT:    mov r4, r0
221; CHECK-ANDROID-NEXT:  .LBB2_1: @ %bb_loop
222; CHECK-ANDROID-NEXT:    @ =>This Inner Loop Header: Depth=1
223; CHECK-ANDROID-NEXT:    mov r8, #0
224; CHECK-ANDROID-NEXT:    bl foo
225; CHECK-ANDROID-NEXT:    cmp r8, #0
226; CHECK-ANDROID-NEXT:    bne .LBB2_4
227; CHECK-ANDROID-NEXT:  @ %bb.2: @ %cont
228; CHECK-ANDROID-NEXT:    @ in Loop: Header=BB2_1 Depth=1
229; CHECK-ANDROID-NEXT:    vmov s0, r0
230; CHECK-ANDROID-NEXT:    vcmp.f32 s0, s16
231; CHECK-ANDROID-NEXT:    vmrs APSR_nzcv, fpscr
232; CHECK-ANDROID-NEXT:    ble .LBB2_1
233; CHECK-ANDROID-NEXT:  @ %bb.3: @ %bb_end
234; CHECK-ANDROID-NEXT:    ldrb r0, [r8, #8]
235; CHECK-ANDROID-NEXT:    strb r0, [r4]
236; CHECK-ANDROID-NEXT:  .LBB2_4: @ %handler
237; CHECK-ANDROID-NEXT:    mov r0, r8
238; CHECK-ANDROID-NEXT:    bl free
239; CHECK-ANDROID-NEXT:    mov r0, #1065353216
240; CHECK-ANDROID-NEXT:    add sp, sp, #8
241; CHECK-ANDROID-NEXT:    vpop {d8}
242; CHECK-ANDROID-NEXT:    pop {r4, r8, r11, pc}
243; Access part of the error object and save it to error_ref
244
245; spill r0
246; reload r0
247entry:
248  %error_ptr_ref = alloca swifterror ptr
249  br label %bb_loop
250bb_loop:
251  store ptr null, ptr %error_ptr_ref
252  %call = call float @foo(ptr swifterror %error_ptr_ref)
253  %error_from_foo = load ptr, ptr %error_ptr_ref
254  %had_error_from_foo = icmp ne ptr %error_from_foo, null
255  br i1 %had_error_from_foo, label %handler, label %cont
256cont:
257  %cmp = fcmp ogt float %call, 1.000000e+00
258  br i1 %cmp, label %bb_end, label %bb_loop
259bb_end:
260  %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
261  %t = load i8, ptr %v1
262  store i8 %t, ptr %error_ref
263  br label %handler
264handler:
265  call void @free(ptr %error_from_foo)
266  ret float 1.0
267}
268
269; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
270; under a certain condition.
271define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) {
272; CHECK-APPLE-LABEL: foo_if:
273; CHECK-APPLE:       @ %bb.0: @ %entry
274; CHECK-APPLE-NEXT:    cmp r0, #0
275; CHECK-APPLE-NEXT:    vldreq s0, LCPI3_0
276; CHECK-APPLE-NEXT:    vmoveq r0, s0
277; CHECK-APPLE-NEXT:    bxeq lr
278; CHECK-APPLE-NEXT:  LBB3_1: @ %gen_error
279; CHECK-APPLE-NEXT:    push {lr}
280; CHECK-APPLE-NEXT:    mov r0, #16
281; CHECK-APPLE-NEXT:    mov r1, #0
282; CHECK-APPLE-NEXT:    bl _malloc
283; CHECK-APPLE-NEXT:    mov r8, r0
284; CHECK-APPLE-NEXT:    mov r0, #1
285; CHECK-APPLE-NEXT:    vmov.f32 s0, #1.000000e+00
286; CHECK-APPLE-NEXT:    strb r0, [r8, #8]
287; CHECK-APPLE-NEXT:    pop {lr}
288; CHECK-APPLE-NEXT:    vmov r0, s0
289; CHECK-APPLE-NEXT:    bx lr
290; CHECK-APPLE-NEXT:    .p2align 2
291; CHECK-APPLE-NEXT:  @ %bb.2:
292; CHECK-APPLE-NEXT:    .data_region
293; CHECK-APPLE-NEXT:  LCPI3_0:
294; CHECK-APPLE-NEXT:    .long 0x00000000 @ float 0
295; CHECK-APPLE-NEXT:    .end_data_region
296;
297; CHECK-O0-LABEL: foo_if:
298; CHECK-O0:       @ %bb.0: @ %entry
299; CHECK-O0-NEXT:    push {r7, lr}
300; CHECK-O0-NEXT:    mov r7, sp
301; CHECK-O0-NEXT:    sub sp, sp, #4
302; CHECK-O0-NEXT:    str r8, [sp] @ 4-byte Spill
303; CHECK-O0-NEXT:    cmp r0, #0
304; CHECK-O0-NEXT:    beq LBB3_2
305; CHECK-O0-NEXT:  @ %bb.1: @ %gen_error
306; CHECK-O0-NEXT:    mov r0, #16
307; CHECK-O0-NEXT:    mov r1, #0
308; CHECK-O0-NEXT:    bl _malloc
309; CHECK-O0-NEXT:    mov r1, r0
310; CHECK-O0-NEXT:    mov r8, r1
311; CHECK-O0-NEXT:    mov r0, #1
312; CHECK-O0-NEXT:    strb r0, [r1, #8]
313; CHECK-O0-NEXT:    mov r0, #1065353216
314; CHECK-O0-NEXT:    mov sp, r7
315; CHECK-O0-NEXT:    pop {r7, pc}
316; CHECK-O0-NEXT:  LBB3_2: @ %normal
317; CHECK-O0-NEXT:    ldr r8, [sp] @ 4-byte Reload
318; CHECK-O0-NEXT:    mov r0, #0
319; CHECK-O0-NEXT:    mov sp, r7
320; CHECK-O0-NEXT:    pop {r7, pc}
321;
322; CHECK-ANDROID-LABEL: foo_if:
323; CHECK-ANDROID:       @ %bb.0: @ %entry
324; CHECK-ANDROID-NEXT:    cmp r0, #0
325; CHECK-ANDROID-NEXT:    vldreq s0, .LCPI3_0
326; CHECK-ANDROID-NEXT:    vmoveq r0, s0
327; CHECK-ANDROID-NEXT:    bxeq lr
328; CHECK-ANDROID-NEXT:  .LBB3_1: @ %gen_error
329; CHECK-ANDROID-NEXT:    .save {r11, lr}
330; CHECK-ANDROID-NEXT:    push {r11, lr}
331; CHECK-ANDROID-NEXT:    mov r0, #16
332; CHECK-ANDROID-NEXT:    mov r1, #0
333; CHECK-ANDROID-NEXT:    bl malloc
334; CHECK-ANDROID-NEXT:    mov r8, r0
335; CHECK-ANDROID-NEXT:    mov r0, #1
336; CHECK-ANDROID-NEXT:    vmov.f32 s0, #1.000000e+00
337; CHECK-ANDROID-NEXT:    strb r0, [r8, #8]
338; CHECK-ANDROID-NEXT:    pop {r11, lr}
339; CHECK-ANDROID-NEXT:    vmov r0, s0
340; CHECK-ANDROID-NEXT:    bx lr
341; CHECK-ANDROID-NEXT:    .p2align 2
342; CHECK-ANDROID-NEXT:  @ %bb.2:
343; CHECK-ANDROID-NEXT:  .LCPI3_0:
344; CHECK-ANDROID-NEXT:    .long 0x00000000 @ float 0
345
346; spill to stack
347; reload from stack
348entry:
349  %cond = icmp ne i32 %cc, 0
350  br i1 %cond, label %gen_error, label %normal
351
352gen_error:
353  %call = call ptr @malloc(i64 16)
354  store ptr %call, ptr %error_ptr_ref
355  %tmp = getelementptr inbounds i8, ptr %call, i64 8
356  store i8 1, ptr %tmp
357  ret float 1.0
358
359normal:
360  ret float 0.0
361}
362
363; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
364; under a certain condition inside a loop.
365define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) {
366; CHECK-APPLE-LABEL: foo_loop:
367; CHECK-APPLE:       @ %bb.0: @ %entry
368; CHECK-APPLE-NEXT:    push {r4, r5, lr}
369; CHECK-APPLE-NEXT:    vpush {d8, d9}
370; CHECK-APPLE-NEXT:    vmov.f32 s18, #1.000000e+00
371; CHECK-APPLE-NEXT:    mov r4, r0
372; CHECK-APPLE-NEXT:    vmov s16, r1
373; CHECK-APPLE-NEXT:    mov r5, #1
374; CHECK-APPLE-NEXT:    b LBB4_2
375; CHECK-APPLE-NEXT:  LBB4_1: @ %bb_cont
376; CHECK-APPLE-NEXT:    @ in Loop: Header=BB4_2 Depth=1
377; CHECK-APPLE-NEXT:    vcmp.f32 s16, s18
378; CHECK-APPLE-NEXT:    vmrs APSR_nzcv, fpscr
379; CHECK-APPLE-NEXT:    bgt LBB4_4
380; CHECK-APPLE-NEXT:  LBB4_2: @ %bb_loop
381; CHECK-APPLE-NEXT:    @ =>This Inner Loop Header: Depth=1
382; CHECK-APPLE-NEXT:    cmp r4, #0
383; CHECK-APPLE-NEXT:    beq LBB4_1
384; CHECK-APPLE-NEXT:  @ %bb.3: @ %gen_error
385; CHECK-APPLE-NEXT:    @ in Loop: Header=BB4_2 Depth=1
386; CHECK-APPLE-NEXT:    mov r0, #16
387; CHECK-APPLE-NEXT:    mov r1, #0
388; CHECK-APPLE-NEXT:    bl _malloc
389; CHECK-APPLE-NEXT:    mov r8, r0
390; CHECK-APPLE-NEXT:    strb r5, [r0, #8]
391; CHECK-APPLE-NEXT:    b LBB4_1
392; CHECK-APPLE-NEXT:  LBB4_4: @ %bb_end
393; CHECK-APPLE-NEXT:    mov r0, #0
394; CHECK-APPLE-NEXT:    vpop {d8, d9}
395; CHECK-APPLE-NEXT:    pop {r4, r5, pc}
396;
397; CHECK-O0-LABEL: foo_loop:
398; CHECK-O0:       @ %bb.0: @ %entry
399; CHECK-O0-NEXT:    push {r7, lr}
400; CHECK-O0-NEXT:    mov r7, sp
401; CHECK-O0-NEXT:    sub sp, sp, #20
402; CHECK-O0-NEXT:    str r0, [sp, #8] @ 4-byte Spill
403; CHECK-O0-NEXT:    vmov s0, r1
404; CHECK-O0-NEXT:    vstr s0, [r7, #-8] @ 4-byte Spill
405; CHECK-O0-NEXT:    str r8, [r7, #-4] @ 4-byte Spill
406; CHECK-O0-NEXT:    b LBB4_1
407; CHECK-O0-NEXT:  LBB4_1: @ %bb_loop
408; CHECK-O0-NEXT:    @ =>This Inner Loop Header: Depth=1
409; CHECK-O0-NEXT:    ldr r1, [sp, #8] @ 4-byte Reload
410; CHECK-O0-NEXT:    ldr r0, [r7, #-4] @ 4-byte Reload
411; CHECK-O0-NEXT:    cmp r1, #0
412; CHECK-O0-NEXT:    str r0, [sp, #4] @ 4-byte Spill
413; CHECK-O0-NEXT:    beq LBB4_3
414; CHECK-O0-NEXT:  @ %bb.2: @ %gen_error
415; CHECK-O0-NEXT:    @ in Loop: Header=BB4_1 Depth=1
416; CHECK-O0-NEXT:    mov r0, #16
417; CHECK-O0-NEXT:    mov r1, #0
418; CHECK-O0-NEXT:    bl _malloc
419; CHECK-O0-NEXT:    mov r2, r0
420; CHECK-O0-NEXT:    movw r1, #1
421; CHECK-O0-NEXT:    strb r1, [r2, #8]
422; CHECK-O0-NEXT:    str r0, [sp, #4] @ 4-byte Spill
423; CHECK-O0-NEXT:  LBB4_3: @ %bb_cont
424; CHECK-O0-NEXT:    @ in Loop: Header=BB4_1 Depth=1
425; CHECK-O0-NEXT:    vldr s0, [r7, #-8] @ 4-byte Reload
426; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
427; CHECK-O0-NEXT:    str r0, [sp] @ 4-byte Spill
428; CHECK-O0-NEXT:    vmov.f32 s2, #1.000000e+00
429; CHECK-O0-NEXT:    vcmp.f32 s0, s2
430; CHECK-O0-NEXT:    vmrs APSR_nzcv, fpscr
431; CHECK-O0-NEXT:    str r0, [r7, #-4] @ 4-byte Spill
432; CHECK-O0-NEXT:    ble LBB4_1
433; CHECK-O0-NEXT:  @ %bb.4: @ %bb_end
434; CHECK-O0-NEXT:    ldr r8, [sp] @ 4-byte Reload
435; CHECK-O0-NEXT:    mov r0, #0
436; CHECK-O0-NEXT:    mov sp, r7
437; CHECK-O0-NEXT:    pop {r7, pc}
438;
439; CHECK-ANDROID-LABEL: foo_loop:
440; CHECK-ANDROID:       @ %bb.0: @ %entry
441; CHECK-ANDROID-NEXT:    .save {r4, r5, r11, lr}
442; CHECK-ANDROID-NEXT:    push {r4, r5, r11, lr}
443; CHECK-ANDROID-NEXT:    .vsave {d8, d9}
444; CHECK-ANDROID-NEXT:    vpush {d8, d9}
445; CHECK-ANDROID-NEXT:    vmov.f32 s18, #1.000000e+00
446; CHECK-ANDROID-NEXT:    mov r4, r0
447; CHECK-ANDROID-NEXT:    vmov s16, r1
448; CHECK-ANDROID-NEXT:    mov r5, #1
449; CHECK-ANDROID-NEXT:    b .LBB4_2
450; CHECK-ANDROID-NEXT:  .LBB4_1: @ %bb_cont
451; CHECK-ANDROID-NEXT:    @ in Loop: Header=BB4_2 Depth=1
452; CHECK-ANDROID-NEXT:    vcmp.f32 s16, s18
453; CHECK-ANDROID-NEXT:    vmrs APSR_nzcv, fpscr
454; CHECK-ANDROID-NEXT:    bgt .LBB4_4
455; CHECK-ANDROID-NEXT:  .LBB4_2: @ %bb_loop
456; CHECK-ANDROID-NEXT:    @ =>This Inner Loop Header: Depth=1
457; CHECK-ANDROID-NEXT:    cmp r4, #0
458; CHECK-ANDROID-NEXT:    beq .LBB4_1
459; CHECK-ANDROID-NEXT:  @ %bb.3: @ %gen_error
460; CHECK-ANDROID-NEXT:    @ in Loop: Header=BB4_2 Depth=1
461; CHECK-ANDROID-NEXT:    mov r0, #16
462; CHECK-ANDROID-NEXT:    mov r1, #0
463; CHECK-ANDROID-NEXT:    bl malloc
464; CHECK-ANDROID-NEXT:    mov r8, r0
465; CHECK-ANDROID-NEXT:    strb r5, [r0, #8]
466; CHECK-ANDROID-NEXT:    b .LBB4_1
467; CHECK-ANDROID-NEXT:  .LBB4_4: @ %bb_end
468; CHECK-ANDROID-NEXT:    mov r0, #0
469; CHECK-ANDROID-NEXT:    vpop {d8, d9}
470; CHECK-ANDROID-NEXT:    pop {r4, r5, r11, pc}
471; swifterror is kept in a register
472
473; spill r0
474; reload from stack
475entry:
476  br label %bb_loop
477
478bb_loop:
479  %cond = icmp ne i32 %cc, 0
480  br i1 %cond, label %gen_error, label %bb_cont
481
482gen_error:
483  %call = call ptr @malloc(i64 16)
484  store ptr %call, ptr %error_ptr_ref
485  %tmp = getelementptr inbounds i8, ptr %call, i64 8
486  store i8 1, ptr %tmp
487  br label %bb_cont
488
489bb_cont:
490  %cmp = fcmp ogt float %cc2, 1.000000e+00
491  br i1 %cmp, label %bb_end, label %bb_loop
492bb_end:
493  ret float 0.0
494}
495
496; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
497; parameter.
498define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) {
499; CHECK-APPLE-LABEL: foo_sret:
500; CHECK-APPLE:       @ %bb.0: @ %entry
501; CHECK-APPLE-NEXT:    push {r4, r5, lr}
502; CHECK-APPLE-NEXT:    mov r4, r1
503; CHECK-APPLE-NEXT:    mov r5, r0
504; CHECK-APPLE-NEXT:    mov r0, #16
505; CHECK-APPLE-NEXT:    mov r1, #0
506; CHECK-APPLE-NEXT:    bl _malloc
507; CHECK-APPLE-NEXT:    mov r1, #1
508; CHECK-APPLE-NEXT:    mov r8, r0
509; CHECK-APPLE-NEXT:    strb r1, [r0, #8]
510; CHECK-APPLE-NEXT:    str r4, [r5, #4]
511; CHECK-APPLE-NEXT:    pop {r4, r5, pc}
512;
513; CHECK-O0-LABEL: foo_sret:
514; CHECK-O0:       @ %bb.0: @ %entry
515; CHECK-O0-NEXT:    push {r7, lr}
516; CHECK-O0-NEXT:    mov r7, sp
517; CHECK-O0-NEXT:    sub sp, sp, #8
518; CHECK-O0-NEXT:    str r1, [sp] @ 4-byte Spill
519; CHECK-O0-NEXT:    str r0, [sp, #4] @ 4-byte Spill
520; CHECK-O0-NEXT:    mov r0, #16
521; CHECK-O0-NEXT:    mov r1, #0
522; CHECK-O0-NEXT:    bl _malloc
523; CHECK-O0-NEXT:    ldr r1, [sp] @ 4-byte Reload
524; CHECK-O0-NEXT:    mov r3, r0
525; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
526; CHECK-O0-NEXT:    mov r8, r3
527; CHECK-O0-NEXT:    mov r2, #1
528; CHECK-O0-NEXT:    strb r2, [r3, #8]
529; CHECK-O0-NEXT:    str r1, [r0, #4]
530; CHECK-O0-NEXT:    mov sp, r7
531; CHECK-O0-NEXT:    pop {r7, pc}
532;
533; CHECK-ANDROID-LABEL: foo_sret:
534; CHECK-ANDROID:       @ %bb.0: @ %entry
535; CHECK-ANDROID-NEXT:    .save {r4, r5, r11, lr}
536; CHECK-ANDROID-NEXT:    push {r4, r5, r11, lr}
537; CHECK-ANDROID-NEXT:    mov r4, r1
538; CHECK-ANDROID-NEXT:    mov r5, r0
539; CHECK-ANDROID-NEXT:    mov r0, #16
540; CHECK-ANDROID-NEXT:    mov r1, #0
541; CHECK-ANDROID-NEXT:    bl malloc
542; CHECK-ANDROID-NEXT:    mov r1, #1
543; CHECK-ANDROID-NEXT:    mov r8, r0
544; CHECK-ANDROID-NEXT:    strb r1, [r0, #8]
545; CHECK-ANDROID-NEXT:    str r4, [r5, #4]
546; CHECK-ANDROID-NEXT:    pop {r4, r5, r11, pc}
547
548; spill to stack: sret and val1
549; reload from stack: sret and val1
550entry:
551  %call = call ptr @malloc(i64 16)
552  store ptr %call, ptr %error_ptr_ref
553  %tmp = getelementptr inbounds i8, ptr %call, i64 8
554  store i8 1, ptr %tmp
555  %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1
556  store i32 %val1, ptr %v2
557  ret void
558}
559
560; "caller3" calls "foo_sret" that takes a swifterror parameter.
561define float @caller3(ptr %error_ref) {
562; CHECK-APPLE-LABEL: caller3:
563; CHECK-APPLE:       @ %bb.0: @ %entry
564; CHECK-APPLE-NEXT:    push {r4, r7, r8, lr}
565; CHECK-APPLE-NEXT:    add r7, sp, #8
566; CHECK-APPLE-NEXT:    sub sp, sp, #32
567; CHECK-APPLE-NEXT:    bfc sp, #0, #3
568; CHECK-APPLE-NEXT:    mov r4, r0
569; CHECK-APPLE-NEXT:    add r0, sp, #8
570; CHECK-APPLE-NEXT:    mov r1, #1
571; CHECK-APPLE-NEXT:    mov r8, #0
572; CHECK-APPLE-NEXT:    bl _foo_sret
573; CHECK-APPLE-NEXT:    mov r0, r8
574; CHECK-APPLE-NEXT:    cmp r8, #0
575; CHECK-APPLE-NEXT:    ldrbeq r1, [r0, #8]
576; CHECK-APPLE-NEXT:    strbeq r1, [r4]
577; CHECK-APPLE-NEXT:    bl _free
578; CHECK-APPLE-NEXT:    mov r0, #1065353216
579; CHECK-APPLE-NEXT:    sub sp, r7, #8
580; CHECK-APPLE-NEXT:    pop {r4, r7, r8, pc}
581;
582; CHECK-O0-LABEL: caller3:
583; CHECK-O0:       @ %bb.0: @ %entry
584; CHECK-O0-NEXT:    push	{r7, r8, lr}
585; CHECK-O0-NEXT:    add	r7, sp, #4
586; CHECK-O0-NEXT:    sub	sp, sp, #44
587; CHECK-O0-NEXT:    bfc	sp, #0, #3
588; CHECK-O0-NEXT:    @ implicit-def: $r1
589; CHECK-O0-NEXT:    str	r0, [sp, #4] @ 4-byte Spill
590; CHECK-O0-NEXT:    mov	r8, #0
591; CHECK-O0-NEXT:    add	r0, sp, #16
592; CHECK-O0-NEXT:    mov	r1, #1
593; CHECK-O0-NEXT:    bl	_foo_sret
594; CHECK-O0-NEXT:    str	r8, [sp, #8] @ 4-byte Spill
595; CHECK-O0-NEXT:    movw	r0, #0
596; CHECK-O0-NEXT:    cmp	r8, r0
597; CHECK-O0-NEXT:    bne	LBB6_2
598; CHECK-O0-NEXT:  @ %bb.1: @ %cont
599; CHECK-O0-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
600; CHECK-O0-NEXT:    ldr r0, [sp, #8] @ 4-byte Reload
601; CHECK-O0-NEXT:    ldrb r0, [r0, #8]
602; CHECK-O0-NEXT:    strb r0, [r1]
603; CHECK-O0-NEXT:  LBB6_2: @ %handler
604; CHECK-O0-NEXT:    ldr r0, [sp, #8] @ 4-byte Reload
605; CHECK-O0-NEXT:    bl _free
606; CHECK-O0-NEXT:    mov r0, #1065353216
607; CHECK-O0-NEXT:    sub sp, r7, #4
608; CHECK-O0-NEXT:    pop	{r7, r8, pc}
609;
610; CHECK-ANDROID-LABEL: caller3:
611; CHECK-ANDROID:       @ %bb.0: @ %entry
612; CHECK-ANDROID-NEXT:    .save {r4, r8, r11, lr}
613; CHECK-ANDROID-NEXT:    push {r4, r8, r11, lr}
614; CHECK-ANDROID-NEXT:    .pad #32
615; CHECK-ANDROID-NEXT:    sub sp, sp, #32
616; CHECK-ANDROID-NEXT:    mov r4, r0
617; CHECK-ANDROID-NEXT:    add r0, sp, #8
618; CHECK-ANDROID-NEXT:    mov r1, #1
619; CHECK-ANDROID-NEXT:    mov r8, #0
620; CHECK-ANDROID-NEXT:    bl foo_sret
621; CHECK-ANDROID-NEXT:    mov r0, r8
622; CHECK-ANDROID-NEXT:    cmp r8, #0
623; CHECK-ANDROID-NEXT:    ldrbeq r1, [r0, #8]
624; CHECK-ANDROID-NEXT:    strbeq r1, [r4]
625; CHECK-ANDROID-NEXT:    bl free
626; CHECK-ANDROID-NEXT:    mov r0, #1065353216
627; CHECK-ANDROID-NEXT:    add sp, sp, #32
628; CHECK-ANDROID-NEXT:    pop {r4, r8, r11, pc}
629; Access part of the error object and save it to error_ref
630
631; Access part of the error object and save it to error_ref
632entry:
633  %s = alloca %struct.S, align 8
634  %error_ptr_ref = alloca swifterror ptr
635  store ptr null, ptr %error_ptr_ref
636  call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref)
637  %error_from_foo = load ptr, ptr %error_ptr_ref
638  %had_error_from_foo = icmp ne ptr %error_from_foo, null
639  br i1 %had_error_from_foo, label %handler, label %cont
640cont:
641  %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
642  %t = load i8, ptr %v1
643  store i8 %t, ptr %error_ref
644  br label %handler
645handler:
646  call void @free(ptr %error_from_foo)
647  ret float 1.0
648}
649
650; "foo_vararg" is a function that takes a swifterror parameter, it also has
651; variable number of arguments.
652declare void @llvm.va_start(ptr) nounwind
653define float @foo_vararg(ptr swifterror %error_ptr_ref, ...) {
654; CHECK-APPLE-LABEL: foo_vararg:
655; CHECK-APPLE:       @ %bb.0: @ %entry
656; CHECK-APPLE-NEXT:    sub sp, sp, #16
657; CHECK-APPLE-NEXT:    push {r7, lr}
658; CHECK-APPLE-NEXT:    mov r7, sp
659; CHECK-APPLE-NEXT:    sub sp, sp, #24
660; CHECK-APPLE-NEXT:    bfc sp, #0, #3
661; CHECK-APPLE-NEXT:    add r8, r7, #8
662; CHECK-APPLE-NEXT:    stm r8, {r0, r1, r2, r3}
663; CHECK-APPLE-NEXT:    mov r0, #16
664; CHECK-APPLE-NEXT:    mov r1, #0
665; CHECK-APPLE-NEXT:    bl _malloc
666; CHECK-APPLE-NEXT:    mov r8, r0
667; CHECK-APPLE-NEXT:    mov r0, #1
668; CHECK-APPLE-NEXT:    strb r0, [r8, #8]
669; CHECK-APPLE-NEXT:    add r0, r7, #8
670; CHECK-APPLE-NEXT:    add r0, r0, #4
671; CHECK-APPLE-NEXT:    ldr r2, [r7, #8]
672; CHECK-APPLE-NEXT:    ldr r1, [r0], #4
673; CHECK-APPLE-NEXT:    ldr r3, [r0], #4
674; CHECK-APPLE-NEXT:    str r0, [sp, #16]
675; CHECK-APPLE-NEXT:    mov r0, #1065353216
676; CHECK-APPLE-NEXT:    str r2, [sp, #12]
677; CHECK-APPLE-NEXT:    str r1, [sp, #8]
678; CHECK-APPLE-NEXT:    str r3, [sp, #4]
679; CHECK-APPLE-NEXT:    mov sp, r7
680; CHECK-APPLE-NEXT:    pop {r7, lr}
681; CHECK-APPLE-NEXT:    add sp, sp, #16
682; CHECK-APPLE-NEXT:    bx lr
683;
684; CHECK-O0-LABEL: foo_vararg:
685; CHECK-O0:       @ %bb.0: @ %entry
686; CHECK-O0-NEXT:    sub sp, sp, #16
687; CHECK-O0-NEXT:    push {r7, lr}
688; CHECK-O0-NEXT:    mov r7, sp
689; CHECK-O0-NEXT:    sub sp, sp, #24
690; CHECK-O0-NEXT:    bfc sp, #0, #3
691; CHECK-O0-NEXT:    str r3, [r7, #20]
692; CHECK-O0-NEXT:    str r2, [r7, #16]
693; CHECK-O0-NEXT:    str r1, [r7, #12]
694; CHECK-O0-NEXT:    str r0, [r7, #8]
695; CHECK-O0-NEXT:    mov r0, #16
696; CHECK-O0-NEXT:    mov r1, #0
697; CHECK-O0-NEXT:    bl _malloc
698; CHECK-O0-NEXT:    mov r1, r0
699; CHECK-O0-NEXT:    mov r8, r1
700; CHECK-O0-NEXT:    mov r0, #1
701; CHECK-O0-NEXT:    strb r0, [r1, #8]
702; CHECK-O0-NEXT:    add r0, r7, #8
703; CHECK-O0-NEXT:    str r0, [sp, #16]
704; CHECK-O0-NEXT:    ldr r0, [sp, #16]
705; CHECK-O0-NEXT:    add r1, r0, #4
706; CHECK-O0-NEXT:    str r1, [sp, #16]
707; CHECK-O0-NEXT:    ldr r0, [r0]
708; CHECK-O0-NEXT:    str r0, [sp, #12]
709; CHECK-O0-NEXT:    ldr r0, [sp, #16]
710; CHECK-O0-NEXT:    add r1, r0, #4
711; CHECK-O0-NEXT:    str r1, [sp, #16]
712; CHECK-O0-NEXT:    ldr r0, [r0]
713; CHECK-O0-NEXT:    str r0, [sp, #8]
714; CHECK-O0-NEXT:    ldr r0, [sp, #16]
715; CHECK-O0-NEXT:    add r1, r0, #4
716; CHECK-O0-NEXT:    str r1, [sp, #16]
717; CHECK-O0-NEXT:    ldr r0, [r0]
718; CHECK-O0-NEXT:    str r0, [sp, #4]
719; CHECK-O0-NEXT:    mov r0, #1065353216
720; CHECK-O0-NEXT:    mov sp, r7
721; CHECK-O0-NEXT:    pop {r7, lr}
722; CHECK-O0-NEXT:    add sp, sp, #16
723; CHECK-O0-NEXT:    bx lr
724;
725; CHECK-ANDROID-LABEL: foo_vararg:
726; CHECK-ANDROID:       @ %bb.0: @ %entry
727; CHECK-ANDROID-NEXT:    .pad #16
728; CHECK-ANDROID-NEXT:    sub sp, sp, #16
729; CHECK-ANDROID-NEXT:    .save {r11, lr}
730; CHECK-ANDROID-NEXT:    push {r11, lr}
731; CHECK-ANDROID-NEXT:    .pad #24
732; CHECK-ANDROID-NEXT:    sub sp, sp, #24
733; CHECK-ANDROID-NEXT:    add r8, sp, #32
734; CHECK-ANDROID-NEXT:    stm r8, {r0, r1, r2, r3}
735; CHECK-ANDROID-NEXT:    mov r0, #16
736; CHECK-ANDROID-NEXT:    mov r1, #0
737; CHECK-ANDROID-NEXT:    bl malloc
738; CHECK-ANDROID-NEXT:    mov r8, r0
739; CHECK-ANDROID-NEXT:    mov r0, #1
740; CHECK-ANDROID-NEXT:    strb r0, [r8, #8]
741; CHECK-ANDROID-NEXT:    add r0, sp, #32
742; CHECK-ANDROID-NEXT:    orr r0, r0, #4
743; CHECK-ANDROID-NEXT:    ldr r2, [sp, #32]
744; CHECK-ANDROID-NEXT:    ldr r1, [r0], #4
745; CHECK-ANDROID-NEXT:    ldr r3, [r0], #4
746; CHECK-ANDROID-NEXT:    str r0, [sp, #16]
747; CHECK-ANDROID-NEXT:    mov r0, #1065353216
748; CHECK-ANDROID-NEXT:    str r2, [sp, #12]
749; CHECK-ANDROID-NEXT:    str r1, [sp, #8]
750; CHECK-ANDROID-NEXT:    str r3, [sp, #4]
751; CHECK-ANDROID-NEXT:    add sp, sp, #24
752; CHECK-ANDROID-NEXT:    pop {r11, lr}
753; CHECK-ANDROID-NEXT:    add sp, sp, #16
754; CHECK-ANDROID-NEXT:    bx lr
755
756entry:
757  %call = call ptr @malloc(i64 16)
758  store ptr %call, ptr %error_ptr_ref
759  %tmp = getelementptr inbounds i8, ptr %call, i64 8
760  store i8 1, ptr %tmp
761
762  %args = alloca ptr, align 8
763  %a10 = alloca i32, align 4
764  %a11 = alloca i32, align 4
765  %a12 = alloca i32, align 4
766  call void @llvm.va_start(ptr %args)
767  %v11 = va_arg ptr %args, i32
768  store i32 %v11, ptr %a10, align 4
769  %v12 = va_arg ptr %args, i32
770  store i32 %v12, ptr %a11, align 4
771  %v13 = va_arg ptr %args, i32
772  store i32 %v13, ptr %a12, align 4
773
774  ret float 1.0
775}
776
777; "caller4" calls "foo_vararg" that takes a swifterror parameter.
778define float @caller4(ptr %error_ref) {
779; CHECK-APPLE-LABEL: caller4:
780; CHECK-APPLE:       @ %bb.0: @ %entry
781; CHECK-APPLE-NEXT:    push {r4, r8, lr}
782; CHECK-APPLE-NEXT:    sub sp, sp, #16
783; CHECK-APPLE-NEXT:    mov r4, r0
784; CHECK-APPLE-NEXT:    mov r0, #11
785; CHECK-APPLE-NEXT:    str r0, [sp, #4]
786; CHECK-APPLE-NEXT:    mov r0, #10
787; CHECK-APPLE-NEXT:    str r0, [sp, #8]
788; CHECK-APPLE-NEXT:    mov r0, #12
789; CHECK-APPLE-NEXT:    str r0, [sp]
790; CHECK-APPLE-NEXT:    mov r8, #0
791; CHECK-APPLE-NEXT:    mov r0, #10
792; CHECK-APPLE-NEXT:    mov r1, #11
793; CHECK-APPLE-NEXT:    mov r2, #12
794; CHECK-APPLE-NEXT:    bl _foo_vararg
795; CHECK-APPLE-NEXT:    mov r0, r8
796; CHECK-APPLE-NEXT:    cmp r8, #0
797; CHECK-APPLE-NEXT:    ldrbeq r1, [r0, #8]
798; CHECK-APPLE-NEXT:    strbeq r1, [r4]
799; CHECK-APPLE-NEXT:    bl _free
800; CHECK-APPLE-NEXT:    mov r0, #1065353216
801; CHECK-APPLE-NEXT:    add sp, sp, #16
802; CHECK-APPLE-NEXT:    pop {r4, r8, pc}
803;
804; CHECK-O0-LABEL: caller4:
805; CHECK-O0:       @ %bb.0: @ %entry
806; CHECK-O0-NEXT:    push	{r7, r8, lr}
807; CHECK-O0-NEXT:    add	r7, sp, #4
808; CHECK-O0-NEXT:    sub	sp, sp, #24
809; CHECK-O0-NEXT:    @ implicit-def: $r1
810; CHECK-O0-NEXT:    str	r0, [sp] @ 4-byte Spill
811; CHECK-O0-NEXT:    mov	r8, #0
812; CHECK-O0-NEXT:    mov	r0, #10
813; CHECK-O0-NEXT:    str	r0, [r7, #-12]
814; CHECK-O0-NEXT:    mov	r0, #11
815; CHECK-O0-NEXT:    str	r0, [sp, #12]
816; CHECK-O0-NEXT:    mov	r0, #12
817; CHECK-O0-NEXT:    str	r0, [sp, #8]
818; CHECK-O0-NEXT:    ldr	r0, [r7, #-12]
819; CHECK-O0-NEXT:    ldr	r1, [sp, #12]
820; CHECK-O0-NEXT:    ldr	r2, [sp, #8]
821; CHECK-O0-NEXT:    bl	_foo_vararg
822; CHECK-O0-NEXT:    str	r8, [sp, #4] @ 4-byte Spill
823; CHECK-O0-NEXT:    movw	r0, #0
824; CHECK-O0-NEXT:    cmp	r8, r0
825; CHECK-O0-NEXT:    bne	LBB8_2
826; CHECK-O0-NEXT:  @ %bb.1: @ %cont
827; CHECK-O0-NEXT:    ldr r1, [sp] @ 4-byte Reload
828; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
829; CHECK-O0-NEXT:    ldrb r0, [r0, #8]
830; CHECK-O0-NEXT:    strb r0, [r1]
831; CHECK-O0-NEXT:  LBB8_2: @ %handler
832; CHECK-O0-NEXT:    ldr r0, [sp, #4] @ 4-byte Reload
833; CHECK-O0-NEXT:    bl _free
834; CHECK-O0-NEXT:    mov r0, #1065353216
835; CHECK-O0-NEXT:    sub sp, r7, #4
836; CHECK-O0-NEXT:    pop	{r7, r8, pc}
837;
838; CHECK-ANDROID-LABEL: caller4:
839; CHECK-ANDROID:       @ %bb.0: @ %entry
840; CHECK-ANDROID-NEXT:    .save {r4, r8, r11, lr}
841; CHECK-ANDROID-NEXT:    push {r4, r8, r11, lr}
842; CHECK-ANDROID-NEXT:    .pad #16
843; CHECK-ANDROID-NEXT:    sub sp, sp, #16
844; CHECK-ANDROID-NEXT:    mov r4, r0
845; CHECK-ANDROID-NEXT:    mov r0, #11
846; CHECK-ANDROID-NEXT:    str r0, [sp, #4]
847; CHECK-ANDROID-NEXT:    mov r0, #10
848; CHECK-ANDROID-NEXT:    str r0, [sp, #8]
849; CHECK-ANDROID-NEXT:    mov r0, #12
850; CHECK-ANDROID-NEXT:    str r0, [sp]
851; CHECK-ANDROID-NEXT:    mov r8, #0
852; CHECK-ANDROID-NEXT:    mov r0, #10
853; CHECK-ANDROID-NEXT:    mov r1, #11
854; CHECK-ANDROID-NEXT:    mov r2, #12
855; CHECK-ANDROID-NEXT:    bl foo_vararg
856; CHECK-ANDROID-NEXT:    mov r0, r8
857; CHECK-ANDROID-NEXT:    cmp r8, #0
858; CHECK-ANDROID-NEXT:    ldrbeq r1, [r0, #8]
859; CHECK-ANDROID-NEXT:    strbeq r1, [r4]
860; CHECK-ANDROID-NEXT:    bl free
861; CHECK-ANDROID-NEXT:    mov r0, #1065353216
862; CHECK-ANDROID-NEXT:    add sp, sp, #16
863; CHECK-ANDROID-NEXT:    pop {r4, r8, r11, pc}
864; Access part of the error object and save it to error_ref
865entry:
866  %error_ptr_ref = alloca swifterror ptr
867  store ptr null, ptr %error_ptr_ref
868
869  %a10 = alloca i32, align 4
870  %a11 = alloca i32, align 4
871  %a12 = alloca i32, align 4
872  store i32 10, ptr %a10, align 4
873  store i32 11, ptr %a11, align 4
874  store i32 12, ptr %a12, align 4
875  %v10 = load i32, ptr %a10, align 4
876  %v11 = load i32, ptr %a11, align 4
877  %v12 = load i32, ptr %a12, align 4
878
879  %call = call float (ptr, ...) @foo_vararg(ptr swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
880  %error_from_foo = load ptr, ptr %error_ptr_ref
881  %had_error_from_foo = icmp ne ptr %error_from_foo, null
882  br i1 %had_error_from_foo, label %handler, label %cont
883
884cont:
885  %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
886  %t = load i8, ptr %v1
887  store i8 %t, ptr %error_ref
888  br label %handler
889handler:
890  call void @free(ptr %error_from_foo)
891  ret float 1.0
892}
893
894; Check that we don't blow up on tail calling swifterror argument functions.
895define float @tailcallswifterror(ptr swifterror %error_ptr_ref) {
896; CHECK-APPLE-LABEL: tailcallswifterror:
897; CHECK-APPLE:       @ %bb.0: @ %entry
898; CHECK-APPLE-NEXT:    push {lr}
899; CHECK-APPLE-NEXT:    bl _tailcallswifterror
900; CHECK-APPLE-NEXT:    pop {lr}
901; CHECK-APPLE-NEXT:    bx lr
902;
903; CHECK-O0-LABEL: tailcallswifterror:
904; CHECK-O0:       @ %bb.0: @ %entry
905; CHECK-O0-NEXT:    push {r7, lr}
906; CHECK-O0-NEXT:    mov r7, sp
907; CHECK-O0-NEXT:    bl _tailcallswifterror
908; CHECK-O0-NEXT:    pop {r7, pc}
909;
910; CHECK-ANDROID-LABEL: tailcallswifterror:
911; CHECK-ANDROID:       @ %bb.0: @ %entry
912; CHECK-ANDROID-NEXT:    .save {r11, lr}
913; CHECK-ANDROID-NEXT:    push {r11, lr}
914; CHECK-ANDROID-NEXT:    bl tailcallswifterror
915; CHECK-ANDROID-NEXT:    pop {r11, pc}
916entry:
917  %0 = tail call float @tailcallswifterror(ptr swifterror %error_ptr_ref)
918  ret float %0
919}
920define swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) {
921; CHECK-APPLE-LABEL: tailcallswifterror_swiftcc:
922; CHECK-APPLE:       @ %bb.0: @ %entry
923; CHECK-APPLE-NEXT:    push {lr}
924; CHECK-APPLE-NEXT:    bl _tailcallswifterror_swiftcc
925; CHECK-APPLE-NEXT:    pop {lr}
926; CHECK-APPLE-NEXT:    bx lr
927;
928; CHECK-O0-LABEL: tailcallswifterror_swiftcc:
929; CHECK-O0:       @ %bb.0: @ %entry
930; CHECK-O0-NEXT:    push {r7, lr}
931; CHECK-O0-NEXT:    mov r7, sp
932; CHECK-O0-NEXT:    bl _tailcallswifterror_swiftcc
933; CHECK-O0-NEXT:    pop {r7, pc}
934;
935; CHECK-ANDROID-LABEL: tailcallswifterror_swiftcc:
936; CHECK-ANDROID:       @ %bb.0: @ %entry
937; CHECK-ANDROID-NEXT:    .save {r11, lr}
938; CHECK-ANDROID-NEXT:    push {r11, lr}
939; CHECK-ANDROID-NEXT:    bl tailcallswifterror_swiftcc
940; CHECK-ANDROID-NEXT:    pop {r11, pc}
941entry:
942  %0 = tail call swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref)
943  ret float %0
944}
945
946define swiftcc void @swifterror_clobber(ptr nocapture swifterror %err) {
947; CHECK-APPLE-LABEL: swifterror_clobber:
948; CHECK-APPLE:       @ %bb.0:
949; CHECK-APPLE-NEXT:    mov r0, r8
950; CHECK-APPLE-NEXT:    @ InlineAsm Start
951; CHECK-APPLE-NEXT:    nop
952; CHECK-APPLE-NEXT:    @ InlineAsm End
953; CHECK-APPLE-NEXT:    mov r8, r0
954; CHECK-APPLE-NEXT:    bx lr
955;
956; CHECK-O0-LABEL: swifterror_clobber:
957; CHECK-O0:       @ %bb.0:
958; CHECK-O0-NEXT:    sub sp, sp, #4
959; CHECK-O0-NEXT:    str r8, [sp] @ 4-byte Spill
960; CHECK-O0-NEXT:    @ InlineAsm Start
961; CHECK-O0-NEXT:    nop
962; CHECK-O0-NEXT:    @ InlineAsm End
963; CHECK-O0-NEXT:    ldr r8, [sp] @ 4-byte Reload
964; CHECK-O0-NEXT:    add sp, sp, #4
965; CHECK-O0-NEXT:    bx lr
966;
967; CHECK-ANDROID-LABEL: swifterror_clobber:
968; CHECK-ANDROID:       @ %bb.0:
969; CHECK-ANDROID-NEXT:    mov r0, r8
970; CHECK-ANDROID-NEXT:    @APP
971; CHECK-ANDROID-NEXT:    nop
972; CHECK-ANDROID-NEXT:    @NO_APP
973; CHECK-ANDROID-NEXT:    mov r8, r0
974; CHECK-ANDROID-NEXT:    bx lr
975  call void asm sideeffect "nop", "~{r8}"()
976  ret void
977}
978
979define swiftcc void @swifterror_reg_clobber(ptr nocapture %err) {
980; CHECK-APPLE-LABEL: swifterror_reg_clobber:
981; CHECK-APPLE:       @ %bb.0:
982; CHECK-APPLE-NEXT:    push {r8, lr}
983; CHECK-APPLE-NEXT:    @ InlineAsm Start
984; CHECK-APPLE-NEXT:    nop
985; CHECK-APPLE-NEXT:    @ InlineAsm End
986; CHECK-APPLE-NEXT:    pop {r8, pc}
987;
988; CHECK-O0-LABEL: swifterror_reg_clobber:
989; CHECK-O0:       @ %bb.0:
990; CHECK-O0-NEXT:    push	{r7, r8, lr}
991; CHECK-O0-NEXT:    add	r7, sp, #4
992; CHECK-O0-NEXT:    @ InlineAsm Start
993; CHECK-O0-NEXT:    nop
994; CHECK-O0-NEXT:    @ InlineAsm End
995; CHECK-O0-NEXT:    pop	{r7, r8, pc}
996;
997; CHECK-ANDROID-LABEL: swifterror_reg_clobber:
998; CHECK-ANDROID:       @ %bb.0:
999; CHECK-ANDROID-NEXT:    .save {r8, lr}
1000; CHECK-ANDROID-NEXT:    push {r8, lr}
1001; CHECK-ANDROID-NEXT:    @APP
1002; CHECK-ANDROID-NEXT:    nop
1003; CHECK-ANDROID-NEXT:    @NO_APP
1004; CHECK-ANDROID-NEXT:    pop {r8, pc}
1005  call void asm sideeffect "nop", "~{r8}"()
1006  ret void
1007}
1008
1009define swiftcc void @params_in_reg(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) {
1010; CHECK-APPLE-LABEL: params_in_reg:
1011; CHECK-APPLE:       @ %bb.0:
1012; CHECK-APPLE-NEXT:    push {r4, r5, r6, r7, r10, r11, lr}
1013; CHECK-APPLE-NEXT:    add r7, sp, #20
1014; CHECK-APPLE-NEXT:    sub sp, sp, #12
1015; CHECK-APPLE-NEXT:    bfc sp, #0, #3
1016; CHECK-APPLE-NEXT:    str r8, [sp, #4] @ 4-byte Spill
1017; CHECK-APPLE-NEXT:    mov r6, r3
1018; CHECK-APPLE-NEXT:    str r10, [sp] @ 4-byte Spill
1019; CHECK-APPLE-NEXT:    mov r4, r2
1020; CHECK-APPLE-NEXT:    mov r11, r1
1021; CHECK-APPLE-NEXT:    mov r5, r0
1022; CHECK-APPLE-NEXT:    mov r0, #1
1023; CHECK-APPLE-NEXT:    mov r1, #2
1024; CHECK-APPLE-NEXT:    mov r2, #3
1025; CHECK-APPLE-NEXT:    mov r3, #4
1026; CHECK-APPLE-NEXT:    mov r10, #0
1027; CHECK-APPLE-NEXT:    mov r8, #0
1028; CHECK-APPLE-NEXT:    bl _params_in_reg2
1029; CHECK-APPLE-NEXT:    ldr r10, [sp] @ 4-byte Reload
1030; CHECK-APPLE-NEXT:    mov r0, r5
1031; CHECK-APPLE-NEXT:    ldr r8, [sp, #4] @ 4-byte Reload
1032; CHECK-APPLE-NEXT:    mov r1, r11
1033; CHECK-APPLE-NEXT:    mov r2, r4
1034; CHECK-APPLE-NEXT:    mov r3, r6
1035; CHECK-APPLE-NEXT:    bl _params_in_reg2
1036; CHECK-APPLE-NEXT:    sub sp, r7, #20
1037; CHECK-APPLE-NEXT:    pop {r4, r5, r6, r7, r10, r11, pc}
1038;
1039; CHECK-O0-LABEL: params_in_reg:
1040; CHECK-O0:       @ %bb.0:
1041; CHECK-O0-NEXT:    push	{r7, r10, lr}
1042; CHECK-O0-NEXT:    add	r7, sp, #4
1043; CHECK-O0-NEXT:    sub	sp, sp, #28
1044; CHECK-O0-NEXT:    bfc	sp, #0, #3
1045; CHECK-O0-NEXT:    str	r8, [sp, #20] @ 4-byte Spill
1046; CHECK-O0-NEXT:    str	r10, [sp] @ 4-byte Spill
1047; CHECK-O0-NEXT:    str	r3, [sp, #16] @ 4-byte Spill
1048; CHECK-O0-NEXT:    str	r2, [sp, #12] @ 4-byte Spill
1049; CHECK-O0-NEXT:    str	r1, [sp, #8] @ 4-byte Spill
1050; CHECK-O0-NEXT:    str	r0, [sp, #4] @ 4-byte Spill
1051; CHECK-O0-NEXT:    @ implicit-def: $r0
1052; CHECK-O0-NEXT:    mov	r8, #0
1053; CHECK-O0-NEXT:    mov	r0, #1
1054; CHECK-O0-NEXT:    mov	r1, #2
1055; CHECK-O0-NEXT:    mov	r2, #3
1056; CHECK-O0-NEXT:    mov	r3, #4
1057; CHECK-O0-NEXT:    mov	r10, r8
1058; CHECK-O0-NEXT:    bl	_params_in_reg2
1059; CHECK-O0-NEXT:    ldr	r10, [sp] @ 4-byte Reload
1060; CHECK-O0-NEXT:    ldr	r0, [sp, #4] @ 4-byte Reload
1061; CHECK-O0-NEXT:    ldr	r1, [sp, #8] @ 4-byte Reload
1062; CHECK-O0-NEXT:    ldr	r2, [sp, #12] @ 4-byte Reload
1063; CHECK-O0-NEXT:    ldr	r3, [sp, #16] @ 4-byte Reload
1064; CHECK-O0-NEXT:    mov	r9, r8
1065; CHECK-O0-NEXT:    ldr	r8, [sp, #20] @ 4-byte Reload
1066; CHECK-O0-NEXT:    bl	_params_in_reg2
1067; CHECK-O0-NEXT:    sub	sp, r7, #4
1068; CHECK-O0-NEXT:    pop	{r7, r10, pc}
1069;
1070; CHECK-ANDROID-LABEL: params_in_reg:
1071; CHECK-ANDROID:       @ %bb.0:
1072; CHECK-ANDROID-NEXT:    .save {r4, r5, r6, r7, r9, r10, r11, lr}
1073; CHECK-ANDROID-NEXT:    push {r4, r5, r6, r7, r9, r10, r11, lr}
1074; CHECK-ANDROID-NEXT:    .pad #8
1075; CHECK-ANDROID-NEXT:    sub sp, sp, #8
1076; CHECK-ANDROID-NEXT:    mov r9, r8
1077; CHECK-ANDROID-NEXT:    mov r11, r10
1078; CHECK-ANDROID-NEXT:    mov r6, r3
1079; CHECK-ANDROID-NEXT:    mov r7, r2
1080; CHECK-ANDROID-NEXT:    mov r4, r1
1081; CHECK-ANDROID-NEXT:    mov r5, r0
1082; CHECK-ANDROID-NEXT:    mov r0, #1
1083; CHECK-ANDROID-NEXT:    mov r1, #2
1084; CHECK-ANDROID-NEXT:    mov r2, #3
1085; CHECK-ANDROID-NEXT:    mov r3, #4
1086; CHECK-ANDROID-NEXT:    mov r10, #0
1087; CHECK-ANDROID-NEXT:    mov r8, #0
1088; CHECK-ANDROID-NEXT:    bl params_in_reg2
1089; CHECK-ANDROID-NEXT:    mov r0, r5
1090; CHECK-ANDROID-NEXT:    mov r1, r4
1091; CHECK-ANDROID-NEXT:    mov r2, r7
1092; CHECK-ANDROID-NEXT:    mov r3, r6
1093; CHECK-ANDROID-NEXT:    mov r10, r11
1094; CHECK-ANDROID-NEXT:    mov r8, r9
1095; CHECK-ANDROID-NEXT:    bl params_in_reg2
1096; CHECK-ANDROID-NEXT:    add sp, sp, #8
1097; CHECK-ANDROID-NEXT:    pop {r4, r5, r6, r7, r9, r10, r11, pc}
1098  %error_ptr_ref = alloca swifterror ptr, align 8
1099  store ptr null, ptr %error_ptr_ref
1100  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref)
1101  call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, ptr swiftself %4, ptr nocapture swifterror %err)
1102  ret void
1103}
1104declare swiftcc void @params_in_reg2(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err)
1105
1106define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err) {
1107; CHECK-APPLE-LABEL: params_and_return_in_reg:
1108; CHECK-APPLE:       @ %bb.0:
1109; CHECK-APPLE-NEXT:    push {r4, r5, r6, r7, r10, r11, lr}
1110; CHECK-APPLE-NEXT:    add r7, sp, #20
1111; CHECK-APPLE-NEXT:    sub sp, sp, #20
1112; CHECK-APPLE-NEXT:    bfc sp, #0, #3
1113; CHECK-APPLE-NEXT:    mov r6, r8
1114; CHECK-APPLE-NEXT:    str r10, [sp, #12] @ 4-byte Spill
1115; CHECK-APPLE-NEXT:    str r3, [sp, #8] @ 4-byte Spill
1116; CHECK-APPLE-NEXT:    mov r4, r2
1117; CHECK-APPLE-NEXT:    mov r11, r1
1118; CHECK-APPLE-NEXT:    mov r5, r0
1119; CHECK-APPLE-NEXT:    mov r0, #1
1120; CHECK-APPLE-NEXT:    mov r1, #2
1121; CHECK-APPLE-NEXT:    mov r2, #3
1122; CHECK-APPLE-NEXT:    mov r3, #4
1123; CHECK-APPLE-NEXT:    mov r10, #0
1124; CHECK-APPLE-NEXT:    mov r8, #0
1125; CHECK-APPLE-NEXT:    bl _params_in_reg2
1126; CHECK-APPLE-NEXT:    ldr r3, [sp, #8] @ 4-byte Reload
1127; CHECK-APPLE-NEXT:    mov r0, r5
1128; CHECK-APPLE-NEXT:    ldr r10, [sp, #12] @ 4-byte Reload
1129; CHECK-APPLE-NEXT:    mov r1, r11
1130; CHECK-APPLE-NEXT:    str r8, [sp, #4] @ 4-byte Spill
1131; CHECK-APPLE-NEXT:    mov r2, r4
1132; CHECK-APPLE-NEXT:    mov r8, r6
1133; CHECK-APPLE-NEXT:    bl _params_and_return_in_reg2
1134; CHECK-APPLE-NEXT:    str r8, [sp, #12] @ 4-byte Spill
1135; CHECK-APPLE-NEXT:    mov r4, r0
1136; CHECK-APPLE-NEXT:    ldr r8, [sp, #4] @ 4-byte Reload
1137; CHECK-APPLE-NEXT:    mov r5, r1
1138; CHECK-APPLE-NEXT:    mov r6, r2
1139; CHECK-APPLE-NEXT:    mov r11, r3
1140; CHECK-APPLE-NEXT:    mov r0, #1
1141; CHECK-APPLE-NEXT:    mov r1, #2
1142; CHECK-APPLE-NEXT:    mov r2, #3
1143; CHECK-APPLE-NEXT:    mov r3, #4
1144; CHECK-APPLE-NEXT:    mov r10, #0
1145; CHECK-APPLE-NEXT:    bl _params_in_reg2
1146; CHECK-APPLE-NEXT:    mov r0, r4
1147; CHECK-APPLE-NEXT:    mov r1, r5
1148; CHECK-APPLE-NEXT:    mov r2, r6
1149; CHECK-APPLE-NEXT:    mov r3, r11
1150; CHECK-APPLE-NEXT:    ldr r8, [sp, #12] @ 4-byte Reload
1151; CHECK-APPLE-NEXT:    sub sp, r7, #20
1152; CHECK-APPLE-NEXT:    pop {r4, r5, r6, r7, r10, r11, pc}
1153;
1154; CHECK-O0-LABEL: params_and_return_in_reg:
1155; CHECK-O0:       @ %bb.0:
1156; CHECK-O0-NEXT:    push	{r7, r10, lr}
1157; CHECK-O0-NEXT:    add	r7, sp, #4
1158; CHECK-O0-NEXT:    sub	sp, sp, #76
1159; CHECK-O0-NEXT:    bfc	sp, #0, #3
1160; CHECK-O0-NEXT:    str	r8, [sp, #24] @ 4-byte Spill
1161; CHECK-O0-NEXT:    str	r10, [sp, #4] @ 4-byte Spill
1162; CHECK-O0-NEXT:    str	r3, [sp, #20] @ 4-byte Spill
1163; CHECK-O0-NEXT:    str	r2, [sp, #16] @ 4-byte Spill
1164; CHECK-O0-NEXT:    str	r1, [sp, #12] @ 4-byte Spill
1165; CHECK-O0-NEXT:    str	r0, [sp, #8] @ 4-byte Spill
1166; CHECK-O0-NEXT:    @ implicit-def: $r0
1167; CHECK-O0-NEXT:    mov	r8, #0
1168; CHECK-O0-NEXT:    str	r8, [sp, #28] @ 4-byte Spill
1169; CHECK-O0-NEXT:    mov	r0, #1
1170; CHECK-O0-NEXT:    str	r0, [sp, #32] @ 4-byte Spill
1171; CHECK-O0-NEXT:    mov	r1, #2
1172; CHECK-O0-NEXT:    str	r1, [sp, #36] @ 4-byte Spill
1173; CHECK-O0-NEXT:    mov	r2, #3
1174; CHECK-O0-NEXT:    str	r2, [sp, #40] @ 4-byte Spill
1175; CHECK-O0-NEXT:    mov	r3, #4
1176; CHECK-O0-NEXT:    str	r3, [sp, #44] @ 4-byte Spill
1177; CHECK-O0-NEXT:    mov	r10, r8
1178; CHECK-O0-NEXT:    bl	_params_in_reg2
1179; CHECK-O0-NEXT:    ldr	r10, [sp, #4] @ 4-byte Reload
1180; CHECK-O0-NEXT:    ldr	r0, [sp, #8] @ 4-byte Reload
1181; CHECK-O0-NEXT:    ldr	r1, [sp, #12] @ 4-byte Reload
1182; CHECK-O0-NEXT:    ldr	r2, [sp, #16] @ 4-byte Reload
1183; CHECK-O0-NEXT:    ldr	r3, [sp, #20] @ 4-byte Reload
1184; CHECK-O0-NEXT:    mov	r9, r8
1185; CHECK-O0-NEXT:    ldr	r8, [sp, #24] @ 4-byte Reload
1186; CHECK-O0-NEXT:    str	r9, [sp, #48] @ 4-byte Spill
1187; CHECK-O0-NEXT:    bl	_params_and_return_in_reg2
1188; CHECK-O0-NEXT:    ldr	r10, [sp, #28] @ 4-byte Reload
1189; CHECK-O0-NEXT:    mov	r9, r0
1190; CHECK-O0-NEXT:    ldr	r0, [sp, #32] @ 4-byte Reload
1191; CHECK-O0-NEXT:    str	r9, [sp, #52] @ 4-byte Spill
1192; CHECK-O0-NEXT:    mov	r9, r1
1193; CHECK-O0-NEXT:    ldr	r1, [sp, #36] @ 4-byte Reload
1194; CHECK-O0-NEXT:    str	r9, [sp, #56] @ 4-byte Spill
1195; CHECK-O0-NEXT:    mov	r9, r2
1196; CHECK-O0-NEXT:    ldr	r2, [sp, #40] @ 4-byte Reload
1197; CHECK-O0-NEXT:    str	r9, [sp, #60] @ 4-byte Spill
1198; CHECK-O0-NEXT:    mov	r9, r3
1199; CHECK-O0-NEXT:    ldr	r3, [sp, #44] @ 4-byte Reload
1200; CHECK-O0-NEXT:    str	r9, [sp, #64] @ 4-byte Spill
1201; CHECK-O0-NEXT:    mov	r9, r8
1202; CHECK-O0-NEXT:    ldr	r8, [sp, #48] @ 4-byte Reload
1203; CHECK-O0-NEXT:    str	r9, [sp, #68] @ 4-byte Spill
1204; CHECK-O0-NEXT:    bl	_params_in_reg2
1205; CHECK-O0-NEXT:    ldr	r0, [sp, #52] @ 4-byte Reload
1206; CHECK-O0-NEXT:    ldr	r1, [sp, #56] @ 4-byte Reload
1207; CHECK-O0-NEXT:    ldr	r2, [sp, #60] @ 4-byte Reload
1208; CHECK-O0-NEXT:    ldr	r3, [sp, #64] @ 4-byte Reload
1209; CHECK-O0-NEXT:    mov	r9, r8
1210; CHECK-O0-NEXT:    ldr	r8, [sp, #68] @ 4-byte Reload
1211; CHECK-O0-NEXT:    sub	sp, r7, #4
1212; CHECK-O0-NEXT:    pop	{r7, r10, pc}
1213;
1214; CHECK-ANDROID-LABEL: params_and_return_in_reg:
1215; CHECK-ANDROID:       @ %bb.0:
1216; CHECK-ANDROID-NEXT:    .save {r4, r5, r6, r7, r9, r10, r11, lr}
1217; CHECK-ANDROID-NEXT:    push {r4, r5, r6, r7, r9, r10, r11, lr}
1218; CHECK-ANDROID-NEXT:    .pad #16
1219; CHECK-ANDROID-NEXT:    sub sp, sp, #16
1220; CHECK-ANDROID-NEXT:    str r8, [sp, #4] @ 4-byte Spill
1221; CHECK-ANDROID-NEXT:    mov r11, r10
1222; CHECK-ANDROID-NEXT:    mov r6, r3
1223; CHECK-ANDROID-NEXT:    mov r7, r2
1224; CHECK-ANDROID-NEXT:    mov r4, r1
1225; CHECK-ANDROID-NEXT:    mov r5, r0
1226; CHECK-ANDROID-NEXT:    mov r0, #1
1227; CHECK-ANDROID-NEXT:    mov r1, #2
1228; CHECK-ANDROID-NEXT:    mov r2, #3
1229; CHECK-ANDROID-NEXT:    mov r3, #4
1230; CHECK-ANDROID-NEXT:    mov r10, #0
1231; CHECK-ANDROID-NEXT:    mov r8, #0
1232; CHECK-ANDROID-NEXT:    bl params_in_reg2
1233; CHECK-ANDROID-NEXT:    mov r9, r8
1234; CHECK-ANDROID-NEXT:    ldr r8, [sp, #4] @ 4-byte Reload
1235; CHECK-ANDROID-NEXT:    mov r0, r5
1236; CHECK-ANDROID-NEXT:    mov r1, r4
1237; CHECK-ANDROID-NEXT:    mov r2, r7
1238; CHECK-ANDROID-NEXT:    mov r3, r6
1239; CHECK-ANDROID-NEXT:    mov r10, r11
1240; CHECK-ANDROID-NEXT:    bl params_and_return_in_reg2
1241; CHECK-ANDROID-NEXT:    mov r4, r0
1242; CHECK-ANDROID-NEXT:    mov r5, r1
1243; CHECK-ANDROID-NEXT:    mov r6, r2
1244; CHECK-ANDROID-NEXT:    mov r7, r3
1245; CHECK-ANDROID-NEXT:    mov r11, r8
1246; CHECK-ANDROID-NEXT:    mov r0, #1
1247; CHECK-ANDROID-NEXT:    mov r1, #2
1248; CHECK-ANDROID-NEXT:    mov r2, #3
1249; CHECK-ANDROID-NEXT:    mov r3, #4
1250; CHECK-ANDROID-NEXT:    mov r10, #0
1251; CHECK-ANDROID-NEXT:    mov r8, r9
1252; CHECK-ANDROID-NEXT:    bl params_in_reg2
1253; CHECK-ANDROID-NEXT:    mov r0, r4
1254; CHECK-ANDROID-NEXT:    mov r1, r5
1255; CHECK-ANDROID-NEXT:    mov r2, r6
1256; CHECK-ANDROID-NEXT:    mov r3, r7
1257; CHECK-ANDROID-NEXT:    mov r8, r11
1258; CHECK-ANDROID-NEXT:    add sp, sp, #16
1259; CHECK-ANDROID-NEXT:    pop {r4, r5, r6, r7, r9, r10, r11, pc}
1260  %error_ptr_ref = alloca swifterror ptr, align 8
1261  store ptr null, ptr %error_ptr_ref
1262  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref)
1263  %val = call swiftcc  { i32, i32, i32, i32 } @params_and_return_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, ptr swiftself %4, ptr nocapture swifterror %err)
1264  call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, ptr swiftself null, ptr nocapture swifterror %error_ptr_ref)
1265  ret { i32, i32, i32, i32 }%val
1266}
1267
1268declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, ptr swiftself, ptr nocapture swifterror %err)
1269
1270
1271declare void @acallee(ptr)
1272
1273; Make sure we don't tail call if the caller returns a swifterror value. We
1274; would have to move into the swifterror register before the tail call.
1275define swiftcc void @tailcall_from_swifterror(ptr swifterror %error_ptr_ref) {
1276; CHECK-APPLE-LABEL: tailcall_from_swifterror:
1277; CHECK-APPLE:       @ %bb.0: @ %entry
1278; CHECK-APPLE-NEXT:    push {r4, lr}
1279; CHECK-APPLE-NEXT:    mov r0, #0
1280; CHECK-APPLE-NEXT:    mov r4, r8
1281; CHECK-APPLE-NEXT:    bl _acallee
1282; CHECK-APPLE-NEXT:    mov r8, r4
1283; CHECK-APPLE-NEXT:    pop {r4, pc}
1284;
1285; CHECK-O0-LABEL: tailcall_from_swifterror:
1286; CHECK-O0:       @ %bb.0: @ %entry
1287; CHECK-O0-NEXT:    push {r7, lr}
1288; CHECK-O0-NEXT:    mov r7, sp
1289; CHECK-O0-NEXT:    sub sp, sp, #4
1290; CHECK-O0-NEXT:    str r8, [sp] @ 4-byte Spill
1291; CHECK-O0-NEXT:    mov r0, #0
1292; CHECK-O0-NEXT:    bl _acallee
1293; CHECK-O0-NEXT:    ldr r8, [sp] @ 4-byte Reload
1294; CHECK-O0-NEXT:    mov sp, r7
1295; CHECK-O0-NEXT:    pop {r7, pc}
1296;
1297; CHECK-ANDROID-LABEL: tailcall_from_swifterror:
1298; CHECK-ANDROID:       @ %bb.0: @ %entry
1299; CHECK-ANDROID-NEXT:    .save {r4, lr}
1300; CHECK-ANDROID-NEXT:    push {r4, lr}
1301; CHECK-ANDROID-NEXT:    mov r0, #0
1302; CHECK-ANDROID-NEXT:    mov r4, r8
1303; CHECK-ANDROID-NEXT:    bl acallee
1304; CHECK-ANDROID-NEXT:    mov r8, r4
1305; CHECK-ANDROID-NEXT:    pop {r4, pc}
1306entry:
1307  tail call void @acallee(ptr null)
1308  ret void
1309}
1310
1311
1312declare swiftcc void @foo2(ptr swifterror)
1313
1314; Make sure we properly assign registers during fast-isel.
1315define swiftcc ptr @testAssign(ptr %error_ref) {
1316; CHECK-APPLE-LABEL: testAssign:
1317; CHECK-APPLE:       @ %bb.0: @ %entry
1318; CHECK-APPLE-NEXT:    push {r8, lr}
1319; CHECK-APPLE-NEXT:    sub sp, sp, #4
1320; CHECK-APPLE-NEXT:    mov r8, #0
1321; CHECK-APPLE-NEXT:    bl _foo2
1322; CHECK-APPLE-NEXT:    mov r0, r8
1323; CHECK-APPLE-NEXT:    add sp, sp, #4
1324; CHECK-APPLE-NEXT:    pop {r8, pc}
1325;
1326; CHECK-O0-LABEL: testAssign:
1327; CHECK-O0:       @ %bb.0: @ %entry
1328; CHECK-O0-NEXT:    push	{r7, r8, lr}
1329; CHECK-O0-NEXT:    add	r7, sp, #4
1330; CHECK-O0-NEXT:    sub	sp, sp, #8
1331; CHECK-O0-NEXT:    @ implicit-def: $r1
1332; CHECK-O0-NEXT:    mov	r8, #0
1333; CHECK-O0-NEXT:    bl	_foo2
1334; CHECK-O0-NEXT:    str	r8, [sp] @ 4-byte Spill
1335; CHECK-O0-NEXT:  @ %bb.1: @ %a
1336; CHECK-O0-NEXT:    ldr r0, [sp] @ 4-byte Reload
1337; CHECK-O0-NEXT:    sub sp, r7, #4
1338; CHECK-O0-NEXT:    pop	{r7, r8, pc}
1339;
1340; CHECK-ANDROID-LABEL: testAssign:
1341; CHECK-ANDROID:       @ %bb.0: @ %entry
1342; CHECK-ANDROID-NEXT:    .save {r8, lr}
1343; CHECK-ANDROID-NEXT:    push {r8, lr}
1344; CHECK-ANDROID-NEXT:    .pad #8
1345; CHECK-ANDROID-NEXT:    sub sp, sp, #8
1346; CHECK-ANDROID-NEXT:    mov r8, #0
1347; CHECK-ANDROID-NEXT:    bl foo2
1348; CHECK-ANDROID-NEXT:    mov r0, r8
1349; CHECK-ANDROID-NEXT:    add sp, sp, #8
1350; CHECK-ANDROID-NEXT:    pop {r8, pc}
1351entry:
1352  %error_ptr = alloca swifterror ptr
1353  store ptr null, ptr %error_ptr
1354  call swiftcc void @foo2(ptr swifterror %error_ptr)
1355  br label %a
1356
1357a:
1358  %error = load ptr, ptr %error_ptr
1359  ret ptr %error
1360}
1361