Files
clang-p2996/llvm/test/CodeGen/ARM/swifterror.ll
Amaury Séchet 06fad8bc05 [DAGCombine] Add node in the worklist in topological order in CombineTo
This is part of an ongoing effort toward making DAGCombine process the nodes in topological order.

This is able to discover a couple of new optimizations, but also causes a couple of regression. I nevertheless chose to submit this patch for review as to start the discussion with people working on the backend so we can find a good way forward.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D124743
2022-05-07 16:24:31 +00:00

1390 lines
50 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s
; RUN: llc -verify-machineinstrs -O0 < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s
; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-linux-androideabi | FileCheck --check-prefix=CHECK-ANDROID %s
declare i8* @malloc(i64)
declare void @free(i8*)
%swift_error = type { i64, i8 }
%struct.S = type { i32, i32, i32, i32, i32, i32 }
; This tests the basic usage of a swifterror parameter. "foo" is the function
; that takes a swifterror parameter and "caller" is the caller of "foo".
define float @foo(%swift_error** swifterror %error_ptr_ref) {
; CHECK-APPLE-LABEL: foo:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {lr}
; CHECK-APPLE-NEXT: mov r0, #16
; CHECK-APPLE-NEXT: mov r1, #0
; CHECK-APPLE-NEXT: bl _malloc
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: strb r0, [r8, #8]
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: pop {lr}
; CHECK-APPLE-NEXT: bx lr
;
; CHECK-O0-LABEL: foo:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: mov r0, #16
; CHECK-O0-NEXT: mov r1, #0
; CHECK-O0-NEXT: bl _malloc
; CHECK-O0-NEXT: mov r1, r0
; CHECK-O0-NEXT: mov r8, r1
; CHECK-O0-NEXT: mov r0, #1
; CHECK-O0-NEXT: strb r0, [r1, #8]
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: foo:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r11, lr}
; CHECK-ANDROID-NEXT: push {r11, lr}
; CHECK-ANDROID-NEXT: mov r0, #16
; CHECK-ANDROID-NEXT: mov r1, #0
; CHECK-ANDROID-NEXT: bl malloc
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: strb r0, [r8, #8]
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: pop {r11, pc}
entry:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
store %swift_error* %call.0, %swift_error** %error_ptr_ref
%tmp = getelementptr inbounds i8, i8* %call, i64 8
store i8 1, i8* %tmp
ret float 1.0
}
; "caller" calls "foo" that takes a swifterror parameter.
define float @caller(i8* %error_ref) {
; CHECK-APPLE-LABEL: caller:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r8, lr}
; CHECK-APPLE-NEXT: sub sp, sp, #4
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: bl _foo
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: cmp r8, #0
; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8]
; CHECK-APPLE-NEXT: strbeq r1, [r4]
; CHECK-APPLE-NEXT: bl _free
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: add sp, sp, #4
; CHECK-APPLE-NEXT: pop {r4, r8, pc}
;
; CHECK-O0-LABEL: caller:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: sub sp, sp, #12
; CHECK-O0-NEXT: @ implicit-def: $r1
; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: bl _foo
; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: movw r0, #0
; CHECK-O0-NEXT: cmp r8, r0
; CHECK-O0-NEXT: bne LBB1_2
; CHECK-O0-NEXT: @ %bb.1: @ %cont
; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldrb r0, [r0, #8]
; CHECK-O0-NEXT: strb r0, [r1]
; CHECK-O0-NEXT: LBB1_2: @ %handler
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: bl _free
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: caller:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: .pad #8
; CHECK-ANDROID-NEXT: sub sp, sp, #8
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: bl foo
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: cmp r8, #0
; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8]
; CHECK-ANDROID-NEXT: strbeq r1, [r4]
; CHECK-ANDROID-NEXT: bl free
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: add sp, sp, #8
; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc}
; Access part of the error object and save it to error_ref
; spill r0
; reload r0
entry:
%error_ptr_ref = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr_ref
%call = call float @foo(%swift_error** swifterror %error_ptr_ref)
%error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
%had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
%tmp = bitcast %swift_error* %error_from_foo to i8*
br i1 %had_error_from_foo, label %handler, label %cont
cont:
%v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
%t = load i8, i8* %v1
store i8 %t, i8* %error_ref
br label %handler
handler:
call void @free(i8* %tmp)
ret float 1.0
}
; "caller2" is the caller of "foo", it calls "foo" inside a loop.
define float @caller2(i8* %error_ref) {
; CHECK-APPLE-LABEL: caller2:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r8, lr}
; CHECK-APPLE-NEXT: vpush {d8}
; CHECK-APPLE-NEXT: sub sp, sp, #4
; CHECK-APPLE-NEXT: vmov.f32 s16, #1.000000e+00
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: LBB2_1: @ %bb_loop
; CHECK-APPLE-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: bl _foo
; CHECK-APPLE-NEXT: cmp r8, #0
; CHECK-APPLE-NEXT: bne LBB2_4
; CHECK-APPLE-NEXT: @ %bb.2: @ %cont
; CHECK-APPLE-NEXT: @ in Loop: Header=BB2_1 Depth=1
; CHECK-APPLE-NEXT: vmov s0, r0
; CHECK-APPLE-NEXT: vcmp.f32 s0, s16
; CHECK-APPLE-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-APPLE-NEXT: ble LBB2_1
; CHECK-APPLE-NEXT: @ %bb.3: @ %bb_end
; CHECK-APPLE-NEXT: ldrb r0, [r8, #8]
; CHECK-APPLE-NEXT: strb r0, [r4]
; CHECK-APPLE-NEXT: LBB2_4: @ %handler
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: bl _free
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: add sp, sp, #4
; CHECK-APPLE-NEXT: vpop {d8}
; CHECK-APPLE-NEXT: pop {r4, r8, pc}
;
; CHECK-O0-LABEL: caller2:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: sub sp, sp, #16
; CHECK-O0-NEXT: @ implicit-def: $r1
; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill
; CHECK-O0-NEXT: LBB2_1: @ %bb_loop
; CHECK-O0-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: bl _foo
; CHECK-O0-NEXT: vmov s0, r0
; CHECK-O0-NEXT: vstr s0, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: movw r0, #0
; CHECK-O0-NEXT: cmp r8, r0
; CHECK-O0-NEXT: bne LBB2_4
; CHECK-O0-NEXT: @ %bb.2: @ %cont
; CHECK-O0-NEXT: @ in Loop: Header=BB2_1 Depth=1
; CHECK-O0-NEXT: vldr s0, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: vmov.f32 s2, #1.000000e+00
; CHECK-O0-NEXT: vcmp.f32 s0, s2
; CHECK-O0-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-O0-NEXT: ble LBB2_1
; CHECK-O0-NEXT: @ %bb.3: @ %bb_end
; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldrb r0, [r0, #8]
; CHECK-O0-NEXT: strb r0, [r1]
; CHECK-O0-NEXT: LBB2_4: @ %handler
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: bl _free
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: caller2:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: .vsave {d8}
; CHECK-ANDROID-NEXT: vpush {d8}
; CHECK-ANDROID-NEXT: .pad #8
; CHECK-ANDROID-NEXT: sub sp, sp, #8
; CHECK-ANDROID-NEXT: vmov.f32 s16, #1.000000e+00
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: .LBB2_1: @ %bb_loop
; CHECK-ANDROID-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: bl foo
; CHECK-ANDROID-NEXT: cmp r8, #0
; CHECK-ANDROID-NEXT: bne .LBB2_4
; CHECK-ANDROID-NEXT: @ %bb.2: @ %cont
; CHECK-ANDROID-NEXT: @ in Loop: Header=BB2_1 Depth=1
; CHECK-ANDROID-NEXT: vmov s0, r0
; CHECK-ANDROID-NEXT: vcmp.f32 s0, s16
; CHECK-ANDROID-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-ANDROID-NEXT: ble .LBB2_1
; CHECK-ANDROID-NEXT: @ %bb.3: @ %bb_end
; CHECK-ANDROID-NEXT: ldrb r0, [r8, #8]
; CHECK-ANDROID-NEXT: strb r0, [r4]
; CHECK-ANDROID-NEXT: .LBB2_4: @ %handler
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: bl free
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: add sp, sp, #8
; CHECK-ANDROID-NEXT: vpop {d8}
; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc}
; Access part of the error object and save it to error_ref
; spill r0
; reload r0
entry:
%error_ptr_ref = alloca swifterror %swift_error*
br label %bb_loop
bb_loop:
store %swift_error* null, %swift_error** %error_ptr_ref
%call = call float @foo(%swift_error** swifterror %error_ptr_ref)
%error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
%had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
%tmp = bitcast %swift_error* %error_from_foo to i8*
br i1 %had_error_from_foo, label %handler, label %cont
cont:
%cmp = fcmp ogt float %call, 1.000000e+00
br i1 %cmp, label %bb_end, label %bb_loop
bb_end:
%v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
%t = load i8, i8* %v1
store i8 %t, i8* %error_ref
br label %handler
handler:
call void @free(i8* %tmp)
ret float 1.0
}
; "foo_if" is a function that takes a swifterror parameter, it sets swifterror
; under a certain condition.
define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) {
; CHECK-APPLE-LABEL: foo_if:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {lr}
; CHECK-APPLE-NEXT: cmp r0, #0
; CHECK-APPLE-NEXT: beq LBB3_2
; CHECK-APPLE-NEXT: @ %bb.1: @ %gen_error
; CHECK-APPLE-NEXT: mov r0, #16
; CHECK-APPLE-NEXT: mov r1, #0
; CHECK-APPLE-NEXT: bl _malloc
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: vmov.f32 s0, #1.000000e+00
; CHECK-APPLE-NEXT: strb r0, [r8, #8]
; CHECK-APPLE-NEXT: b LBB3_3
; CHECK-APPLE-NEXT: LBB3_2:
; CHECK-APPLE-NEXT: vldr s0, LCPI3_0
; CHECK-APPLE-NEXT: LBB3_3: @ %common.ret
; CHECK-APPLE-NEXT: vmov r0, s0
; CHECK-APPLE-NEXT: pop {lr}
; CHECK-APPLE-NEXT: bx lr
; CHECK-APPLE-NEXT: .p2align 2
; CHECK-APPLE-NEXT: @ %bb.4:
; CHECK-APPLE-NEXT: .data_region
; CHECK-APPLE-NEXT: LCPI3_0:
; CHECK-APPLE-NEXT: .long 0x00000000 @ float 0
; CHECK-APPLE-NEXT: .end_data_region
;
; CHECK-O0-LABEL: foo_if:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: sub sp, sp, #4
; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: cmp r0, #0
; CHECK-O0-NEXT: beq LBB3_2
; CHECK-O0-NEXT: @ %bb.1: @ %gen_error
; CHECK-O0-NEXT: mov r0, #16
; CHECK-O0-NEXT: mov r1, #0
; CHECK-O0-NEXT: bl _malloc
; CHECK-O0-NEXT: mov r1, r0
; CHECK-O0-NEXT: mov r8, r1
; CHECK-O0-NEXT: mov r0, #1
; CHECK-O0-NEXT: strb r0, [r1, #8]
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, pc}
; CHECK-O0-NEXT: LBB3_2: @ %normal
; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: mov r0, #0
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: foo_if:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r11, lr}
; CHECK-ANDROID-NEXT: push {r11, lr}
; CHECK-ANDROID-NEXT: cmp r0, #0
; CHECK-ANDROID-NEXT: beq .LBB3_2
; CHECK-ANDROID-NEXT: @ %bb.1: @ %gen_error
; CHECK-ANDROID-NEXT: mov r0, #16
; CHECK-ANDROID-NEXT: mov r1, #0
; CHECK-ANDROID-NEXT: bl malloc
; CHECK-ANDROID-NEXT: vmov.f32 s0, #1.000000e+00
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: strb r0, [r8, #8]
; CHECK-ANDROID-NEXT: vmov r0, s0
; CHECK-ANDROID-NEXT: pop {r11, pc}
; CHECK-ANDROID-NEXT: .LBB3_2:
; CHECK-ANDROID-NEXT: vldr s0, .LCPI3_0
; CHECK-ANDROID-NEXT: vmov r0, s0
; CHECK-ANDROID-NEXT: pop {r11, pc}
; CHECK-ANDROID-NEXT: .p2align 2
; CHECK-ANDROID-NEXT: @ %bb.3:
; CHECK-ANDROID-NEXT: .LCPI3_0:
; CHECK-ANDROID-NEXT: .long 0x00000000 @ float 0
; spill to stack
; reload from stack
entry:
%cond = icmp ne i32 %cc, 0
br i1 %cond, label %gen_error, label %normal
gen_error:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
store %swift_error* %call.0, %swift_error** %error_ptr_ref
%tmp = getelementptr inbounds i8, i8* %call, i64 8
store i8 1, i8* %tmp
ret float 1.0
normal:
ret float 0.0
}
; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror
; under a certain condition inside a loop.
define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) {
; CHECK-APPLE-LABEL: foo_loop:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r5, lr}
; CHECK-APPLE-NEXT: vpush {d8, d9}
; CHECK-APPLE-NEXT: vmov.f32 s18, #1.000000e+00
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: vmov s16, r1
; CHECK-APPLE-NEXT: mov r5, #1
; CHECK-APPLE-NEXT: b LBB4_2
; CHECK-APPLE-NEXT: LBB4_1: @ %bb_cont
; CHECK-APPLE-NEXT: @ in Loop: Header=BB4_2 Depth=1
; CHECK-APPLE-NEXT: vcmp.f32 s16, s18
; CHECK-APPLE-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-APPLE-NEXT: bgt LBB4_4
; CHECK-APPLE-NEXT: LBB4_2: @ %bb_loop
; CHECK-APPLE-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-APPLE-NEXT: cmp r4, #0
; CHECK-APPLE-NEXT: beq LBB4_1
; CHECK-APPLE-NEXT: @ %bb.3: @ %gen_error
; CHECK-APPLE-NEXT: @ in Loop: Header=BB4_2 Depth=1
; CHECK-APPLE-NEXT: mov r0, #16
; CHECK-APPLE-NEXT: mov r1, #0
; CHECK-APPLE-NEXT: bl _malloc
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: strb r5, [r0, #8]
; CHECK-APPLE-NEXT: b LBB4_1
; CHECK-APPLE-NEXT: LBB4_4: @ %bb_end
; CHECK-APPLE-NEXT: mov r0, #0
; CHECK-APPLE-NEXT: vpop {d8, d9}
; CHECK-APPLE-NEXT: pop {r4, r5, pc}
;
; CHECK-O0-LABEL: foo_loop:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: sub sp, sp, #20
; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill
; CHECK-O0-NEXT: vmov s0, r1
; CHECK-O0-NEXT: vstr s0, [r7, #-8] @ 4-byte Spill
; CHECK-O0-NEXT: str r8, [r7, #-4] @ 4-byte Spill
; CHECK-O0-NEXT: b LBB4_1
; CHECK-O0-NEXT: LBB4_1: @ %bb_loop
; CHECK-O0-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [r7, #-4] @ 4-byte Reload
; CHECK-O0-NEXT: cmp r1, #0
; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: beq LBB4_3
; CHECK-O0-NEXT: @ %bb.2: @ %gen_error
; CHECK-O0-NEXT: @ in Loop: Header=BB4_1 Depth=1
; CHECK-O0-NEXT: mov r0, #16
; CHECK-O0-NEXT: mov r1, #0
; CHECK-O0-NEXT: bl _malloc
; CHECK-O0-NEXT: mov r2, r0
; CHECK-O0-NEXT: movw r1, #1
; CHECK-O0-NEXT: strb r1, [r2, #8]
; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: LBB4_3: @ %bb_cont
; CHECK-O0-NEXT: @ in Loop: Header=BB4_1 Depth=1
; CHECK-O0-NEXT: vldr s0, [r7, #-8] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: vmov.f32 s2, #1.000000e+00
; CHECK-O0-NEXT: vcmp.f32 s0, s2
; CHECK-O0-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-O0-NEXT: str r0, [r7, #-4] @ 4-byte Spill
; CHECK-O0-NEXT: ble LBB4_1
; CHECK-O0-NEXT: @ %bb.4: @ %bb_end
; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: mov r0, #0
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: foo_loop:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r5, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r5, r11, lr}
; CHECK-ANDROID-NEXT: .vsave {d8, d9}
; CHECK-ANDROID-NEXT: vpush {d8, d9}
; CHECK-ANDROID-NEXT: vmov.f32 s18, #1.000000e+00
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: vmov s16, r1
; CHECK-ANDROID-NEXT: mov r5, #1
; CHECK-ANDROID-NEXT: b .LBB4_2
; CHECK-ANDROID-NEXT: .LBB4_1: @ %bb_cont
; CHECK-ANDROID-NEXT: @ in Loop: Header=BB4_2 Depth=1
; CHECK-ANDROID-NEXT: vcmp.f32 s16, s18
; CHECK-ANDROID-NEXT: vmrs APSR_nzcv, fpscr
; CHECK-ANDROID-NEXT: bgt .LBB4_4
; CHECK-ANDROID-NEXT: .LBB4_2: @ %bb_loop
; CHECK-ANDROID-NEXT: @ =>This Inner Loop Header: Depth=1
; CHECK-ANDROID-NEXT: cmp r4, #0
; CHECK-ANDROID-NEXT: beq .LBB4_1
; CHECK-ANDROID-NEXT: @ %bb.3: @ %gen_error
; CHECK-ANDROID-NEXT: @ in Loop: Header=BB4_2 Depth=1
; CHECK-ANDROID-NEXT: mov r0, #16
; CHECK-ANDROID-NEXT: mov r1, #0
; CHECK-ANDROID-NEXT: bl malloc
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: strb r5, [r0, #8]
; CHECK-ANDROID-NEXT: b .LBB4_1
; CHECK-ANDROID-NEXT: .LBB4_4: @ %bb_end
; CHECK-ANDROID-NEXT: mov r0, #0
; CHECK-ANDROID-NEXT: vpop {d8, d9}
; CHECK-ANDROID-NEXT: pop {r4, r5, r11, pc}
; swifterror is kept in a register
; spill r0
; reload from stack
entry:
br label %bb_loop
bb_loop:
%cond = icmp ne i32 %cc, 0
br i1 %cond, label %gen_error, label %bb_cont
gen_error:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
store %swift_error* %call.0, %swift_error** %error_ptr_ref
%tmp = getelementptr inbounds i8, i8* %call, i64 8
store i8 1, i8* %tmp
br label %bb_cont
bb_cont:
%cmp = fcmp ogt float %cc2, 1.000000e+00
br i1 %cmp, label %bb_end, label %bb_loop
bb_end:
ret float 0.0
}
; "foo_sret" is a function that takes a swifterror parameter, it also has a sret
; parameter.
define void @foo_sret(%struct.S* sret(%struct.S) %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) {
; CHECK-APPLE-LABEL: foo_sret:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r5, lr}
; CHECK-APPLE-NEXT: mov r4, r1
; CHECK-APPLE-NEXT: mov r5, r0
; CHECK-APPLE-NEXT: mov r0, #16
; CHECK-APPLE-NEXT: mov r1, #0
; CHECK-APPLE-NEXT: bl _malloc
; CHECK-APPLE-NEXT: mov r1, #1
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: strb r1, [r0, #8]
; CHECK-APPLE-NEXT: str r4, [r5, #4]
; CHECK-APPLE-NEXT: pop {r4, r5, pc}
;
; CHECK-O0-LABEL: foo_sret:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: sub sp, sp, #8
; CHECK-O0-NEXT: str r1, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: mov r0, #16
; CHECK-O0-NEXT: mov r1, #0
; CHECK-O0-NEXT: bl _malloc
; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: mov r3, r0
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: mov r8, r3
; CHECK-O0-NEXT: mov r2, #1
; CHECK-O0-NEXT: strb r2, [r3, #8]
; CHECK-O0-NEXT: str r1, [r0, #4]
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: foo_sret:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r5, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r5, r11, lr}
; CHECK-ANDROID-NEXT: mov r4, r1
; CHECK-ANDROID-NEXT: mov r5, r0
; CHECK-ANDROID-NEXT: mov r0, #16
; CHECK-ANDROID-NEXT: mov r1, #0
; CHECK-ANDROID-NEXT: bl malloc
; CHECK-ANDROID-NEXT: mov r1, #1
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: strb r1, [r0, #8]
; CHECK-ANDROID-NEXT: str r4, [r5, #4]
; CHECK-ANDROID-NEXT: pop {r4, r5, r11, pc}
; spill to stack: sret and val1
; reload from stack: sret and val1
entry:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
store %swift_error* %call.0, %swift_error** %error_ptr_ref
%tmp = getelementptr inbounds i8, i8* %call, i64 8
store i8 1, i8* %tmp
%v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1
store i32 %val1, i32* %v2
ret void
}
; "caller3" calls "foo_sret" that takes a swifterror parameter.
define float @caller3(i8* %error_ref) {
; CHECK-APPLE-LABEL: caller3:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r7, r8, lr}
; CHECK-APPLE-NEXT: add r7, sp, #8
; CHECK-APPLE-NEXT: sub sp, sp, #32
; CHECK-APPLE-NEXT: bfc sp, #0, #3
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: add r0, sp, #8
; CHECK-APPLE-NEXT: mov r1, #1
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: bl _foo_sret
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: cmp r8, #0
; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8]
; CHECK-APPLE-NEXT: strbeq r1, [r4]
; CHECK-APPLE-NEXT: bl _free
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: sub sp, r7, #8
; CHECK-APPLE-NEXT: pop {r4, r7, r8, pc}
;
; CHECK-O0-LABEL: caller3:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: sub sp, sp, #44
; CHECK-O0-NEXT: bfc sp, #0, #3
; CHECK-O0-NEXT: @ implicit-def: $r1
; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: add r0, sp, #16
; CHECK-O0-NEXT: mov r1, #1
; CHECK-O0-NEXT: bl _foo_sret
; CHECK-O0-NEXT: str r8, [sp, #8] @ 4-byte Spill
; CHECK-O0-NEXT: movw r0, #0
; CHECK-O0-NEXT: cmp r8, r0
; CHECK-O0-NEXT: bne LBB6_2
; CHECK-O0-NEXT: @ %bb.1: @ %cont
; CHECK-O0-NEXT: ldr r1, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: ldrb r0, [r0, #8]
; CHECK-O0-NEXT: strb r0, [r1]
; CHECK-O0-NEXT: LBB6_2: @ %handler
; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: bl _free
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: caller3:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: .pad #32
; CHECK-ANDROID-NEXT: sub sp, sp, #32
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: add r0, sp, #8
; CHECK-ANDROID-NEXT: mov r1, #1
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: bl foo_sret
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: cmp r8, #0
; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8]
; CHECK-ANDROID-NEXT: strbeq r1, [r4]
; CHECK-ANDROID-NEXT: bl free
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: add sp, sp, #32
; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc}
; Access part of the error object and save it to error_ref
; Access part of the error object and save it to error_ref
entry:
%s = alloca %struct.S, align 8
%error_ptr_ref = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr_ref
call void @foo_sret(%struct.S* sret(%struct.S) %s, i32 1, %swift_error** swifterror %error_ptr_ref)
%error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
%had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
%tmp = bitcast %swift_error* %error_from_foo to i8*
br i1 %had_error_from_foo, label %handler, label %cont
cont:
%v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
%t = load i8, i8* %v1
store i8 %t, i8* %error_ref
br label %handler
handler:
call void @free(i8* %tmp)
ret float 1.0
}
; "foo_vararg" is a function that takes a swifterror parameter, it also has
; variable number of arguments.
declare void @llvm.va_start(i8*) nounwind
define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) {
; CHECK-APPLE-LABEL: foo_vararg:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: sub sp, sp, #16
; CHECK-APPLE-NEXT: push {r7, lr}
; CHECK-APPLE-NEXT: mov r7, sp
; CHECK-APPLE-NEXT: sub sp, sp, #24
; CHECK-APPLE-NEXT: bfc sp, #0, #3
; CHECK-APPLE-NEXT: add r8, r7, #8
; CHECK-APPLE-NEXT: stm r8, {r0, r1, r2, r3}
; CHECK-APPLE-NEXT: mov r0, #16
; CHECK-APPLE-NEXT: mov r1, #0
; CHECK-APPLE-NEXT: bl _malloc
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: strb r0, [r8, #8]
; CHECK-APPLE-NEXT: add r0, r7, #8
; CHECK-APPLE-NEXT: add r0, r0, #4
; CHECK-APPLE-NEXT: ldr r2, [r7, #8]
; CHECK-APPLE-NEXT: ldr r1, [r0], #4
; CHECK-APPLE-NEXT: ldr r3, [r0], #4
; CHECK-APPLE-NEXT: str r0, [sp, #16]
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: str r2, [sp, #12]
; CHECK-APPLE-NEXT: str r1, [sp, #8]
; CHECK-APPLE-NEXT: str r3, [sp, #4]
; CHECK-APPLE-NEXT: mov sp, r7
; CHECK-APPLE-NEXT: pop {r7, lr}
; CHECK-APPLE-NEXT: add sp, sp, #16
; CHECK-APPLE-NEXT: bx lr
;
; CHECK-O0-LABEL: foo_vararg:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: sub sp, sp, #16
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: sub sp, sp, #24
; CHECK-O0-NEXT: bfc sp, #0, #3
; CHECK-O0-NEXT: str r3, [r7, #20]
; CHECK-O0-NEXT: str r2, [r7, #16]
; CHECK-O0-NEXT: str r1, [r7, #12]
; CHECK-O0-NEXT: str r0, [r7, #8]
; CHECK-O0-NEXT: mov r0, #16
; CHECK-O0-NEXT: mov r1, #0
; CHECK-O0-NEXT: bl _malloc
; CHECK-O0-NEXT: mov r1, r0
; CHECK-O0-NEXT: mov r8, r1
; CHECK-O0-NEXT: mov r0, #1
; CHECK-O0-NEXT: strb r0, [r1, #8]
; CHECK-O0-NEXT: add r0, r7, #8
; CHECK-O0-NEXT: str r0, [sp, #16]
; CHECK-O0-NEXT: ldr r0, [sp, #16]
; CHECK-O0-NEXT: add r1, r0, #4
; CHECK-O0-NEXT: str r1, [sp, #16]
; CHECK-O0-NEXT: ldr r0, [r0]
; CHECK-O0-NEXT: str r0, [sp, #12]
; CHECK-O0-NEXT: ldr r0, [sp, #16]
; CHECK-O0-NEXT: add r1, r0, #4
; CHECK-O0-NEXT: str r1, [sp, #16]
; CHECK-O0-NEXT: ldr r0, [r0]
; CHECK-O0-NEXT: str r0, [sp, #8]
; CHECK-O0-NEXT: ldr r0, [sp, #16]
; CHECK-O0-NEXT: add r1, r0, #4
; CHECK-O0-NEXT: str r1, [sp, #16]
; CHECK-O0-NEXT: ldr r0, [r0]
; CHECK-O0-NEXT: str r0, [sp, #4]
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, lr}
; CHECK-O0-NEXT: add sp, sp, #16
; CHECK-O0-NEXT: bx lr
;
; CHECK-ANDROID-LABEL: foo_vararg:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .pad #16
; CHECK-ANDROID-NEXT: sub sp, sp, #16
; CHECK-ANDROID-NEXT: .save {r11, lr}
; CHECK-ANDROID-NEXT: push {r11, lr}
; CHECK-ANDROID-NEXT: .pad #24
; CHECK-ANDROID-NEXT: sub sp, sp, #24
; CHECK-ANDROID-NEXT: add r8, sp, #32
; CHECK-ANDROID-NEXT: stm r8, {r0, r1, r2, r3}
; CHECK-ANDROID-NEXT: mov r0, #16
; CHECK-ANDROID-NEXT: mov r1, #0
; CHECK-ANDROID-NEXT: bl malloc
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: strb r0, [r8, #8]
; CHECK-ANDROID-NEXT: add r0, sp, #32
; CHECK-ANDROID-NEXT: orr r0, r0, #4
; CHECK-ANDROID-NEXT: ldr r2, [sp, #32]
; CHECK-ANDROID-NEXT: ldr r1, [r0], #4
; CHECK-ANDROID-NEXT: ldr r3, [r0], #4
; CHECK-ANDROID-NEXT: str r0, [sp, #16]
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: str r2, [sp, #12]
; CHECK-ANDROID-NEXT: str r1, [sp, #8]
; CHECK-ANDROID-NEXT: str r3, [sp, #4]
; CHECK-ANDROID-NEXT: add sp, sp, #24
; CHECK-ANDROID-NEXT: pop {r11, lr}
; CHECK-ANDROID-NEXT: add sp, sp, #16
; CHECK-ANDROID-NEXT: bx lr
entry:
%call = call i8* @malloc(i64 16)
%call.0 = bitcast i8* %call to %swift_error*
store %swift_error* %call.0, %swift_error** %error_ptr_ref
%tmp = getelementptr inbounds i8, i8* %call, i64 8
store i8 1, i8* %tmp
%args = alloca i8*, align 8
%a10 = alloca i32, align 4
%a11 = alloca i32, align 4
%a12 = alloca i32, align 4
%v10 = bitcast i8** %args to i8*
call void @llvm.va_start(i8* %v10)
%v11 = va_arg i8** %args, i32
store i32 %v11, i32* %a10, align 4
%v12 = va_arg i8** %args, i32
store i32 %v12, i32* %a11, align 4
%v13 = va_arg i8** %args, i32
store i32 %v13, i32* %a12, align 4
ret float 1.0
}
; "caller4" calls "foo_vararg" that takes a swifterror parameter.
define float @caller4(i8* %error_ref) {
; CHECK-APPLE-LABEL: caller4:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, r8, lr}
; CHECK-APPLE-NEXT: sub sp, sp, #16
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: mov r0, #11
; CHECK-APPLE-NEXT: str r0, [sp, #4]
; CHECK-APPLE-NEXT: mov r0, #10
; CHECK-APPLE-NEXT: str r0, [sp, #8]
; CHECK-APPLE-NEXT: mov r0, #12
; CHECK-APPLE-NEXT: str r0, [sp]
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: mov r0, #10
; CHECK-APPLE-NEXT: mov r1, #11
; CHECK-APPLE-NEXT: mov r2, #12
; CHECK-APPLE-NEXT: bl _foo_vararg
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: cmp r8, #0
; CHECK-APPLE-NEXT: ldrbeq r1, [r0, #8]
; CHECK-APPLE-NEXT: strbeq r1, [r4]
; CHECK-APPLE-NEXT: bl _free
; CHECK-APPLE-NEXT: mov r0, #1065353216
; CHECK-APPLE-NEXT: add sp, sp, #16
; CHECK-APPLE-NEXT: pop {r4, r8, pc}
;
; CHECK-O0-LABEL: caller4:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: sub sp, sp, #24
; CHECK-O0-NEXT: @ implicit-def: $r1
; CHECK-O0-NEXT: str r0, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: mov r0, #10
; CHECK-O0-NEXT: str r0, [r7, #-12]
; CHECK-O0-NEXT: mov r0, #11
; CHECK-O0-NEXT: str r0, [sp, #12]
; CHECK-O0-NEXT: mov r0, #12
; CHECK-O0-NEXT: str r0, [sp, #8]
; CHECK-O0-NEXT: ldr r0, [r7, #-12]
; CHECK-O0-NEXT: ldr r1, [sp, #12]
; CHECK-O0-NEXT: ldr r2, [sp, #8]
; CHECK-O0-NEXT: bl _foo_vararg
; CHECK-O0-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: movw r0, #0
; CHECK-O0-NEXT: cmp r8, r0
; CHECK-O0-NEXT: bne LBB8_2
; CHECK-O0-NEXT: @ %bb.1: @ %cont
; CHECK-O0-NEXT: ldr r1, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldrb r0, [r0, #8]
; CHECK-O0-NEXT: strb r0, [r1]
; CHECK-O0-NEXT: LBB8_2: @ %handler
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: bl _free
; CHECK-O0-NEXT: mov r0, #1065353216
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: caller4:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r8, r11, lr}
; CHECK-ANDROID-NEXT: .pad #16
; CHECK-ANDROID-NEXT: sub sp, sp, #16
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: mov r0, #11
; CHECK-ANDROID-NEXT: str r0, [sp, #4]
; CHECK-ANDROID-NEXT: mov r0, #10
; CHECK-ANDROID-NEXT: str r0, [sp, #8]
; CHECK-ANDROID-NEXT: mov r0, #12
; CHECK-ANDROID-NEXT: str r0, [sp]
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: mov r0, #10
; CHECK-ANDROID-NEXT: mov r1, #11
; CHECK-ANDROID-NEXT: mov r2, #12
; CHECK-ANDROID-NEXT: bl foo_vararg
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: cmp r8, #0
; CHECK-ANDROID-NEXT: ldrbeq r1, [r0, #8]
; CHECK-ANDROID-NEXT: strbeq r1, [r4]
; CHECK-ANDROID-NEXT: bl free
; CHECK-ANDROID-NEXT: mov r0, #1065353216
; CHECK-ANDROID-NEXT: add sp, sp, #16
; CHECK-ANDROID-NEXT: pop {r4, r8, r11, pc}
; Access part of the error object and save it to error_ref
entry:
%error_ptr_ref = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr_ref
%a10 = alloca i32, align 4
%a11 = alloca i32, align 4
%a12 = alloca i32, align 4
store i32 10, i32* %a10, align 4
store i32 11, i32* %a11, align 4
store i32 12, i32* %a12, align 4
%v10 = load i32, i32* %a10, align 4
%v11 = load i32, i32* %a11, align 4
%v12 = load i32, i32* %a12, align 4
%call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12)
%error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref
%had_error_from_foo = icmp ne %swift_error* %error_from_foo, null
%tmp = bitcast %swift_error* %error_from_foo to i8*
br i1 %had_error_from_foo, label %handler, label %cont
cont:
%v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1
%t = load i8, i8* %v1
store i8 %t, i8* %error_ref
br label %handler
handler:
call void @free(i8* %tmp)
ret float 1.0
}
; Check that we don't blow up on tail calling swifterror argument functions.
define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) {
; CHECK-APPLE-LABEL: tailcallswifterror:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {lr}
; CHECK-APPLE-NEXT: bl _tailcallswifterror
; CHECK-APPLE-NEXT: pop {lr}
; CHECK-APPLE-NEXT: bx lr
;
; CHECK-O0-LABEL: tailcallswifterror:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: bl _tailcallswifterror
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: tailcallswifterror:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r11, lr}
; CHECK-ANDROID-NEXT: push {r11, lr}
; CHECK-ANDROID-NEXT: bl tailcallswifterror
; CHECK-ANDROID-NEXT: pop {r11, pc}
entry:
%0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref)
ret float %0
}
define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) {
; CHECK-APPLE-LABEL: tailcallswifterror_swiftcc:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {lr}
; CHECK-APPLE-NEXT: bl _tailcallswifterror_swiftcc
; CHECK-APPLE-NEXT: pop {lr}
; CHECK-APPLE-NEXT: bx lr
;
; CHECK-O0-LABEL: tailcallswifterror_swiftcc:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: bl _tailcallswifterror_swiftcc
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: tailcallswifterror_swiftcc:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r11, lr}
; CHECK-ANDROID-NEXT: push {r11, lr}
; CHECK-ANDROID-NEXT: bl tailcallswifterror_swiftcc
; CHECK-ANDROID-NEXT: pop {r11, pc}
entry:
%0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref)
ret float %0
}
define swiftcc void @swifterror_clobber(%swift_error** nocapture swifterror %err) {
; CHECK-APPLE-LABEL: swifterror_clobber:
; CHECK-APPLE: @ %bb.0:
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: @ InlineAsm Start
; CHECK-APPLE-NEXT: nop
; CHECK-APPLE-NEXT: @ InlineAsm End
; CHECK-APPLE-NEXT: mov r8, r0
; CHECK-APPLE-NEXT: bx lr
;
; CHECK-O0-LABEL: swifterror_clobber:
; CHECK-O0: @ %bb.0:
; CHECK-O0-NEXT: sub sp, sp, #4
; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: @ InlineAsm Start
; CHECK-O0-NEXT: nop
; CHECK-O0-NEXT: @ InlineAsm End
; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: add sp, sp, #4
; CHECK-O0-NEXT: bx lr
;
; CHECK-ANDROID-LABEL: swifterror_clobber:
; CHECK-ANDROID: @ %bb.0:
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: @APP
; CHECK-ANDROID-NEXT: nop
; CHECK-ANDROID-NEXT: @NO_APP
; CHECK-ANDROID-NEXT: mov r8, r0
; CHECK-ANDROID-NEXT: bx lr
call void asm sideeffect "nop", "~{r8}"()
ret void
}
define swiftcc void @swifterror_reg_clobber(%swift_error** nocapture %err) {
; CHECK-APPLE-LABEL: swifterror_reg_clobber:
; CHECK-APPLE: @ %bb.0:
; CHECK-APPLE-NEXT: push {r8, lr}
; CHECK-APPLE-NEXT: @ InlineAsm Start
; CHECK-APPLE-NEXT: nop
; CHECK-APPLE-NEXT: @ InlineAsm End
; CHECK-APPLE-NEXT: pop {r8, pc}
;
; CHECK-O0-LABEL: swifterror_reg_clobber:
; CHECK-O0: @ %bb.0:
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: @ InlineAsm Start
; CHECK-O0-NEXT: nop
; CHECK-O0-NEXT: @ InlineAsm End
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: swifterror_reg_clobber:
; CHECK-ANDROID: @ %bb.0:
; CHECK-ANDROID-NEXT: .save {r8, lr}
; CHECK-ANDROID-NEXT: push {r8, lr}
; CHECK-ANDROID-NEXT: @APP
; CHECK-ANDROID-NEXT: nop
; CHECK-ANDROID-NEXT: @NO_APP
; CHECK-ANDROID-NEXT: pop {r8, pc}
call void asm sideeffect "nop", "~{r8}"()
ret void
}
define swiftcc void @params_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
; CHECK-APPLE-LABEL: params_in_reg:
; CHECK-APPLE: @ %bb.0:
; CHECK-APPLE-NEXT: push {r4, r5, r6, r7, r10, r11, lr}
; CHECK-APPLE-NEXT: add r7, sp, #20
; CHECK-APPLE-NEXT: sub sp, sp, #12
; CHECK-APPLE-NEXT: bfc sp, #0, #3
; CHECK-APPLE-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-APPLE-NEXT: mov r6, r3
; CHECK-APPLE-NEXT: str r10, [sp] @ 4-byte Spill
; CHECK-APPLE-NEXT: mov r4, r2
; CHECK-APPLE-NEXT: mov r11, r1
; CHECK-APPLE-NEXT: mov r5, r0
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: mov r1, #2
; CHECK-APPLE-NEXT: mov r2, #3
; CHECK-APPLE-NEXT: mov r3, #4
; CHECK-APPLE-NEXT: mov r10, #0
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: bl _params_in_reg2
; CHECK-APPLE-NEXT: ldr r10, [sp] @ 4-byte Reload
; CHECK-APPLE-NEXT: mov r0, r5
; CHECK-APPLE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload
; CHECK-APPLE-NEXT: mov r1, r11
; CHECK-APPLE-NEXT: mov r2, r4
; CHECK-APPLE-NEXT: mov r3, r6
; CHECK-APPLE-NEXT: bl _params_in_reg2
; CHECK-APPLE-NEXT: sub sp, r7, #20
; CHECK-APPLE-NEXT: pop {r4, r5, r6, r7, r10, r11, pc}
;
; CHECK-O0-LABEL: params_in_reg:
; CHECK-O0: @ %bb.0:
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r10}
; CHECK-O0-NEXT: sub sp, sp, #28
; CHECK-O0-NEXT: bfc sp, #0, #3
; CHECK-O0-NEXT: str r8, [sp, #20] @ 4-byte Spill
; CHECK-O0-NEXT: str r10, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: str r3, [sp, #16] @ 4-byte Spill
; CHECK-O0-NEXT: str r2, [sp, #12] @ 4-byte Spill
; CHECK-O0-NEXT: str r1, [sp, #8] @ 4-byte Spill
; CHECK-O0-NEXT: str r0, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: @ implicit-def: $r0
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: mov r0, #1
; CHECK-O0-NEXT: mov r1, #2
; CHECK-O0-NEXT: mov r2, #3
; CHECK-O0-NEXT: mov r3, #4
; CHECK-O0-NEXT: mov r10, r8
; CHECK-O0-NEXT: bl _params_in_reg2
; CHECK-O0-NEXT: ldr r10, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r1, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r2, [sp, #12] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r3, [sp, #16] @ 4-byte Reload
; CHECK-O0-NEXT: mov r9, r8
; CHECK-O0-NEXT: ldr r8, [sp, #20] @ 4-byte Reload
; CHECK-O0-NEXT: bl _params_in_reg2
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r10}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: params_in_reg:
; CHECK-ANDROID: @ %bb.0:
; CHECK-ANDROID-NEXT: .save {r4, r5, r6, r7, r9, r10, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r5, r6, r7, r9, r10, r11, lr}
; CHECK-ANDROID-NEXT: .pad #8
; CHECK-ANDROID-NEXT: sub sp, sp, #8
; CHECK-ANDROID-NEXT: mov r9, r8
; CHECK-ANDROID-NEXT: mov r11, r10
; CHECK-ANDROID-NEXT: mov r6, r3
; CHECK-ANDROID-NEXT: mov r7, r2
; CHECK-ANDROID-NEXT: mov r4, r1
; CHECK-ANDROID-NEXT: mov r5, r0
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: mov r1, #2
; CHECK-ANDROID-NEXT: mov r2, #3
; CHECK-ANDROID-NEXT: mov r3, #4
; CHECK-ANDROID-NEXT: mov r10, #0
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: bl params_in_reg2
; CHECK-ANDROID-NEXT: mov r0, r5
; CHECK-ANDROID-NEXT: mov r1, r4
; CHECK-ANDROID-NEXT: mov r2, r7
; CHECK-ANDROID-NEXT: mov r3, r6
; CHECK-ANDROID-NEXT: mov r10, r11
; CHECK-ANDROID-NEXT: mov r8, r9
; CHECK-ANDROID-NEXT: bl params_in_reg2
; CHECK-ANDROID-NEXT: add sp, sp, #8
; CHECK-ANDROID-NEXT: pop {r4, r5, r6, r7, r9, r10, r11, pc}
%error_ptr_ref = alloca swifterror %swift_error*, align 8
store %swift_error* null, %swift_error** %error_ptr_ref
call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
call swiftcc void @params_in_reg2(i32 %0, i32 %1, i32 %2, i32 %3, i8* swiftself %4, %swift_error** nocapture swifterror %err)
ret void
}
declare swiftcc void @params_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)
define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) {
; CHECK-APPLE-LABEL: params_and_return_in_reg:
; CHECK-APPLE: @ %bb.0:
; CHECK-APPLE-NEXT: push {r4, r5, r6, r7, r10, r11, lr}
; CHECK-APPLE-NEXT: add r7, sp, #20
; CHECK-APPLE-NEXT: sub sp, sp, #20
; CHECK-APPLE-NEXT: bfc sp, #0, #3
; CHECK-APPLE-NEXT: mov r6, r8
; CHECK-APPLE-NEXT: str r10, [sp, #12] @ 4-byte Spill
; CHECK-APPLE-NEXT: str r3, [sp, #8] @ 4-byte Spill
; CHECK-APPLE-NEXT: mov r4, r2
; CHECK-APPLE-NEXT: mov r11, r1
; CHECK-APPLE-NEXT: mov r5, r0
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: mov r1, #2
; CHECK-APPLE-NEXT: mov r2, #3
; CHECK-APPLE-NEXT: mov r3, #4
; CHECK-APPLE-NEXT: mov r10, #0
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: bl _params_in_reg2
; CHECK-APPLE-NEXT: ldr r3, [sp, #8] @ 4-byte Reload
; CHECK-APPLE-NEXT: mov r0, r5
; CHECK-APPLE-NEXT: ldr r10, [sp, #12] @ 4-byte Reload
; CHECK-APPLE-NEXT: mov r1, r11
; CHECK-APPLE-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-APPLE-NEXT: mov r2, r4
; CHECK-APPLE-NEXT: mov r8, r6
; CHECK-APPLE-NEXT: bl _params_and_return_in_reg2
; CHECK-APPLE-NEXT: str r8, [sp, #12] @ 4-byte Spill
; CHECK-APPLE-NEXT: mov r4, r0
; CHECK-APPLE-NEXT: ldr r8, [sp, #4] @ 4-byte Reload
; CHECK-APPLE-NEXT: mov r5, r1
; CHECK-APPLE-NEXT: mov r6, r2
; CHECK-APPLE-NEXT: mov r11, r3
; CHECK-APPLE-NEXT: mov r0, #1
; CHECK-APPLE-NEXT: mov r1, #2
; CHECK-APPLE-NEXT: mov r2, #3
; CHECK-APPLE-NEXT: mov r3, #4
; CHECK-APPLE-NEXT: mov r10, #0
; CHECK-APPLE-NEXT: bl _params_in_reg2
; CHECK-APPLE-NEXT: mov r0, r4
; CHECK-APPLE-NEXT: mov r1, r5
; CHECK-APPLE-NEXT: mov r2, r6
; CHECK-APPLE-NEXT: mov r3, r11
; CHECK-APPLE-NEXT: ldr r8, [sp, #12] @ 4-byte Reload
; CHECK-APPLE-NEXT: sub sp, r7, #20
; CHECK-APPLE-NEXT: pop {r4, r5, r6, r7, r10, r11, pc}
;
; CHECK-O0-LABEL: params_and_return_in_reg:
; CHECK-O0: @ %bb.0:
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r10}
; CHECK-O0-NEXT: sub sp, sp, #76
; CHECK-O0-NEXT: bfc sp, #0, #3
; CHECK-O0-NEXT: str r8, [sp, #24] @ 4-byte Spill
; CHECK-O0-NEXT: str r10, [sp, #4] @ 4-byte Spill
; CHECK-O0-NEXT: str r3, [sp, #20] @ 4-byte Spill
; CHECK-O0-NEXT: str r2, [sp, #16] @ 4-byte Spill
; CHECK-O0-NEXT: str r1, [sp, #12] @ 4-byte Spill
; CHECK-O0-NEXT: str r0, [sp, #8] @ 4-byte Spill
; CHECK-O0-NEXT: @ implicit-def: $r0
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: str r8, [sp, #28] @ 4-byte Spill
; CHECK-O0-NEXT: mov r0, #1
; CHECK-O0-NEXT: str r0, [sp, #32] @ 4-byte Spill
; CHECK-O0-NEXT: mov r1, #2
; CHECK-O0-NEXT: str r1, [sp, #36] @ 4-byte Spill
; CHECK-O0-NEXT: mov r2, #3
; CHECK-O0-NEXT: str r2, [sp, #40] @ 4-byte Spill
; CHECK-O0-NEXT: mov r3, #4
; CHECK-O0-NEXT: str r3, [sp, #44] @ 4-byte Spill
; CHECK-O0-NEXT: mov r10, r8
; CHECK-O0-NEXT: bl _params_in_reg2
; CHECK-O0-NEXT: ldr r10, [sp, #4] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r0, [sp, #8] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r1, [sp, #12] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r2, [sp, #16] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r3, [sp, #20] @ 4-byte Reload
; CHECK-O0-NEXT: mov r9, r8
; CHECK-O0-NEXT: ldr r8, [sp, #24] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #48] @ 4-byte Spill
; CHECK-O0-NEXT: bl _params_and_return_in_reg2
; CHECK-O0-NEXT: ldr r10, [sp, #28] @ 4-byte Reload
; CHECK-O0-NEXT: mov r9, r0
; CHECK-O0-NEXT: ldr r0, [sp, #32] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #52] @ 4-byte Spill
; CHECK-O0-NEXT: mov r9, r1
; CHECK-O0-NEXT: ldr r1, [sp, #36] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #56] @ 4-byte Spill
; CHECK-O0-NEXT: mov r9, r2
; CHECK-O0-NEXT: ldr r2, [sp, #40] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #60] @ 4-byte Spill
; CHECK-O0-NEXT: mov r9, r3
; CHECK-O0-NEXT: ldr r3, [sp, #44] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #64] @ 4-byte Spill
; CHECK-O0-NEXT: mov r9, r8
; CHECK-O0-NEXT: ldr r8, [sp, #48] @ 4-byte Reload
; CHECK-O0-NEXT: str r9, [sp, #68] @ 4-byte Spill
; CHECK-O0-NEXT: bl _params_in_reg2
; CHECK-O0-NEXT: ldr r0, [sp, #52] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r1, [sp, #56] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r2, [sp, #60] @ 4-byte Reload
; CHECK-O0-NEXT: ldr r3, [sp, #64] @ 4-byte Reload
; CHECK-O0-NEXT: mov r9, r8
; CHECK-O0-NEXT: ldr r8, [sp, #68] @ 4-byte Reload
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r10}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: params_and_return_in_reg:
; CHECK-ANDROID: @ %bb.0:
; CHECK-ANDROID-NEXT: .save {r4, r5, r6, r7, r9, r10, r11, lr}
; CHECK-ANDROID-NEXT: push {r4, r5, r6, r7, r9, r10, r11, lr}
; CHECK-ANDROID-NEXT: .pad #16
; CHECK-ANDROID-NEXT: sub sp, sp, #16
; CHECK-ANDROID-NEXT: str r8, [sp, #4] @ 4-byte Spill
; CHECK-ANDROID-NEXT: mov r11, r10
; CHECK-ANDROID-NEXT: mov r6, r3
; CHECK-ANDROID-NEXT: mov r7, r2
; CHECK-ANDROID-NEXT: mov r4, r1
; CHECK-ANDROID-NEXT: mov r5, r0
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: mov r1, #2
; CHECK-ANDROID-NEXT: mov r2, #3
; CHECK-ANDROID-NEXT: mov r3, #4
; CHECK-ANDROID-NEXT: mov r10, #0
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: bl params_in_reg2
; CHECK-ANDROID-NEXT: mov r9, r8
; CHECK-ANDROID-NEXT: ldr r8, [sp, #4] @ 4-byte Reload
; CHECK-ANDROID-NEXT: mov r0, r5
; CHECK-ANDROID-NEXT: mov r1, r4
; CHECK-ANDROID-NEXT: mov r2, r7
; CHECK-ANDROID-NEXT: mov r3, r6
; CHECK-ANDROID-NEXT: mov r10, r11
; CHECK-ANDROID-NEXT: bl params_and_return_in_reg2
; CHECK-ANDROID-NEXT: mov r4, r0
; CHECK-ANDROID-NEXT: mov r5, r1
; CHECK-ANDROID-NEXT: mov r6, r2
; CHECK-ANDROID-NEXT: mov r7, r3
; CHECK-ANDROID-NEXT: mov r11, r8
; CHECK-ANDROID-NEXT: mov r0, #1
; CHECK-ANDROID-NEXT: mov r1, #2
; CHECK-ANDROID-NEXT: mov r2, #3
; CHECK-ANDROID-NEXT: mov r3, #4
; CHECK-ANDROID-NEXT: mov r10, #0
; CHECK-ANDROID-NEXT: mov r8, r9
; CHECK-ANDROID-NEXT: bl params_in_reg2
; CHECK-ANDROID-NEXT: mov r0, r4
; CHECK-ANDROID-NEXT: mov r1, r5
; CHECK-ANDROID-NEXT: mov r2, r6
; CHECK-ANDROID-NEXT: mov r3, r7
; CHECK-ANDROID-NEXT: mov r8, r11
; CHECK-ANDROID-NEXT: add sp, sp, #16
; CHECK-ANDROID-NEXT: pop {r4, r5, r6, r7, r9, r10, r11, pc}
%error_ptr_ref = alloca swifterror %swift_error*, align 8
store %swift_error* null, %swift_error** %error_ptr_ref
call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
%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)
call swiftcc void @params_in_reg2(i32 1, i32 2, i32 3, i32 4, i8* swiftself null, %swift_error** nocapture swifterror %error_ptr_ref)
ret { i32, i32, i32, i32 }%val
}
declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err)
declare void @acallee(i8*)
; Make sure we don't tail call if the caller returns a swifterror value. We
; would have to move into the swifterror register before the tail call.
define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) {
; CHECK-APPLE-LABEL: tailcall_from_swifterror:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r4, lr}
; CHECK-APPLE-NEXT: mov r0, #0
; CHECK-APPLE-NEXT: mov r4, r8
; CHECK-APPLE-NEXT: bl _acallee
; CHECK-APPLE-NEXT: mov r8, r4
; CHECK-APPLE-NEXT: pop {r4, pc}
;
; CHECK-O0-LABEL: tailcall_from_swifterror:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: sub sp, sp, #4
; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: mov r0, #0
; CHECK-O0-NEXT: bl _acallee
; CHECK-O0-NEXT: ldr r8, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: mov sp, r7
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: tailcall_from_swifterror:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r4, lr}
; CHECK-ANDROID-NEXT: push {r4, lr}
; CHECK-ANDROID-NEXT: mov r0, #0
; CHECK-ANDROID-NEXT: mov r4, r8
; CHECK-ANDROID-NEXT: bl acallee
; CHECK-ANDROID-NEXT: mov r8, r4
; CHECK-ANDROID-NEXT: pop {r4, pc}
entry:
tail call void @acallee(i8* null)
ret void
}
declare swiftcc void @foo2(%swift_error** swifterror)
; Make sure we properly assign registers during fast-isel.
define swiftcc %swift_error* @testAssign(i8* %error_ref) {
; CHECK-APPLE-LABEL: testAssign:
; CHECK-APPLE: @ %bb.0: @ %entry
; CHECK-APPLE-NEXT: push {r8, lr}
; CHECK-APPLE-NEXT: sub sp, sp, #4
; CHECK-APPLE-NEXT: mov r8, #0
; CHECK-APPLE-NEXT: bl _foo2
; CHECK-APPLE-NEXT: mov r0, r8
; CHECK-APPLE-NEXT: add sp, sp, #4
; CHECK-APPLE-NEXT: pop {r8, pc}
;
; CHECK-O0-LABEL: testAssign:
; CHECK-O0: @ %bb.0: @ %entry
; CHECK-O0-NEXT: push {r7, lr}
; CHECK-O0-NEXT: mov r7, sp
; CHECK-O0-NEXT: push {r8}
; CHECK-O0-NEXT: sub sp, sp, #8
; CHECK-O0-NEXT: @ implicit-def: $r1
; CHECK-O0-NEXT: mov r8, #0
; CHECK-O0-NEXT: bl _foo2
; CHECK-O0-NEXT: str r8, [sp] @ 4-byte Spill
; CHECK-O0-NEXT: @ %bb.1: @ %a
; CHECK-O0-NEXT: ldr r0, [sp] @ 4-byte Reload
; CHECK-O0-NEXT: sub sp, r7, #4
; CHECK-O0-NEXT: pop {r8}
; CHECK-O0-NEXT: pop {r7, pc}
;
; CHECK-ANDROID-LABEL: testAssign:
; CHECK-ANDROID: @ %bb.0: @ %entry
; CHECK-ANDROID-NEXT: .save {r8, lr}
; CHECK-ANDROID-NEXT: push {r8, lr}
; CHECK-ANDROID-NEXT: .pad #8
; CHECK-ANDROID-NEXT: sub sp, sp, #8
; CHECK-ANDROID-NEXT: mov r8, #0
; CHECK-ANDROID-NEXT: bl foo2
; CHECK-ANDROID-NEXT: mov r0, r8
; CHECK-ANDROID-NEXT: add sp, sp, #8
; CHECK-ANDROID-NEXT: pop {r8, pc}
entry:
%error_ptr = alloca swifterror %swift_error*
store %swift_error* null, %swift_error** %error_ptr
call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
br label %a
a:
%error = load %swift_error*, %swift_error** %error_ptr
ret %swift_error* %error
}