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