1; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -enable-shrink-wrap=false < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-APPLE --check-prefix=CHECK-APPLE-AARCH64 %s
2; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -O0 -fast-isel < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-O0 --check-prefix=CHECK-O0-AARCH64 %s
3; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -frame-pointer=all -enable-shrink-wrap=false < %s -mtriple=arm64_32-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-APPLE --check-prefix=CHECK-APPLE-ARM64_32 %s
4; RUN: llc -fast-isel-sink-local-values -verify-machineinstrs -O0 -fast-isel < %s -mtriple=arm64_32-apple-ios -disable-post-ra | FileCheck -allow-deprecated-dag-overlap --check-prefix=CHECK-O0 --check-prefix=CHECK-O0-ARM64_32 %s
5
6declare i8* @malloc(i64)
7declare void @free(i8*)
8%swift_error = type {i64, i8}
9
10; This tests the basic usage of a swifterror parameter. "foo" is the function
11; that takes a swifterror parameter and "caller" is the caller of "foo".
12define float @foo(%swift_error** swifterror %error_ptr_ref) {
13; CHECK-APPLE-LABEL: foo:
14; CHECK-APPLE: mov w0, #16
15; CHECK-APPLE: malloc
16; CHECK-APPLE: mov [[ID:w[0-9]+]], #1
17; CHECK-APPLE: strb [[ID]], [x0, #8]
18; CHECK-APPLE: mov x21, x0
19; CHECK-APPLE-NOT: x21
20
21; CHECK-O0-LABEL: foo:
22; CHECK-O0: mov w{{.*}}, #16
23; CHECK-O0: malloc
24; CHECK-O0: mov x21, x0
25; CHECK-O0-NOT: x21
26; CHECK-O0: mov [[ID:w[0-9]+]], #1
27; CHECK-O0: strb [[ID]], [x0, #8]
28entry:
29  %call = call i8* @malloc(i64 16)
30  %call.0 = bitcast i8* %call to %swift_error*
31  store %swift_error* %call.0, %swift_error** %error_ptr_ref
32  %tmp = getelementptr inbounds i8, i8* %call, i64 8
33  store i8 1, i8* %tmp
34  ret float 1.0
35}
36
37; "caller" calls "foo" that takes a swifterror parameter.
38define float @caller(i8* %error_ref) {
39; CHECK-APPLE-LABEL: caller:
40; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
41; CHECK-APPLE: mov x21, xzr
42; CHECK-APPLE: bl {{.*}}foo
43; CHECK-APPLE: mov x0, x21
44; CHECK-APPLE-AARCH64: cbnz x21
45; CHECK-APPLE-ARM64_32: cbnz w0
46; Access part of the error object and save it to error_ref
47; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x0, #8]
48; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
49; CHECK-APPLE: bl {{.*}}free
50
51; CHECK-O0-LABEL: caller:
52; CHECK-O0: mov x21
53; CHECK-O0: bl {{.*}}foo
54; CHECK-O0: mov [[ID:x[0-9]+]], x21
55; CHECK-O0-AARCH64: cbnz x21
56; CHECK-O0-ARM64_32: cmp x21, #0
57entry:
58  %error_ptr_ref = alloca swifterror %swift_error*
59  store %swift_error* null, %swift_error** %error_ptr_ref
60  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
61  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
62  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
63  %tmp = bitcast %swift_error* %error_from_foo to i8*
64  br i1 %had_error_from_foo, label %handler, label %cont
65cont:
66  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
67  %t = load i8, i8* %v1
68  store i8 %t, i8* %error_ref
69  br label %handler
70handler:
71  call void @free(i8* %tmp)
72  ret float 1.0
73}
74
75; "caller2" is the caller of "foo", it calls "foo" inside a loop.
76define float @caller2(i8* %error_ref) {
77; CHECK-APPLE-LABEL: caller2:
78; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
79; CHECK-APPLE: fmov [[CMP:s[0-9]+]], #1.0
80; CHECK-APPLE: mov x21, xzr
81; CHECK-APPLE: bl {{.*}}foo
82; CHECK-APPLE-AARCH64: cbnz x21
83; CHECK-APPLE-ARM64_32: cbnz w21
84; CHECK-APPLE: fcmp s0, [[CMP]]
85; CHECK-APPLE: b.le
86; Access part of the error object and save it to error_ref
87; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x21, #8]
88; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
89; CHECK-APPLE: mov x0, x21
90; CHECK-APPLE: bl {{.*}}free
91
92; CHECK-O0-LABEL: caller2:
93; CHECK-O0: mov x21
94; CHECK-O0: bl {{.*}}foo
95; CHECK-O0: mov [[ID:x[0-9]+]], x21
96; CHECK-O0-AARCH64: cbnz x21
97; CHECK-O0-ARM64_32: cmp x21, #0
98entry:
99  %error_ptr_ref = alloca swifterror %swift_error*
100  br label %bb_loop
101bb_loop:
102  store %swift_error* null, %swift_error** %error_ptr_ref
103  %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
104  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
105  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
106  %tmp = bitcast %swift_error* %error_from_foo to i8*
107  br i1 %had_error_from_foo, label %handler, label %cont
108cont:
109  %cmp = fcmp ogt float %call, 1.000000e+00
110  br i1 %cmp, label %bb_end, label %bb_loop
111bb_end:
112  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
113  %t = load i8, i8* %v1
114  store i8 %t, i8* %error_ref
115  br label %handler
116handler:
117  call void @free(i8* %tmp)
118  ret float 1.0
119}
120
121; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
122; under a certain condition.
123define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
124; CHECK-APPLE-LABEL: foo_if:
125; CHECK-APPLE: cbz w0
126; CHECK-APPLE: mov w0, #16
127; CHECK-APPLE: malloc
128; CHECK-APPLE: mov [[ID:w[0-9]+]], #1
129; CHECK-APPLE: strb [[ID]], [x0, #8]
130; CHECK-APPLE: mov x21, x0
131; CHECK-APPLE-NOT: x21
132; CHECK-APPLE: ret
133
134; CHECK-O0-LABEL: foo_if:
135; spill x21
136; CHECK-O0: str x21, [sp, [[SLOT:#[0-9]+]]]
137; CHECK-O0: cbz w0
138; CHECK-O0: mov w{{.*}}, #16
139; CHECK-O0: malloc
140; CHECK-O0: mov x21, x0
141; CHECK-O0: mov [[ID2:w[0-9]+]], #1
142; CHECK-O0: strb [[ID2]], [x0, #8]
143; CHECK-O0: ret
144; reload from stack
145; CHECK-O0: ldr x21, [sp, [[SLOT]]]
146; CHECK-O0: ret
147entry:
148  %cond = icmp ne i32 %cc, 0
149  br i1 %cond, label %gen_error, label %normal
150
151gen_error:
152  %call = call i8* @malloc(i64 16)
153  %call.0 = bitcast i8* %call to %swift_error*
154  store %swift_error* %call.0, %swift_error** %error_ptr_ref
155  %tmp = getelementptr inbounds i8, i8* %call, i64 8
156  store i8 1, i8* %tmp
157  ret float 1.0
158
159normal:
160  ret float 0.0
161}
162
163; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
164; under a certain condition inside a loop.
165define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
166; CHECK-APPLE-LABEL: foo_loop:
167; CHECK-APPLE: mov x0, x21
168; CHECK-APPLE: fcmp
169; CHECK-APPLE: b.gt
170; CHECK-APPLE: cbz
171; CHECK-APPLE: mov w0, #16
172; CHECK-APPLE: malloc
173; CHECK-APPLE: strb w{{.*}}, [x0, #8]
174; CHECK-APPLE: mov x21, x0
175; CHECK-APPLE: ret
176
177; CHECK-O0-AARCH64-LABEL: foo_loop:
178; spill x21
179; CHECK-O0-AARCH64: stur x21, [x29, [[SLOT:#-[0-9]+]]]
180; CHECK-O0-AARCH64: b [[BB1:[A-Za-z0-9_]*]]
181; CHECK-O0-AARCH64: [[BB1]]:
182; CHECK-O0-AARCH64: ldur    x0, [x29, [[SLOT]]]
183; CHECK-O0-AARCH64: str     x0, [sp, [[SLOT2:#[0-9]+]]]
184; CHECK-O0-AARCH64: cbz {{.*}}, [[BB2:[A-Za-z0-9_]*]]
185; CHECK-O0-AARCH64: mov w{{.*}}, #16
186; CHECK-O0-AARCH64: malloc
187; CHECK-O0-AARCH64: mov [[ID:x[0-9]+]], x0
188; CHECK-O0-AARCH64: strb w{{.*}}, [{{.*}}[[ID]], #8]
189; spill x0
190; CHECK-O0-AARCH64: str x0, [sp, [[SLOT2]]]
191; CHECK-O0-AARCH64:[[BB2]]:
192; CHECK-O0-AARCH64: ldr     x0, [sp, [[SLOT2]]]
193; CHECK-O0-AARCH64: fcmp
194; CHECK-O0-AARCH64: stur     x0, [x29, [[SLOT]]]
195; CHECK-O0-AARCH64: b.le [[BB1]]
196; reload from stack
197; CHECK-O0-AARCH64: ldr x21, [sp]
198; CHECK-O0-AARCH64: ret
199
200; CHECK-O0-ARM64_32-LABEL: foo_loop:
201; spill x21
202; CHECK-O0-ARM64_32: str x21, [sp, [[SLOT:#[0-9]+]]]
203; CHECK-O0-ARM64_32: b [[BB1:[A-Za-z0-9_]*]]
204; CHECK-O0-ARM64_32: [[BB1]]:
205; CHECK-O0-ARM64_32: ldr     x0, [sp, [[SLOT]]]
206; CHECK-O0-ARM64_32: str     x0, [sp, [[SLOT2:#[0-9]+]]]
207; CHECK-O0-ARM64_32: cbz {{.*}}, [[BB2:[A-Za-z0-9_]*]]
208; CHECK-O0-ARM64_32: mov w{{.*}}, #16
209; CHECK-O0-ARM64_32: malloc
210; CHECK-O0-ARM64_32: mov {{.*}}, x0
211; CHECK-O0-ARM64_32: strb w{{.*}},
212; CHECK-O0-ARM64_32:[[BB2]]:
213; CHECK-O0-ARM64_32: ldr     x0, [sp, [[SLOT2]]]
214; CHECK-O0-ARM64_32: str     x0, [sp[[OFFSET:.*]]]
215; CHECK-O0-ARM64_32: fcmp
216; CHECK-O0-ARM64_32: b.le [[BB1]]
217; reload from stack
218; CHECK-O0-ARM64_32: ldr x21, [sp[[OFFSET]]]
219; CHECK-O0-ARM64_32: ret
220entry:
221  br label %bb_loop
222
223bb_loop:
224  %cond = icmp ne i32 %cc, 0
225  br i1 %cond, label %gen_error, label %bb_cont
226
227gen_error:
228  %call = call i8* @malloc(i64 16)
229  %call.0 = bitcast i8* %call to %swift_error*
230  store %swift_error* %call.0, %swift_error** %error_ptr_ref
231  %tmp = getelementptr inbounds i8, i8* %call, i64 8
232  store i8 1, i8* %tmp
233  br label %bb_cont
234
235bb_cont:
236  %cmp = fcmp ogt float %cc2, 1.000000e+00
237  br i1 %cmp, label %bb_end, label %bb_loop
238bb_end:
239  ret float 0.0
240}
241
242%struct.S = type { i32, i32, i32, i32, i32, i32 }
243
244; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
245; parameter.
246define void @foo_sret(%struct.S* sret(%struct.S) %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
247; CHECK-APPLE-LABEL: foo_sret:
248; CHECK-APPLE: mov [[SRET:x[0-9]+]], x8
249; CHECK-APPLE: mov w0, #16
250; CHECK-APPLE: malloc
251; CHECK-APPLE: mov [[ID:w[0-9]+]], #1
252; CHECK-APPLE: strb [[ID]], [x0, #8]
253; CHECK-APPLE: str w{{.*}}, [{{.*}}[[SRET]], #4]
254; CHECK-APPLE: mov x21, x0
255; CHECK-APPLE-NOT: x21
256
257; CHECK-O0-LABEL: foo_sret:
258; spill x8
259; CHECK-O0-DAG: str x8
260; CHECK-O0: mov w{{.*}}, #16
261; CHECK-O0: malloc
262; CHECK-O0: mov	x10, x0
263; CHECK-O0: mov	x21, x10
264; CHECK-O0: mov [[ID:w[0-9]+]], #1
265; CHECK-O0: strb [[ID]], [x10, #8]
266; reload from stack
267; CHECK-O0: str w{{.*}}, [x8, #4]
268; CHECK-O0-NOT: x21
269entry:
270  %call = call i8* @malloc(i64 16)
271  %call.0 = bitcast i8* %call to %swift_error*
272  store %swift_error* %call.0, %swift_error** %error_ptr_ref
273  %tmp = getelementptr inbounds i8, i8* %call, i64 8
274  store i8 1, i8* %tmp
275  %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
276  store i32 %val1, i32* %v2
277  ret void
278}
279
280; "caller3" calls "foo_sret" that takes a swifterror parameter.
281define float @caller3(i8* %error_ref) {
282; CHECK-APPLE-LABEL: caller3:
283; CHECK-APPLE: mov [[ID:x[0-9]+]], x0
284; CHECK-APPLE: mov x21, xzr
285; CHECK-APPLE: bl {{.*}}foo_sret
286; CHECK-APPLE: mov x0, x21
287; CHECK-APPLE-AARCH64: cbnz x21
288; CHECK-APPLE-ARM64_32: cbnz w0
289; Access part of the error object and save it to error_ref
290; CHECK-APPLE: ldrb [[CODE:w[0-9]+]], [x0, #8]
291; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
292; CHECK-APPLE: bl {{.*}}free
293
294; CHECK-O0-LABEL: caller3:
295; spill x0
296; CHECK-O0: str x0, [sp, [[OFFSET:#[0-9]+]]]
297; CHECK-O0: mov x21
298; CHECK-O0: bl {{.*}}foo_sret
299; CHECK-O0: mov [[ID2:x[0-9]+]], x21
300; CHECK-O0-AARCH64: cbnz x21
301; CHECK-O0-ARM64_32: cmp x21, #0
302; Access part of the error object and save it to error_ref
303; reload from stack
304; CHECK-O0: ldr [[ID:x[0-9]+]], [sp, [[OFFSET]]]
305; CHECK-O0: ldrb [[CODE:w[0-9]+]]
306; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
307; CHECK-O0: bl {{.*}}free
308entry:
309  %s = alloca %struct.S, align 8
310  %error_ptr_ref = alloca swifterror %swift_error*
311  store %swift_error* null, %swift_error** %error_ptr_ref
312  call void @foo_sret(%struct.S* sret(%struct.S) %s, i32 1, %swift_error** swifterror %error_ptr_ref)
313  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
314  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
315  %tmp = bitcast %swift_error* %error_from_foo to i8*
316  br i1 %had_error_from_foo, label %handler, label %cont
317cont:
318  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
319  %t = load i8, i8* %v1
320  store i8 %t, i8* %error_ref
321  br label %handler
322handler:
323  call void @free(i8* %tmp)
324  ret float 1.0
325}
326
327; "foo_vararg" is a function that takes a swifterror parameter, it also has
328; variable number of arguments.
329declare void @llvm.va_start(i8*) nounwind
330define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
331; CHECK-APPLE-LABEL: foo_vararg:
332; CHECK-APPLE: mov w0, #16
333; CHECK-APPLE: malloc
334
335; First vararg
336; CHECK-APPLE-AARCH64: mov [[ID:w[0-9]+]], #1
337; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP:x[0-9]+]], #16]
338; CHECK-APPLE-AARCH64: add [[ARGS:x[0-9]+]], [[TMP]], #16
339; Third vararg
340; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #32]
341; CHECK-APPLE-AARCH64: strb [[ID]], [x0, #8]
342; Second vararg
343; CHECK-APPLE-AARCH64: ldr {{w[0-9]+}}, [{{.*}}[[TMP]], #24]
344
345; CHECK-APPLE-ARM64_32: mov [[ID:w[0-9]+]], #1
346; CHECK-APPLE-ARM64_32: add [[ARGS:x[0-9]+]], [[TMP:x[0-9]+]], #16
347; CHECK-APPLE-ARM64_32: strb [[ID]], [x0, #8]
348
349
350entry:
351  %call = call i8* @malloc(i64 16)
352  %call.0 = bitcast i8* %call to %swift_error*
353  store %swift_error* %call.0, %swift_error** %error_ptr_ref
354  %tmp = getelementptr inbounds i8, i8* %call, i64 8
355  store i8 1, i8* %tmp
356
357  %args = alloca i8*, align 8
358  %a10 = alloca i32, align 4
359  %a11 = alloca i32, align 4
360  %a12 = alloca i32, align 4
361  %v10 = bitcast i8** %args to i8*
362  call void @llvm.va_start(i8* %v10)
363  %v11 = va_arg i8** %args, i32
364  store i32 %v11, i32* %a10, align 4
365  %v12 = va_arg i8** %args, i32
366  store i32 %v12, i32* %a11, align 4
367  %v13 = va_arg i8** %args, i32
368  store i32 %v13, i32* %a12, align 4
369
370  ret float 1.0
371}
372
373; "caller4" calls "foo_vararg" that takes a swifterror parameter.
374define float @caller4(i8* %error_ref) {
375; CHECK-APPLE-LABEL: caller4:
376
377; CHECK-APPLE-AARCH64: mov [[ID:x[0-9]+]], x0
378; CHECK-APPLE-AARCH64: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #8]
379; CHECK-APPLE-AARCH64: str {{x[0-9]+}}, [sp]
380
381; CHECK-APPLE-AARCH64: mov x21, xzr
382; CHECK-APPLE-AARCH64: bl {{.*}}foo_vararg
383; CHECK-APPLE-AARCH64: mov x0, x21
384; CHECK-APPLE-AARCH64: cbnz x21
385; Access part of the error object and save it to error_ref
386; CHECK-APPLE-AARCH64: ldrb [[CODE:w[0-9]+]], [x0, #8]
387; CHECK-APPLE-AARCH64: strb [[CODE]], [{{.*}}[[ID]]]
388; CHECK-APPLE-AARCH64: bl {{.*}}free
389entry:
390  %error_ptr_ref = alloca swifterror %swift_error*
391  store %swift_error* null, %swift_error** %error_ptr_ref
392
393  %a10 = alloca i32, align 4
394  %a11 = alloca i32, align 4
395  %a12 = alloca i32, align 4
396  store i32 10, i32* %a10, align 4
397  store i32 11, i32* %a11, align 4
398  store i32 12, i32* %a12, align 4
399  %v10 = load i32, i32* %a10, align 4
400  %v11 = load i32, i32* %a11, align 4
401  %v12 = load i32, i32* %a12, align 4
402
403  %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
404  %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
405  %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
406  %tmp = bitcast %swift_error* %error_from_foo to i8*
407  br i1 %had_error_from_foo, label %handler, label %cont
408
409cont:
410  %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
411  %t = load i8, i8* %v1
412  store i8 %t, i8* %error_ref
413  br label %handler
414handler:
415  call void @free(i8* %tmp)
416  ret float 1.0
417}
418
419; Check that we don't blow up on tail calling swifterror argument functions.
420define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
421entry:
422  %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
423  ret float %0
424}
425define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
426entry:
427  %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
428  ret float %0
429}
430
431; CHECK-APPLE-LABEL: swifterror_clobber
432; CHECK-APPLE: mov [[REG:x[0-9]+]], x21
433; CHECK-APPLE: nop
434; CHECK-APPLE: mov x21, [[REG]]
435define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
436  call void asm sideeffect "nop", "~{x21}"()
437  ret void
438}
439
440; CHECK-APPLE-LABEL: swifterror_reg_clobber
441; CHECK-APPLE: stp {{.*}}x21
442; CHECK-APPLE: nop
443; CHECK-APPLE: ldp  {{.*}}x21
444define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
445  call void asm sideeffect "nop", "~{x21}"()
446  ret void
447}
448; CHECK-APPLE-LABEL: params_in_reg
449; Save callee saved registers and swifterror since it will be clobbered by the first call to params_in_reg2.
450; CHECK-APPLE:  stp     x21, x28, [sp
451; CHECK-APPLE:  stp     x27, x26, [sp
452; CHECK-APPLE:  stp     x25, x24, [sp
453; CHECK-APPLE:  stp     x23, x22, [sp
454; CHECK-APPLE:  stp     x20, x19, [sp
455; CHECK-APPLE:  stp     x29, x30, [sp
456; CHECK-APPLE:  str     x20, [sp
457; Store argument registers.
458; CHECK-APPLE:  mov      x23, x7
459; CHECK-APPLE:  mov      x24, x6
460; CHECK-APPLE:  mov      x25, x5
461; CHECK-APPLE:  mov      x26, x4
462; CHECK-APPLE:  mov      x27, x3
463; CHECK-APPLE:  mov      x28, x2
464; CHECK-APPLE:  mov      x19, x1
465; CHECK-APPLE:  mov      x22, x0
466; Setup call.
467; CHECK-APPLE:  mov     w0, #1
468; CHECK-APPLE:  mov     w1, #2
469; CHECK-APPLE:  mov     w2, #3
470; CHECK-APPLE:  mov     w3, #4
471; CHECK-APPLE:  mov     w4, #5
472; CHECK-APPLE:  mov     w5, #6
473; CHECK-APPLE:  mov     w6, #7
474; CHECK-APPLE:  mov     w7, #8
475; CHECK-APPLE:  mov      x20, xzr
476; CHECK-APPLE:  mov      x21, xzr
477; CHECK-APPLE:  bl      _params_in_reg2
478; Restore original arguments for next call.
479; CHECK-APPLE:  mov      x0, x22
480; CHECK-APPLE:  mov      x1, x19
481; CHECK-APPLE:  mov      x2, x28
482; CHECK-APPLE:  mov      x3, x27
483; CHECK-APPLE:  mov      x4, x26
484; CHECK-APPLE:  mov      x5, x25
485; CHECK-APPLE:  mov      x6, x24
486; CHECK-APPLE:  mov      x7, x23
487; Restore original swiftself argument and swifterror %err.
488; CHECK-APPLE:  ldp             x20, x21, [sp
489; CHECK-APPLE:  bl      _params_in_reg2
490; Restore calle save registers but don't clober swifterror x21.
491; CHECK-APPLE-NOT: x21
492; CHECK-APPLE:  ldp     x29, x30, [sp
493; CHECK-APPLE-NOT: x21
494; CHECK-APPLE:  ldp     x20, x19, [sp
495; CHECK-APPLE-NOT: x21
496; CHECK-APPLE:  ldp     x23, x22, [sp
497; CHECK-APPLE-NOT: x21
498; CHECK-APPLE:  ldp     x25, x24, [sp
499; CHECK-APPLE-NOT: x21
500; CHECK-APPLE:  ldp     x27, x26, [sp
501; CHECK-APPLE-NOT: x21
502; CHECK-APPLE:  ldr     x28, [sp
503; CHECK-APPLE-NOT: x21
504; CHECK-APPLE:  ret
505define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
506  %error_ptr_ref = alloca swifterror %swift_error*, align 8
507  store %swift_error* null, %swift_error** %error_ptr_ref
508  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
509  call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i8* swiftself %8, %swift_error** nocapture swifterror %err)
510  ret void
511}
512declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
513
514; CHECK-APPLE-LABEL: params_and_return_in_reg
515; Store callee saved registers.
516; CHECK-APPLE:  stp     x20, x28, [sp, #24
517; CHECK-APPLE:  stp     x27, x26, [sp
518; CHECK-APPLE:  stp     x25, x24, [sp
519; CHECK-APPLE:  stp     x23, x22, [sp
520; CHECK-APPLE:  stp     x20, x19, [sp
521; CHECK-APPLE:  stp     x29, x30, [sp
522; Save original arguments.
523; CHECK-APPLE:  mov      x23, x21
524; CHECK-APPLE:  str     x7, [sp, #16]
525; CHECK-APPLE:  mov      x24, x6
526; CHECK-APPLE:  mov      x25, x5
527; CHECK-APPLE:  mov      x26, x4
528; CHECK-APPLE:  mov      x27, x3
529; CHECK-APPLE:  mov      x28, x2
530; CHECK-APPLE:  mov      x19, x1
531; CHECK-APPLE:  mov      x22, x0
532; Setup call arguments.
533; CHECK-APPLE:  mov     w0, #1
534; CHECK-APPLE:  mov     w1, #2
535; CHECK-APPLE:  mov     w2, #3
536; CHECK-APPLE:  mov     w3, #4
537; CHECK-APPLE:  mov     w4, #5
538; CHECK-APPLE:  mov     w5, #6
539; CHECK-APPLE:  mov     w6, #7
540; CHECK-APPLE:  mov     w7, #8
541; CHECK-APPLE:  mov      x20, xzr
542; CHECK-APPLE:  mov      x21, xzr
543; CHECK-APPLE:  bl      _params_in_reg2
544; Store swifterror %error_ptr_ref.
545; CHECK-APPLE:  str     x21, [sp, #8]
546; Setup call arguments from original arguments.
547; CHECK-APPLE:  mov      x0, x22
548; CHECK-APPLE:  mov      x1, x19
549; CHECK-APPLE:  mov      x2, x28
550; CHECK-APPLE:  mov      x3, x27
551; CHECK-APPLE:  mov      x4, x26
552; CHECK-APPLE:  mov      x5, x25
553; CHECK-APPLE:  mov      x6, x24
554; CHECK-APPLE:  ldp     x7, x20, [sp, #16]
555; CHECK-APPLE:  mov      x21, x23
556; CHECK-APPLE:  bl      _params_and_return_in_reg2
557; Store return values.
558; CHECK-APPLE:  mov      x19, x0
559; CHECK-APPLE:  mov      x22, x1
560; CHECK-APPLE:  mov      x24, x2
561; CHECK-APPLE:  mov      x25, x3
562; CHECK-APPLE:  mov      x26, x4
563; CHECK-APPLE:  mov      x27, x5
564; CHECK-APPLE:  mov      x28, x6
565; CHECK-APPLE:  mov      x23, x7
566; Save swifterror %err.
567; CHECK-APPLE:  str     x21, [sp, #24]
568; Setup call.
569; CHECK-APPLE:  mov     w0, #1
570; CHECK-APPLE:  mov     w1, #2
571; CHECK-APPLE:  mov     w2, #3
572; CHECK-APPLE:  mov     w3, #4
573; CHECK-APPLE:  mov     w4, #5
574; CHECK-APPLE:  mov     w5, #6
575; CHECK-APPLE:  mov     w6, #7
576; CHECK-APPLE:  mov     w7, #8
577; CHECK-APPLE:  mov     x20, xzr
578; ... setup call with swiferror %error_ptr_ref.
579; CHECK-APPLE:  ldr     x21, [sp, #8]
580; CHECK-APPLE:  bl      _params_in_reg2
581; Restore return values for return from this function.
582; CHECK-APPLE:  mov      x0, x19
583; CHECK-APPLE:  mov      x1, x22
584; CHECK-APPLE:  mov      x2, x24
585; CHECK-APPLE:  mov      x3, x25
586; CHECK-APPLE:  mov      x4, x26
587; CHECK-APPLE:  mov      x5, x27
588; CHECK-APPLE:  mov      x6, x28
589; CHECK-APPLE:  mov      x7, x23
590; Restore swifterror %err and callee save registers.
591; CHECK-APPLE:  ldp     x21, x28, [sp, #24
592; CHECK-APPLE:  ldp     x29, x30, [sp
593; CHECK-APPLE:  ldp     x20, x19, [sp
594; CHECK-APPLE:  ldp     x23, x22, [sp
595; CHECK-APPLE:  ldp     x25, x24, [sp
596; CHECK-APPLE:  ldp     x27, x26, [sp
597; CHECK-APPLE:  ret
598define swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) {
599  %error_ptr_ref = alloca swifterror %swift_error*, align 8
600  store %swift_error* null, %swift_error** %error_ptr_ref
601  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
602  %val = call swiftcc  { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i8* swiftself %8, %swift_error** nocapture swifterror %err)
603  call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
604  ret { i64, i64, i64, i64, i64, i64, i64, i64 } %val
605}
606
607declare swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err)
608
609declare void @acallee(i8*)
610
611; Make sure we don't tail call if the caller returns a swifterror value. We
612; would have to move into the swifterror register before the tail call.
613; CHECK-APPLE: tailcall_from_swifterror:
614; CHECK-APPLE-NOT: b _acallee
615; CHECK-APPLE: bl _acallee
616
617define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
618entry:
619  tail call void @acallee(i8* null)
620  ret void
621}
622
623declare swiftcc void @foo2(%swift_error** swifterror)
624
625; Make sure we properly assign registers during fast-isel.
626; CHECK-O0-LABEL: testAssign
627; CHECK-O0: mov     x21, xzr
628; CHECK-O0: bl      _foo2
629; CHECK-O0: str     x21, [s[[STK:.*]]]
630; CHECK-O0: ldr x{{[0-9]+}}, [s[[STK]]]
631
632; CHECK-APPLE-LABEL: testAssign
633; CHECK-APPLE: mov      x21, xzr
634; CHECK-APPLE: bl      _foo2
635; CHECK-APPLE: mov      x0, x21
636
637define swiftcc %swift_error* @testAssign(i8* %error_ref) {
638entry:
639  %error_ptr = alloca swifterror %swift_error*
640  store %swift_error* null, %swift_error** %error_ptr
641  call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
642  br label %a
643
644a:
645  %error = load %swift_error*, %swift_error** %error_ptr
646  ret %swift_error* %error
647}
648