OSDN Git Service

ARM: sort register lists by encoding in push/pop instructions.
[android-x86/external-llvm.git] / test / CodeGen / ARM / swifterror.ll
1 ; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE --check-prefix=CHECK-ARMV7 %s
2 ; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s
3
4 declare i8* @malloc(i64)
5 declare void @free(i8*)
6 %swift_error = type { i64, i8 }
7 %struct.S = type { i32, i32, i32, i32, i32, i32 }
8
9 ; This tests the basic usage of a swifterror parameter. "foo" is the function
10 ; that takes a swifterror parameter and "caller" is the caller of "foo".
11 define float @foo(%swift_error** swifterror %error_ptr_ref) {
12 ; CHECK-APPLE-LABEL: foo:
13 ; CHECK-APPLE: mov r0, #16
14 ; CHECK-APPLE: malloc
15 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], #1
16 ; CHECK-APPLE-DAG: mov r6, r{{.*}}
17 ; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
18
19 ; CHECK-O0-LABEL: foo:
20 ; CHECK-O0: mov r{{.*}}, #16
21 ; CHECK-O0: malloc
22 ; CHECK-O0: mov [[ID2:r[0-9]+]], r0
23 ; CHECK-O0: mov [[ID:r[0-9]+]], #1
24 ; CHECK-O0: strb [[ID]], [r0, #8]
25 ; CHECK-O0: mov r6, [[ID2]]
26 entry:
27   %call = call i8* @malloc(i64 16)
28   %call.0 = bitcast i8* %call to %swift_error*
29   store %swift_error* %call.0, %swift_error** %error_ptr_ref
30   %tmp = getelementptr inbounds i8, i8* %call, i64 8
31   store i8 1, i8* %tmp
32   ret float 1.0
33 }
34
35 ; "caller" calls "foo" that takes a swifterror parameter.
36 define float @caller(i8* %error_ref) {
37 ; CHECK-APPLE-LABEL: caller:
38 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
39 ; CHECK-APPLE-DAG: mov r6, #0
40 ; CHECK-APPLE: bl {{.*}}foo
41 ; CHECK-APPLE: cmp r6, #0
42 ; Access part of the error object and save it to error_ref
43 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
44 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
45 ; CHECK-APPLE: mov r0, r6
46 ; CHECK-APPLE: bl {{.*}}free
47
48 ; CHECK-O0-LABEL: caller:
49 ; spill r0
50 ; CHECK-O0-DAG: mov r6, #0
51 ; CHECK-O0-DAG: str r0, [sp, [[SLOT:#[0-9]+]]
52 ; CHECK-O0: bl {{.*}}foo
53 ; CHECK-O0: mov [[TMP:r[0-9]+]], r6
54 ; CHECK-O0: str [[TMP]], [sp]
55 ; CHECK-O0: bne
56 ; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
57 ; CHECK-O0: ldr     [[ID:r[0-9]+]], [sp, [[SLOT]]]
58 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
59 ; reload r0
60 ; CHECK-O0: ldr r0, [sp]
61 ; CHECK-O0: free
62 entry:
63   %error_ptr_ref = alloca swifterror %swift_error*
64   store %swift_error* null, %swift_error** %error_ptr_ref
65   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
66   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
67   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
68   %tmp = bitcast %swift_error* %error_from_foo to i8*
69   br i1 %had_error_from_foo, label %handler, label %cont
70 cont:
71   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
72   %t = load i8, i8* %v1
73   store i8 %t, i8* %error_ref
74   br label %handler
75 handler:
76   call void @free(i8* %tmp)
77   ret float 1.0
78 }
79
80 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
81 define float @caller2(i8* %error_ref) {
82 ; CHECK-APPLE-LABEL: caller2:
83 ; CHECK-APPLE-DAG: mov [[ID:r[0-9]+]], r0
84 ; CHECK-APPLE-DAG: mov r6, #0
85 ; CHECK-APPLE: bl {{.*}}foo
86 ; CHECK-APPLE: cmp r6, #0
87 ; CHECK-APPLE: bne
88 ; Access part of the error object and save it to error_ref
89 ; CHECK-APPLE: ldrb [[CODE:r[0-9]+]], [r6, #8]
90 ; CHECK-APPLE: strb [[CODE]], [{{.*}}[[ID]]]
91 ; CHECK-APPLE: mov r0, r6
92 ; CHECK-APPLE: bl {{.*}}free
93
94 ; CHECK-O0-LABEL: caller2:
95 ; spill r0
96 ; CHECK-O0-DAG: str r0,
97 ; CHECK-O0-DAG: mov r6, #0
98 ; CHECK-O0: bl {{.*}}foo
99 ; CHECK-O0: mov r{{.*}}, r6
100 ; CHECK-O0: str r0, [sp]
101 ; CHECK-O0: bne
102 ; CHECK-O0: ble
103 ; CHECK-O0: ldrb [[CODE:r[0-9]+]], [r0, #8]
104 ; reload r0
105 ; CHECK-O0: ldr [[ID:r[0-9]+]],
106 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
107 ; CHECK-O0: ldr r0, [sp]
108 ; CHECK-O0: free
109 entry:
110   %error_ptr_ref = alloca swifterror %swift_error*
111   br label %bb_loop
112 bb_loop:
113   store %swift_error* null, %swift_error** %error_ptr_ref
114   %call = call float @foo(%swift_error** swifterror %error_ptr_ref)
115   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
116   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
117   %tmp = bitcast %swift_error* %error_from_foo to i8*
118   br i1 %had_error_from_foo, label %handler, label %cont
119 cont:
120   %cmp = fcmp ogt float %call, 1.000000e+00
121   br i1 %cmp, label %bb_end, label %bb_loop
122 bb_end:
123   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
124   %t = load i8, i8* %v1
125   store i8 %t, i8* %error_ref
126   br label %handler
127 handler:
128   call void @free(i8* %tmp)
129   ret float 1.0
130 }
131
132 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
133 ; under a certain condition.
134 define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
135 ; CHECK-APPLE-LABEL: foo_if:
136 ; CHECK-APPLE: cmp r0, #0
137 ; CHECK-APPLE: eq
138 ; CHECK-APPLE: mov r0, #16
139 ; CHECK-APPLE: malloc
140 ; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
141 ; CHECK-APPLE-DAG: mov r6, r{{.*}}
142 ; CHECK-APPLE-DAG: strb [[ID]], [r{{.*}}, #8]
143
144 ; CHECK-O0-LABEL: foo_if:
145 ; CHECK-O0: cmp r0, #0
146 ; spill to stack
147 ; CHECK-O0: str r6
148 ; CHECK-O0: beq
149 ; CHECK-O0: mov r0, #16
150 ; CHECK-O0: malloc
151 ; CHECK-O0: mov [[ID:r[0-9]+]], r0
152 ; CHECK-O0: mov [[ID2:[a-z0-9]+]], #1
153 ; CHECK-O0: strb [[ID2]], [r0, #8]
154 ; CHECK-O0: mov r6, [[ID]]
155 ; reload from stack
156 ; CHECK-O0: ldr r6
157 entry:
158   %cond = icmp ne i32 %cc, 0
159   br i1 %cond, label %gen_error, label %normal
160
161 gen_error:
162   %call = call i8* @malloc(i64 16)
163   %call.0 = bitcast i8* %call to %swift_error*
164   store %swift_error* %call.0, %swift_error** %error_ptr_ref
165   %tmp = getelementptr inbounds i8, i8* %call, i64 8
166   store i8 1, i8* %tmp
167   ret float 1.0
168
169 normal:
170   ret float 0.0
171 }
172
173 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
174 ; under a certain condition inside a loop.
175 define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
176 ; CHECK-APPLE-LABEL: foo_loop:
177 ; CHECK-APPLE: mov [[CODE:r[0-9]+]], r0
178 ; swifterror is kept in a register
179 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r6
180 ; CHECK-APPLE: cmp [[CODE]], #0
181 ; CHECK-APPLE: beq
182 ; CHECK-APPLE: mov r0, #16
183 ; CHECK-APPLE: malloc
184 ; CHECK-APPLE: strb r{{.*}}, [{{.*}}[[ID]], #8]
185 ; CHECK-APPLE: ble
186 ; CHECK-APPLE: mov r6, [[ID]]
187
188 ; CHECK-O0-LABEL: foo_loop:
189 ; CHECK-O0: mov r{{.*}}, r6
190 ; CHECK-O0: cmp r{{.*}}, #0
191 ; CHECK-O0: beq
192 ; CHECK-O0-DAG: movw r{{.*}}, #1
193 ; CHECK-O0-DAG: mov r{{.*}}, #16
194 ; CHECK-O0: malloc
195 ; CHECK-O0-DAG: mov [[ID:r[0-9]+]], r0
196 ; CHECK-O0-DAG: ldr [[ID2:r[0-9]+]], [sp{{.*}}]
197 ; CHECK-O0: strb [[ID2]], [{{.*}}[[ID]], #8]
198 ; spill r0
199 ; CHECK-O0: str r0, [sp{{.*}}]
200 ; CHECK-O0: vcmpe
201 ; CHECK-O0: ble
202 ; reload from stack
203 ; CHECK-O0: ldr r6
204 entry:
205   br label %bb_loop
206
207 bb_loop:
208   %cond = icmp ne i32 %cc, 0
209   br i1 %cond, label %gen_error, label %bb_cont
210
211 gen_error:
212   %call = call i8* @malloc(i64 16)
213   %call.0 = bitcast i8* %call to %swift_error*
214   store %swift_error* %call.0, %swift_error** %error_ptr_ref
215   %tmp = getelementptr inbounds i8, i8* %call, i64 8
216   store i8 1, i8* %tmp
217   br label %bb_cont
218
219 bb_cont:
220   %cmp = fcmp ogt float %cc2, 1.000000e+00
221   br i1 %cmp, label %bb_end, label %bb_loop
222 bb_end:
223   ret float 0.0
224 }
225
226 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
227 ; parameter.
228 define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
229 ; CHECK-APPLE-LABEL: foo_sret:
230 ; CHECK-APPLE: mov [[SRET:r[0-9]+]], r0
231 ; CHECK-APPLE: mov r0, #16
232 ; CHECK-APPLE: malloc
233 ; CHECK-APPLE: mov [[REG:r[0-9]+]], #1
234 ; CHECK-APPLE-DAG: mov r6, r0
235 ; CHECK-APPLE-DAG: strb [[REG]], [r0, #8]
236 ; CHECK-APPLE-DAG: str r{{.*}}, [{{.*}}[[SRET]], #4]
237
238 ; CHECK-O0-LABEL: foo_sret:
239 ; CHECK-O0: mov r{{.*}}, #16
240 ; spill to stack: sret and val1
241 ; CHECK-O0-DAG: str r0
242 ; CHECK-O0-DAG: str r1
243 ; CHECK-O0: malloc
244 ; CHECK-O0: mov [[ID:r[0-9]+]], #1
245 ; CHECK-O0: strb [[ID]], [r0, #8]
246 ; reload from stack: sret and val1
247 ; CHECK-O0: ldr
248 ; CHECK-O0: ldr
249 ; CHECK-O0: str r{{.*}}, [{{.*}}, #4]
250 ; CHECK-O0: mov r6
251 entry:
252   %call = call i8* @malloc(i64 16)
253   %call.0 = bitcast i8* %call to %swift_error*
254   store %swift_error* %call.0, %swift_error** %error_ptr_ref
255   %tmp = getelementptr inbounds i8, i8* %call, i64 8
256   store i8 1, i8* %tmp
257   %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
258   store i32 %val1, i32* %v2
259   ret void
260 }
261
262 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
263 define float @caller3(i8* %error_ref) {
264 ; CHECK-APPLE-LABEL: caller3:
265 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
266 ; CHECK-APPLE: mov r6, #0
267 ; CHECK-APPLE: bl {{.*}}foo_sret
268 ; CHECK-APPLE: cmp r6, #0
269 ; Access part of the error object and save it to error_ref
270 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
271 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
272 ; CHECK-APPLE: mov r0, r6
273 ; CHECK-APPLE: bl {{.*}}free
274
275 ; CHECK-O0-LABEL: caller3:
276 ; CHECK-O0-DAG: mov r6, #0
277 ; CHECK-O0-DAG: mov r0
278 ; CHECK-O0-DAG: mov r1
279 ; CHECK-O0: bl {{.*}}foo_sret
280 ; CHECK-O0: mov [[ID2:r[0-9]+]], r6
281 ; CHECK-O0: cmp r6
282 ; CHECK-O0: str [[ID2]], [sp[[SLOT:.*]]]
283 ; CHECK-O0: bne
284 ; Access part of the error object and save it to error_ref
285 ; CHECK-O0: ldrb [[CODE:r[0-9]+]]
286 ; CHECK-O0: ldr [[ID:r[0-9]+]]
287 ; CHECK-O0: strb [[CODE]], [{{.*}}[[ID]]]
288 ; CHECK-O0: ldr r0, [sp[[SLOT]]
289 ; CHECK-O0: bl {{.*}}free
290 entry:
291   %s = alloca %struct.S, align 8
292   %error_ptr_ref = alloca swifterror %swift_error*
293   store %swift_error* null, %swift_error** %error_ptr_ref
294   call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref)
295   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
296   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
297   %tmp = bitcast %swift_error* %error_from_foo to i8*
298   br i1 %had_error_from_foo, label %handler, label %cont
299 cont:
300   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
301   %t = load i8, i8* %v1
302   store i8 %t, i8* %error_ref
303   br label %handler
304 handler:
305   call void @free(i8* %tmp)
306   ret float 1.0
307 }
308
309 ; "foo_vararg" is a function that takes a swifterror parameter, it also has
310 ; variable number of arguments.
311 declare void @llvm.va_start(i8*) nounwind
312 define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
313 ; CHECK-APPLE-LABEL: foo_vararg:
314 ; CHECK-APPLE: mov r0, #16
315 ; CHECK-APPLE: malloc
316 ; CHECK-APPLE: mov [[REG:r[0-9]+]], r0
317 ; CHECK-APPLE: mov [[ID:r[0-9]+]], #1
318 ; CHECK-APPLE-DAG: strb [[ID]], [{{.*}}[[REG]], #8]
319 ; CHECK-APPLE-DAG: mov r6, [[REG]]
320
321 entry:
322   %call = call i8* @malloc(i64 16)
323   %call.0 = bitcast i8* %call to %swift_error*
324   store %swift_error* %call.0, %swift_error** %error_ptr_ref
325   %tmp = getelementptr inbounds i8, i8* %call, i64 8
326   store i8 1, i8* %tmp
327
328   %args = alloca i8*, align 8
329   %a10 = alloca i32, align 4
330   %a11 = alloca i32, align 4
331   %a12 = alloca i32, align 4
332   %v10 = bitcast i8** %args to i8*
333   call void @llvm.va_start(i8* %v10)
334   %v11 = va_arg i8** %args, i32
335   store i32 %v11, i32* %a10, align 4
336   %v12 = va_arg i8** %args, i32
337   store i32 %v12, i32* %a11, align 4
338   %v13 = va_arg i8** %args, i32
339   store i32 %v13, i32* %a12, align 4
340
341   ret float 1.0
342 }
343
344 ; "caller4" calls "foo_vararg" that takes a swifterror parameter.
345 define float @caller4(i8* %error_ref) {
346 ; CHECK-APPLE-LABEL: caller4:
347 ; CHECK-APPLE: mov [[ID:r[0-9]+]], r0
348 ; CHECK-APPLE: mov r6, #0
349 ; CHECK-APPLE: bl {{.*}}foo_vararg
350 ; CHECK-APPLE: cmp r6, #0
351 ; Access part of the error object and save it to error_ref
352 ; CHECK-APPLE: ldrbeq [[CODE:r[0-9]+]], [r6, #8]
353 ; CHECK-APPLE: strbeq [[CODE]], [{{.*}}[[ID]]]
354 ; CHECK-APPLE: mov r0, r6
355 ; CHECK-APPLE: bl {{.*}}free
356 entry:
357   %error_ptr_ref = alloca swifterror %swift_error*
358   store %swift_error* null, %swift_error** %error_ptr_ref
359
360   %a10 = alloca i32, align 4
361   %a11 = alloca i32, align 4
362   %a12 = alloca i32, align 4
363   store i32 10, i32* %a10, align 4
364   store i32 11, i32* %a11, align 4
365   store i32 12, i32* %a12, align 4
366   %v10 = load i32, i32* %a10, align 4
367   %v11 = load i32, i32* %a11, align 4
368   %v12 = load i32, i32* %a12, align 4
369
370   %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
371   %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
372   %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
373   %tmp = bitcast %swift_error* %error_from_foo to i8*
374   br i1 %had_error_from_foo, label %handler, label %cont
375
376 cont:
377   %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
378   %t = load i8, i8* %v1
379   store i8 %t, i8* %error_ref
380   br label %handler
381 handler:
382   call void @free(i8* %tmp)
383   ret float 1.0
384 }
385
386 ; Check that we don't blow up on tail calling swifterror argument functions.
387 define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
388 entry:
389   %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
390   ret float %0
391 }
392 define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
393 entry:
394   %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
395   ret float %0
396 }
397
398 ; CHECK-APPLE-LABEL: swifterror_clobber
399 ; CHECK-APPLE: mov [[REG:r[0-9]+]], r6
400 ; CHECK-APPLE: nop
401 ; CHECK-APPLE: mov r6, [[REG]]
402 define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
403   call void asm sideeffect "nop", "~{r6}"()
404   ret void
405 }
406
407 ; CHECK-APPLE-LABEL: swifterror_reg_clobber
408 ; CHECK-APPLE: push {{.*}}r6
409 ; CHECK-APPLE: nop
410 ; CHECK-APPLE: pop  {{.*}}r6
411 define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
412   call void asm sideeffect "nop", "~{r6}"()
413   ret void
414 }
415
416 ; CHECK-ARMV7-LABEL: _params_in_reg
417 ; Store callee saved registers excluding swifterror.
418 ; CHECK-ARMV7:  push    {r4, r5, r7, r8, r10, r11, lr}
419 ; Store swiftself (r10) and swifterror (r6).
420 ; CHECK-ARMV7-DAG:  str     r6, [s[[STK1:.*]]]
421 ; CHECK-ARMV7-DAG:  str     r10, [s[[STK2:.*]]]
422 ; Store arguments.
423 ; CHECK-ARMV7:  mov     r4, r3
424 ; CHECK-ARMV7:  mov     r5, r2
425 ; CHECK-ARMV7:  mov     r8, r1
426 ; CHECK-ARMV7:  mov     r11, r0
427 ; Setup call.
428 ; CHECK-ARMV7:  mov     r0, #1
429 ; CHECK-ARMV7:  mov     r1, #2
430 ; CHECK-ARMV7:  mov     r2, #3
431 ; CHECK-ARMV7:  mov     r3, #4
432 ; CHECK-ARMV7:  mov     r10, #0
433 ; CHECK-ARMV7:  mov     r6, #0
434 ; CHECK-ARMV7:  bl      _params_in_reg2
435 ; Restore original arguments.
436 ; CHECK-ARMV7-DAG:  ldr     r10, [s[[STK2]]]
437 ; CHECK-ARMV7-DAG:  ldr     r6, [s[[STK1]]]
438 ; CHECK-ARMV7:  mov     r0, r11
439 ; CHECK-ARMV7:  mov     r1, r8
440 ; CHECK-ARMV7:  mov     r2, r5
441 ; CHECK-ARMV7:  mov     r3, r4
442 ; CHECK-ARMV7:  bl      _params_in_reg2
443 ; CHECK-ARMV7:  pop     {r4, r5, r7,  r8, r10, r11, pc}
444 define swiftcc void @params_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
445   %error_ptr_ref = alloca swifterror %swift_error*, align 8
446   store %swift_error* null, %swift_error** %error_ptr_ref
447   call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
448   call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err)
449   ret void
450 }
451 declare swiftcc void @params_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)
452
453 ; CHECK-ARMV7-LABEL: params_and_return_in_reg
454 ; CHECK-ARMV7:  push    {r4, r5, r7, r8, r10, r11, lr}
455 ; Store swifterror and swiftself
456 ; CHECK-ARMV7:  mov     r4, r6
457 ; CHECK-ARMV7:  str     r10, [s[[STK1:.*]]]
458 ; Store arguments.
459 ; CHECK-ARMV7:  str     r3, [s[[STK2:.*]]]
460 ; CHECK-ARMV7:  mov     r5, r2
461 ; CHECK-ARMV7:  mov     r8, r1
462 ; CHECK-ARMV7:  mov     r11, r0
463 ; Setup call.
464 ; CHECK-ARMV7:  mov     r0, #1
465 ; CHECK-ARMV7:  mov     r1, #2
466 ; CHECK-ARMV7:  mov     r2, #3
467 ; CHECK-ARMV7:  mov     r3, #4
468 ; CHECK-ARMV7:  mov     r10, #0
469 ; CHECK-ARMV7:  mov     r6, #0
470 ; CHECK-ARMV7:  bl      _params_in_reg2
471 ; Restore original arguments.
472 ; CHECK-ARMV7:  ldr     r3, [s[[STK2]]]
473 ; CHECK-ARMV7:  ldr     r10, [s[[STK1]]]
474 ; Store %error_ptr_ref;
475 ; CHECK-ARMV7:  str     r6, [s[[STK3:.*]]]
476 ; Restore original arguments.
477 ; CHECK-ARMV7:  mov     r0, r11
478 ; CHECK-ARMV7:  mov     r1, r8
479 ; CHECK-ARMV7:  mov     r2, r5
480 ; CHECK-ARMV7:  mov     r6, r4
481 ; CHECK-ARMV7:  bl      _params_and_return_in_reg2
482 ; Store swifterror return %err;
483 ; CHECK-ARMV7:  str     r6, [s[[STK1]]]
484 ; Load swifterror value %error_ptr_ref.
485 ; CHECK-ARMV7:  ldr     r6, [s[[STK3]]]
486 ; Save return values.
487 ; CHECK-ARMV7:  mov     r5, r0
488 ; CHECK-ARMV7:  mov     r4, r1
489 ; CHECK-ARMV7:  mov     r8, r2
490 ; CHECK-ARMV7:  mov     r11, r3
491 ; Setup call.
492 ; CHECK-ARMV7:  mov     r0, #1
493 ; CHECK-ARMV7:  mov     r1, #2
494 ; CHECK-ARMV7:  mov     r2, #3
495 ; CHECK-ARMV7:  mov     r3, #4
496 ; CHECK-ARMV7:  mov     r10, #0
497 ; CHECK-ARMV7:  bl      _params_in_reg2
498 ; Load swifterror %err;
499 ; CHECK-ARMV7:  ldr     r6, [s[[STK1]]]
500 ; Restore return values for returning.
501 ; CHECK-ARMV7:  mov     r0, r5
502 ; CHECK-ARMV7:  mov     r1, r4
503 ; CHECK-ARMV7:  mov     r2, r8
504 ; CHECK-ARMV7:  mov     r3, r11
505 ; CHECK-ARMV7:  pop     {r4, r5, r7, r8, r10, r11, pc}
506 define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
507   %error_ptr_ref = alloca swifterror %swift_error*, align 8
508   store %swift_error* null, %swift_error** %error_ptr_ref
509   call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
510   %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)
511   call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
512   ret { i32, i32, i32, i32 }%val
513 }
514
515 declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)