[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / GlobalISel / swifterror.ll
blob6d27e4f4d603bdf038bdcebb304f43477d3d279b
1 ; RUN: llc -verify-machineinstrs -frame-pointer=all -global-isel < %s -mtriple=aarch64-apple-ios | FileCheck %s
3 declare ptr @malloc(i64)
4 declare void @free(ptr)
5 %swift_error = type {i64, i8}
7 ; This tests the basic usage of a swifterror parameter. "foo" is the function
8 ; that takes a swifterror parameter and "caller" is the caller of "foo".
9 define float @foo(ptr swifterror %error_ptr_ref) {
10 ; CHECK-LABEL: foo:
11 ; CHECK: mov w0, #16
12 ; CHECK: malloc
13 ; CHECK: mov [[ID:w[0-9]+]], #1
14 ; CHECK: mov x21, x0
15 ; CHECK: strb [[ID]], [x0, #8]
16 ; CHECK-NOT: x21
18 entry:
19   %call = call ptr @malloc(i64 16)
20   store ptr %call, ptr %error_ptr_ref
21   %tmp = getelementptr inbounds i8, ptr %call, i64 8
22   store i8 1, ptr %tmp
23   ret float 1.0
26 ; "caller" calls "foo" that takes a swifterror parameter.
27 define float @caller(ptr %error_ref) {
28 ; CHECK-LABEL: caller:
29 ; CHECK: mov [[ID:x[0-9]+]], x0
30 ; CHECK: bl {{.*}}foo
31 ; CHECK: mov x0, x21
32 ; CHECK: cbnz x21
33 ; Access part of the error object and save it to error_ref
34 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
35 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
36 ; CHECK: bl {{.*}}free
38 entry:
39   %error_ptr_ref = alloca swifterror ptr
40   store ptr null, ptr %error_ptr_ref
41   %call = call float @foo(ptr swifterror %error_ptr_ref)
42   %error_from_foo = load ptr, ptr %error_ptr_ref
43   %had_error_from_foo = icmp ne ptr %error_from_foo, null
44   br i1 %had_error_from_foo, label %handler, label %cont
45 cont:
46   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
47   %t = load i8, ptr %v1
48   store i8 %t, ptr %error_ref
49   br label %handler
50 handler:
51   call void @free(ptr %error_from_foo)
52   ret float 1.0
55 ; "caller2" is the caller of "foo", it calls "foo" inside a loop.
56 define float @caller2(ptr %error_ref) {
57 ; CHECK-LABEL: caller2:
58 ; CHECK: fmov [[CMP:s[0-9]+]], #1.0
59 ; CHECK: mov [[ID:x[0-9]+]], x0
60 ; CHECK: mov x21, xzr
61 ; CHECK: bl {{.*}}foo
62 ; CHECK: cbnz x21
63 ; CHECK: fcmp s0, [[CMP]]
64 ; CHECK: b.le
65 ; Access part of the error object and save it to error_ref
66 ; CHECK: ldrb [[CODE:w[0-9]+]], [x21, #8]
67 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
68 ; CHECK: mov x0, x21
69 ; CHECK: bl {{.*}}free
71 entry:
72   %error_ptr_ref = alloca swifterror ptr
73   br label %bb_loop
74 bb_loop:
75   store ptr null, ptr %error_ptr_ref
76   %call = call float @foo(ptr swifterror %error_ptr_ref)
77   %error_from_foo = load ptr, ptr %error_ptr_ref
78   %had_error_from_foo = icmp ne ptr %error_from_foo, null
79   br i1 %had_error_from_foo, label %handler, label %cont
80 cont:
81   %cmp = fcmp ogt float %call, 1.000000e+00
82   br i1 %cmp, label %bb_end, label %bb_loop
83 bb_end:
84   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
85   %t = load i8, ptr %v1
86   store i8 %t, ptr %error_ref
87   br label %handler
88 handler:
89   call void @free(ptr %error_from_foo)
90   ret float 1.0
93 ; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
94 ; under a certain condition.
95 define float @foo_if(ptr swifterror %error_ptr_ref, i32 %cc) {
96 ; CHECK-LABEL: foo_if:
97 ; CHECK: cbz w0
98 ; CHECK: mov w0, #16
99 ; CHECK: malloc
100 ; CHECK-DAG: mov x21, x0
101 ; CHECK-DAG: mov [[ID:w[0-9]+]], #1
102 ; CHECK: strb [[ID]], [x0, #8]
103 ; CHECK-NOT: x21
104 ; CHECK: ret
106 entry:
107   %cond = icmp ne i32 %cc, 0
108   br i1 %cond, label %gen_error, label %normal
110 gen_error:
111   %call = call ptr @malloc(i64 16)
112   store ptr %call, ptr %error_ptr_ref
113   %tmp = getelementptr inbounds i8, ptr %call, i64 8
114   store i8 1, ptr %tmp
115   ret float 1.0
117 normal:
118   ret float 0.0
121 ; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
122 ; under a certain condition inside a loop.
123 define float @foo_loop(ptr swifterror %error_ptr_ref, i32 %cc, float %cc2) {
124 ; CHECK-LABEL: foo_loop:
125 ; CHECK: cbz
126 ; CHECK: mov w0, #16
127 ; CHECK: malloc
128 ; CHECK: mov x21, x0
129 ; CHECK: strb w{{.*}}, [x0, #8]
130 ; CHECK: ret
132 entry:
133   br label %bb_loop
135 bb_loop:
136   %cond = icmp ne i32 %cc, 0
137   br i1 %cond, label %gen_error, label %bb_cont
139 gen_error:
140   %call = call ptr @malloc(i64 16)
141   store ptr %call, ptr %error_ptr_ref
142   %tmp = getelementptr inbounds i8, ptr %call, i64 8
143   store i8 1, ptr %tmp
144   br label %bb_cont
146 bb_cont:
147   %cmp = fcmp ogt float %cc2, 1.000000e+00
148   br i1 %cmp, label %bb_end, label %bb_loop
149 bb_end:
150   ret float 0.0
153 %struct.S = type { i32, i32, i32, i32, i32, i32 }
155 ; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
156 ; parameter.
157 define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror %error_ptr_ref) {
158 ; CHECK-LABEL: foo_sret:
159 ; CHECK-DAG: mov [[SRET:x[0-9]+]], x8
160 ; CHECK-DAG: mov w0, #16
161 ; CHECK: malloc
162 ; CHECK: mov [[ID:w[0-9]+]], #1
163 ; CHECK: strb [[ID]], [x0, #8]
164 ; CHECK: mov x21, x0
165 ; CHECK: str w{{.*}}, [{{.*}}[[SRET]], #4]
166 ; CHECK-NOT: x21
168 entry:
169   %call = call ptr @malloc(i64 16)
170   store ptr %call, ptr %error_ptr_ref
171   %tmp = getelementptr inbounds i8, ptr %call, i64 8
172   store i8 1, ptr %tmp
173   %v2 = getelementptr inbounds %struct.S, ptr %agg.result, i32 0, i32 1
174   store i32 %val1, ptr %v2
175   ret void
178 ; "caller3" calls "foo_sret" that takes a swifterror parameter.
179 define float @caller3(ptr %error_ref) {
180 ; CHECK-LABEL: caller3:
181 ; CHECK: mov [[ID:x[0-9]+]], x0
182 ; CHECK: mov [[ZERO:x[0-9]+]], xzr
183 ; CHECK: bl {{.*}}foo_sret
184 ; CHECK: mov x0, x21
185 ; CHECK: cbnz x21
186 ; Access part of the error object and save it to error_ref
187 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
188 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
189 ; CHECK: bl {{.*}}free
191 entry:
192   %s = alloca %struct.S, align 8
193   %error_ptr_ref = alloca swifterror ptr
194   store ptr null, ptr %error_ptr_ref
195   call void @foo_sret(ptr sret(%struct.S) %s, i32 1, ptr swifterror %error_ptr_ref)
196   %error_from_foo = load ptr, ptr %error_ptr_ref
197   %had_error_from_foo = icmp ne ptr %error_from_foo, null
198   br i1 %had_error_from_foo, label %handler, label %cont
199 cont:
200   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
201   %t = load i8, ptr %v1
202   store i8 %t, ptr %error_ref
203   br label %handler
204 handler:
205   call void @free(ptr %error_from_foo)
206   ret float 1.0
209 ; "foo_vararg" is a function that takes a swifterror parameter, it also has
210 ; variable number of arguments.
211 declare void @llvm.va_start(ptr) nounwind
212 define float @foo_vararg(ptr swifterror %error_ptr_ref, ...) {
213 ; CHECK-LABEL: foo_vararg:
214 ; CHECK: mov w0, #16
215 ; CHECK: malloc
216 ; CHECK: mov [[ID:w[0-9]+]], #1
217 ; CHECK: strb [[ID]], [x0, #8]
218 ; CHECK: mov x21, x0
219 ; CHECK-NOT: x21
221 ; First vararg
222 ; CHECK: ldr {{w[0-9]+}}, [x[[ARG1:[0-9]+]]]
223 ; CHECK-NOT: x21
224 ; Second vararg
225 ; CHECK: ldr {{w[0-9]+}}, [x[[ARG1]]]
226 ; CHECK-NOT: x21
227 ; Third vararg
228 ; CHECK: ldr {{w[0-9]+}}, [x[[ARG1]]]
229 ; CHECK-NOT: x21
230 entry:
231   %call = call ptr @malloc(i64 16)
232   store ptr %call, ptr %error_ptr_ref
233   %tmp = getelementptr inbounds i8, ptr %call, i64 8
234   store i8 1, ptr %tmp
236   %args = alloca ptr, align 8
237   %a10 = alloca i32, align 4
238   %a11 = alloca i32, align 4
239   %a12 = alloca i32, align 4
240   call void @llvm.va_start(ptr %args)
241   %v11 = va_arg ptr %args, i32
242   store i32 %v11, ptr %a10, align 4
243   %v12 = va_arg ptr %args, i32
244   store i32 %v12, ptr %a11, align 4
245   %v13 = va_arg ptr %args, i32
246   store i32 %v13, ptr %a12, align 4
248   ret float 1.0
251 ; "caller4" calls "foo_vararg" that takes a swifterror parameter.
252 define float @caller4(ptr %error_ref) {
253 ; CHECK-LABEL: caller4:
255 ; CHECK: mov x21, xzr
256 ; CHECK: mov [[ID:x[0-9]+]], x0
257 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp]
258 ; CHECK: str {{x[0-9]+}}, [sp, #16]
260 ; CHECK: bl {{.*}}foo_vararg
261 ; CHECK: mov x0, x21
262 ; CHECK: cbnz x21
263 ; Access part of the error object and save it to error_ref
264 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
265 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
266 ; CHECK: bl {{.*}}free
267 entry:
268   %error_ptr_ref = alloca swifterror ptr
269   store ptr null, ptr %error_ptr_ref
271   %a10 = alloca i32, align 4
272   %a11 = alloca i32, align 4
273   %a12 = alloca i32, align 4
274   store i32 10, ptr %a10, align 4
275   store i32 11, ptr %a11, align 4
276   store i32 12, ptr %a12, align 4
277   %v10 = load i32, ptr %a10, align 4
278   %v11 = load i32, ptr %a11, align 4
279   %v12 = load i32, ptr %a12, align 4
281   %call = call float (ptr, ...) @foo_vararg(ptr swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
282   %error_from_foo = load ptr, ptr %error_ptr_ref
283   %had_error_from_foo = icmp ne ptr %error_from_foo, null
284   br i1 %had_error_from_foo, label %handler, label %cont
286 cont:
287   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
288   %t = load i8, ptr %v1
289   store i8 %t, ptr %error_ref
290   br label %handler
291 handler:
292   call void @free(ptr %error_from_foo)
293   ret float 1.0
296 ; Check that we don't blow up on tail calling swifterror argument functions.
297 define float @tailcallswifterror(ptr swifterror %error_ptr_ref) {
298 entry:
299   %0 = tail call float @tailcallswifterror(ptr swifterror %error_ptr_ref)
300   ret float %0
302 define swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref) {
303 entry:
304   %0 = tail call swiftcc float @tailcallswifterror_swiftcc(ptr swifterror %error_ptr_ref)
305   ret float %0
308 ; CHECK-LABEL: params_in_reg
309 ; Save callee saved registers and swifterror since it will be clobbered by the first call to params_in_reg2.
310 ; CHECK:  str     x28, [sp
311 ; CHECK:  stp     x27, x26, [sp
312 ; CHECK:  stp     x25, x24, [sp
313 ; CHECK:  stp     x23, x22, [sp
314 ; CHECK:  stp     x20, x19, [sp
315 ; CHECK:  stp     x29, x30, [sp
316 ; Store argument registers.
317 ; CHECK:  mov      x20, x1
318 ; CHECK:  mov      x22, x2
319 ; CHECK:  mov      x23, x3
320 ; CHECK:  mov      x24, x4
321 ; CHECK:  mov      x25, x5
322 ; CHECK:  mov      x26, x6
323 ; CHECK:  mov      x27, x7
324 ; CHECK:  mov      x28, x21
325 ; Setup call.
326 ; CHECK:  mov     w0, #1
327 ; CHECK:  mov     w1, #2
328 ; CHECK:  mov     w2, #3
329 ; CHECK:  mov     w3, #4
330 ; CHECK:  mov     w4, #5
331 ; CHECK:  mov     w5, #6
332 ; CHECK:  mov     w6, #7
333 ; CHECK:  mov     w7, #8
334 ; CHECK:  mov      x21, xzr
335 ; CHECK:  str     xzr, [sp]
336 ; CHECK:  bl      _params_in_reg2
337 ; Restore original arguments for next call.
338 ; CHECK:  ldr     x8, [sp, #24]
339 ; CHECK:  mov      x1, x20
340 ; CHECK:  mov      x2, x22
341 ; CHECK:  mov      x3, x23
342 ; CHECK:  mov      x4, x24
343 ; CHECK:  mov      x5, x25
344 ; CHECK:  mov      x6, x26
345 ; CHECK:  mov      x7, x27
346 ; Restore original swiftself argument and swifterror %err.
347 ; CHECK:  mov      x21, x28
348 ; CHECK:  bl      _params_in_reg2
349 ; Restore calle save registers but don't clober swifterror x21.
350 ; CHECK-NOT: x21
351 ; CHECK:  ldp     x29, x30, [sp
352 ; CHECK-NOT: x21
353 ; CHECK:  ldr     x28, [sp
354 ; CHECK-NOT: x21
355 ; CHECK:  ldp     x20, x19, [sp
356 ; CHECK-NOT: x21
357 ; CHECK:  ldp     x23, x22, [sp
358 ; CHECK-NOT: x21
359 ; CHECK:  ldp     x25, x24, [sp
360 ; CHECK-NOT: x21
361 ; CHECK:  ldp     x27, x26, [sp
362 ; CHECK-NOT: x21
363 ; CHECK:  ret
364 define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, ptr, ptr nocapture swifterror %err) {
365   %error_ptr_ref = alloca swifterror ptr, align 8
366   store ptr null, ptr %error_ptr_ref
367   call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr  null, ptr nocapture swifterror %error_ptr_ref)
368   call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, ptr  %8, ptr nocapture swifterror %err)
369   ret void
371 declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err)
373 ; CHECK-LABEL: params_and_return_in_reg
374 ; Store callee saved registers.
375 ; CHECK:  stp     x28, x0, [sp, #16
376 ; CHECK:  stp     x27, x26, [sp
377 ; CHECK:  stp     x25, x24, [sp
378 ; CHECK:  stp     x23, x22, [sp
379 ; CHECK:  stp     x20, x19, [sp
380 ; CHECK:  stp     x29, x30, [sp
381 ; Save original arguments.
382 ; CHECK:  mov      x20, x1
383 ; CHECK:  mov      x22, x2
384 ; CHECK:  mov      x23, x3
385 ; CHECK:  mov      x24, x4
386 ; CHECK:  mov      x25, x5
387 ; CHECK:  mov      x26, x6
388 ; CHECK:  mov      x27, x7
389 ; Setup call arguments.
390 ; CHECK:  mov     w0, #1
391 ; CHECK:  mov     w1, #2
392 ; CHECK:  mov     w2, #3
393 ; CHECK:  mov     w3, #4
394 ; CHECK:  mov     w4, #5
395 ; CHECK:  mov     w5, #6
396 ; CHECK:  mov     w6, #7
397 ; CHECK:  mov     w7, #8
398 ; CHECK:  mov      x21, xzr
399 ; CHECK:  bl      _params_in_reg2
400 ; Store swifterror %error_ptr_ref.
401 ; CHECK:  ldr     x0, [sp, #24]
402 ; CHECK:  stp     {{x[0-9]+}}, x21, [sp]
403 ; Setup call arguments from original arguments.
404 ; CHECK:  mov      x1, x20
405 ; CHECK:  mov      x2, x22
406 ; CHECK:  mov      x3, x23
407 ; CHECK:  mov      x4, x24
408 ; CHECK:  mov      x5, x25
409 ; CHECK:  mov      x6, x26
410 ; CHECK:  mov      x7, x27
411 ; CHECK:  mov      x21, x28
412 ; CHECK:  bl      _params_and_return_in_reg2
413 ; CHECK:  mov      x19, x21
414 ; CHECK:  ldr      x21, [sp, #8
415 ; Store return values.
416 ; CHECK:  mov     x20, x0
417 ; CHECK:  mov     x22, x1
418 ; CHECK:  mov     x23, x2
419 ; CHECK:  mov     x24, x3
420 ; CHECK:  mov     x25, x4
421 ; CHECK:  mov     x26, x5
422 ; CHECK:  mov     x27, x6
423 ; CHECK:  mov     x28, x7
424 ; Setup call.
425 ; CHECK:  mov     w0, #1
426 ; CHECK:  mov     w1, #2
427 ; CHECK:  mov     w2, #3
428 ; CHECK:  mov     w3, #4
429 ; CHECK:  mov     w4, #5
430 ; CHECK:  mov     w5, #6
431 ; CHECK:  mov     w6, #7
432 ; CHECK:  mov     w7, #8
433 ; CHECK:  str     xzr, [sp]
434 ; CHECK:  bl      _params_in_reg2
435 ; Restore return values for return from this function.
436 ; CHECK:  mov     x0, x20
437 ; CHECK:  mov     x1, x22
438 ; CHECK:  mov     x2, x23
439 ; CHECK:  mov     x3, x24
440 ; CHECK:  mov     x4, x25
441 ; CHECK:  mov     x5, x26
442 ; CHECK:  mov     x6, x27
443 ; CHECK:  mov     x21, x19
444 ; CHECK:  mov     x7, x28
445 ; CHECK:  ldp     x29, x30, [sp, #96]             ; 16-byte Folded Reload
446 ; CHECK:  ldr     x28, [sp, #16]                  ; 8-byte Folded Reload
447 ; CHECK:  ldp     x20, x19, [sp, #80]             ; 16-byte Folded Reload
448 ; CHECK:  ldp     x23, x22, [sp, #64]             ; 16-byte Folded Reload
449 ; CHECK:  ldp     x25, x24, [sp, #48]             ; 16-byte Folded Reload
450 ; CHECK:  ldp     x27, x26, [sp, #32]             ; 16-byte Folded Reload
451 ; CHECK:  add     sp, sp, #112
452 ; CHECK:  ret
453 define swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err) {
454   %error_ptr_ref = alloca swifterror ptr, align 8
455   store ptr null, ptr %error_ptr_ref
456   call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr  null, ptr nocapture swifterror %error_ptr_ref)
457   %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, ptr  %8, ptr nocapture swifterror %err)
458   call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, ptr  null, ptr nocapture swifterror %error_ptr_ref)
459   ret { i64, i64, i64, i64, i64, i64, i64, i64 } %val
462 declare swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, ptr , ptr nocapture swifterror %err)
464 declare void @acallee(ptr)
466 ; Make sure we don't tail call if the caller returns a swifterror value. We
467 ; would have to move into the swifterror register before the tail call.
468 ; CHECK-LABEL: tailcall_from_swifterror:
469 ; CHECK-NOT: b _acallee
470 ; CHECK: bl _acallee
472 define swiftcc void @tailcall_from_swifterror(ptr swifterror %error_ptr_ref) {
473 entry:
474   tail call void @acallee(ptr null)
475   ret void
478 ; CHECK: tailcall_from_swifterror2
479 ; CHECK-NOT: b _simple_fn
480 ; CHECK: bl _simple_fn
481 declare void @simple_fn()
482 define swiftcc void @tailcall_from_swifterror2(ptr swifterror %error_ptr_ref) {
483   tail call void @simple_fn()
484   ret void
487 declare swiftcc void @foo2(ptr swifterror)
488 ; CHECK-LABEL: testAssign
489 ; CHECK: mov      x21, xzr
490 ; CHECK: bl      _foo2
491 ; CHECK: mov      x0, x21
493 define swiftcc ptr @testAssign(ptr %error_ref) {
494 entry:
495   %error_ptr = alloca swifterror ptr
496   store ptr null, ptr %error_ptr
497   call swiftcc void @foo2(ptr swifterror %error_ptr)
498   br label %a
501   %error = load ptr, ptr %error_ptr
502   ret ptr %error
505 ; foo takes a swifterror parameter. We should be able to see that even when
506 ; it isn't explicitly on the call.
507 define float @swifterror_param_not_on_call(ptr %error_ref) {
508 ; CHECK-LABEL: swifterror_param_not_on_call:
509 ; CHECK: mov [[ID:x[0-9]+]], x0
510 ; CHECK: bl {{.*}}foo
511 ; CHECK: mov x0, x21
512 ; CHECK: cbnz x21
513 ; Access part of the error object and save it to error_ref
514 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
515 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
516 ; CHECK: bl {{.*}}free
518 entry:
519   %error_ptr_ref = alloca swifterror ptr
520   store ptr null, ptr %error_ptr_ref
521   %call = call float @foo(ptr %error_ptr_ref)
522   %error_from_foo = load ptr, ptr %error_ptr_ref
523   %had_error_from_foo = icmp ne ptr %error_from_foo, null
524   br i1 %had_error_from_foo, label %handler, label %cont
525 cont:
526   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
527   %t = load i8, ptr %v1
528   store i8 %t, ptr %error_ref
529   br label %handler
530 handler:
531   call void @free(ptr %error_from_foo)
532   ret float 1.0
535 ; foo_sret takes an sret parameter and a swifterror parameter. We should be
536 ; able to see that, even if it's not explicitly on the call.
537 define float @swifterror_param_not_on_call2(ptr %error_ref) {
538 ; CHECK-LABEL: swifterror_param_not_on_call2:
539 ; CHECK: mov [[ID:x[0-9]+]], x0
540 ; CHECK: mov [[ZERO:x[0-9]+]], xzr
541 ; CHECK: bl {{.*}}foo_sret
542 ; CHECK: mov x0, x21
543 ; CHECK: cbnz x21
544 ; Access part of the error object and save it to error_ref
545 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
546 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
547 ; CHECK: bl {{.*}}free
549 entry:
550   %s = alloca %struct.S, align 8
551   %error_ptr_ref = alloca swifterror ptr
552   store ptr null, ptr %error_ptr_ref
553   call void @foo_sret(ptr %s, i32 1, ptr %error_ptr_ref)
554   %error_from_foo = load ptr, ptr %error_ptr_ref
555   %had_error_from_foo = icmp ne ptr %error_from_foo, null
556   br i1 %had_error_from_foo, label %handler, label %cont
557 cont:
558   %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1
559   %t = load i8, ptr %v1
560   store i8 %t, ptr %error_ref
561   br label %handler
562 handler:
563   call void @free(ptr %error_from_foo)
564   ret float 1.0