1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 -enable-shrink-wrap=true | FileCheck %s 3*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7-apple-ios8.0 | FileCheck %s 4*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7-apple-ios8.0 -enable-shrink-wrap=true | FileCheck %s 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 -O0 | FileCheck --check-prefix=CHECK-O0 --check-prefix=WATCH-O0 %s 7*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7-apple-ios8.0 -O0 | FileCheck --check-prefix=CHECK-O0 --check-prefix=IOS-O0 %s 8*9880d681SAndroid Build Coastguard Worker 9*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=thumbv7-apple-ios8.0 | FileCheck --check-prefix=THUMB %s 10*9880d681SAndroid Build Coastguard Worker 11*9880d681SAndroid Build Coastguard Worker%struct.S = type { i8 } 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker@sg = internal thread_local global %struct.S zeroinitializer, align 1 14*9880d681SAndroid Build Coastguard Worker@__dso_handle = external global i8 15*9880d681SAndroid Build Coastguard Worker@__tls_guard = internal thread_local unnamed_addr global i1 false 16*9880d681SAndroid Build Coastguard Worker@sum1 = internal thread_local global i32 0, align 4 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker%class.C = type { i32 } 19*9880d681SAndroid Build Coastguard Worker@tC = internal thread_local global %class.C zeroinitializer, align 4 20*9880d681SAndroid Build Coastguard Worker 21*9880d681SAndroid Build Coastguard Workerdeclare %struct.S* @_ZN1SC1Ev(%struct.S* returned) 22*9880d681SAndroid Build Coastguard Workerdeclare %struct.S* @_ZN1SD1Ev(%struct.S* returned) 23*9880d681SAndroid Build Coastguard Workerdeclare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker; Make sure Epilog does not overwrite an explicitly-handled CSR in CXX_FAST_TLS. 26*9880d681SAndroid Build Coastguard Worker; THUMB-LABEL: _ZTW2sg 27*9880d681SAndroid Build Coastguard Worker; THUMB: push {{.*}}lr 28*9880d681SAndroid Build Coastguard Worker; THUMB: blx 29*9880d681SAndroid Build Coastguard Worker; THUMB: bne [[TH_end:.?LBB0_[0-9]+]] 30*9880d681SAndroid Build Coastguard Worker; THUMB: blx 31*9880d681SAndroid Build Coastguard Worker; THUMB: tlv_atexit 32*9880d681SAndroid Build Coastguard Worker; THUMB: [[TH_end]]: 33*9880d681SAndroid Build Coastguard Worker; THUMB: blx 34*9880d681SAndroid Build Coastguard Worker; THUMB: r4 35*9880d681SAndroid Build Coastguard Worker; THUMB: pop {{.*}}r4 36*9880d681SAndroid Build Coastguard Workerdefine cxx_fast_tlscc nonnull %struct.S* @_ZTW2sg() nounwind { 37*9880d681SAndroid Build Coastguard Worker %.b.i = load i1, i1* @__tls_guard, align 1 38*9880d681SAndroid Build Coastguard Worker br i1 %.b.i, label %__tls_init.exit, label %init.i 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Workerinit.i: 41*9880d681SAndroid Build Coastguard Worker store i1 true, i1* @__tls_guard, align 1 42*9880d681SAndroid Build Coastguard Worker %call.i.i = tail call %struct.S* @_ZN1SC1Ev(%struct.S* nonnull @sg) 43*9880d681SAndroid Build Coastguard Worker %1 = tail call i32 @_tlv_atexit(void (i8*)* nonnull bitcast (%struct.S* (%struct.S*)* @_ZN1SD1Ev to void (i8*)*), i8* nonnull getelementptr inbounds (%struct.S, %struct.S* @sg, i64 0, i32 0), i8* nonnull @__dso_handle) 44*9880d681SAndroid Build Coastguard Worker br label %__tls_init.exit 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Worker__tls_init.exit: 47*9880d681SAndroid Build Coastguard Worker ret %struct.S* @sg 48*9880d681SAndroid Build Coastguard Worker} 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: _ZTW2sg 51*9880d681SAndroid Build Coastguard Worker; CHECK: push {r4, r5, r7, lr} 52*9880d681SAndroid Build Coastguard Worker; CHECK: push {r11, r12} 53*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 54*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 55*9880d681SAndroid Build Coastguard Worker; CHECK: blx 56*9880d681SAndroid Build Coastguard Worker; CHECK: bne [[BB_end:.?LBB0_[0-9]+]] 57*9880d681SAndroid Build Coastguard Worker; CHECK: blx 58*9880d681SAndroid Build Coastguard Worker; CHECK: tlv_atexit 59*9880d681SAndroid Build Coastguard Worker; CHECK: [[BB_end]]: 60*9880d681SAndroid Build Coastguard Worker; CHECK: blx 61*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpop {d0, d1, d2, d3, d4, d5, d6, d7} 62*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpop {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 63*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: pop {r9, r12} 64*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: pop {r1, r2, r3, r4, r7, pc} 65*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r4, r5, r7, pc} 66*9880d681SAndroid Build Coastguard Worker 67*9880d681SAndroid Build Coastguard Worker; CHECK-O0-LABEL: _ZTW2sg 68*9880d681SAndroid Build Coastguard Worker; WATCH-O0: push {r1, r2, r3, r6, r7, lr} 69*9880d681SAndroid Build Coastguard Worker; IOS-O0: push {r1, r2, r3, r7, lr} 70*9880d681SAndroid Build Coastguard Worker; CHECK-O0: push {r9, r12} 71*9880d681SAndroid Build Coastguard Worker; CHECK-O0: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 72*9880d681SAndroid Build Coastguard Worker; CHECK-O0: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 73*9880d681SAndroid Build Coastguard Worker; CHECK-O0: blx 74*9880d681SAndroid Build Coastguard Worker; CHECK-O0: bne [[BB_end:.?LBB0_[0-9]+]] 75*9880d681SAndroid Build Coastguard Worker; CHECK-O0: blx 76*9880d681SAndroid Build Coastguard Worker; CHECK-O0: tlv_atexit 77*9880d681SAndroid Build Coastguard Worker; CHECK-O0: [[BB_end]]: 78*9880d681SAndroid Build Coastguard Worker; CHECK-O0: blx 79*9880d681SAndroid Build Coastguard Worker; CHECK-O0: vpop {d0, d1, d2, d3, d4, d5, d6, d7} 80*9880d681SAndroid Build Coastguard Worker; CHECK-O0: vpop {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 81*9880d681SAndroid Build Coastguard Worker; CHECK-O0: pop {r9, r12} 82*9880d681SAndroid Build Coastguard Worker; WATCH-O0: pop {r1, r2, r3, r6, r7, pc} 83*9880d681SAndroid Build Coastguard Worker; IOS-O0: pop {r1, r2, r3, r7, pc} 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: _ZTW4sum1 86*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: push {r1, r2, r3, r4, r7, lr} 87*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: push {r9, r12} 88*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 89*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 90*9880d681SAndroid Build Coastguard Worker; CHECK: blx 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker; CHECK-O0-LABEL: _ZTW4sum1 93*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vpush 94*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vstr 95*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vpop 96*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vldr 97*9880d681SAndroid Build Coastguard Worker; CHECK-O0: pop 98*9880d681SAndroid Build Coastguard Workerdefine cxx_fast_tlscc nonnull i32* @_ZTW4sum1() nounwind { 99*9880d681SAndroid Build Coastguard Worker ret i32* @sum1 100*9880d681SAndroid Build Coastguard Worker} 101*9880d681SAndroid Build Coastguard Worker 102*9880d681SAndroid Build Coastguard Worker; Make sure at O0, we don't generate spilling/reloading of the CSRs. 103*9880d681SAndroid Build Coastguard Worker; CHECK-O0-LABEL: tls_test2 104*9880d681SAndroid Build Coastguard Worker; CHECK-O0: push 105*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vpush 106*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vstr 107*9880d681SAndroid Build Coastguard Worker; CHECK-O0: tls_helper 108*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vpop 109*9880d681SAndroid Build Coastguard Worker; CHECK-O0-NOT: vldr 110*9880d681SAndroid Build Coastguard Worker; CHECK-O0: pop 111*9880d681SAndroid Build Coastguard Workerdeclare cxx_fast_tlscc void @tls_helper() 112*9880d681SAndroid Build Coastguard Workerdefine cxx_fast_tlscc %class.C* @tls_test2() #1 { 113*9880d681SAndroid Build Coastguard Worker call cxx_fast_tlscc void @tls_helper() 114*9880d681SAndroid Build Coastguard Worker ret %class.C* @tC 115*9880d681SAndroid Build Coastguard Worker} 116*9880d681SAndroid Build Coastguard Worker 117*9880d681SAndroid Build Coastguard Worker; Make sure we do not allow tail call when caller and callee have different 118*9880d681SAndroid Build Coastguard Worker; calling conventions. 119*9880d681SAndroid Build Coastguard Workerdeclare %class.C* @_ZN1CD1Ev(%class.C* readnone returned %this) 120*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: tls_test 121*9880d681SAndroid Build Coastguard Worker; CHECK: bl __tlv_atexit 122*9880d681SAndroid Build Coastguard Workerdefine cxx_fast_tlscc void @__tls_test() { 123*9880d681SAndroid Build Coastguard Workerentry: 124*9880d681SAndroid Build Coastguard Worker store i32 0, i32* getelementptr inbounds (%class.C, %class.C* @tC, i64 0, i32 0), align 4 125*9880d681SAndroid Build Coastguard Worker %0 = tail call i32 @_tlv_atexit(void (i8*)* bitcast (%class.C* (%class.C*)* @_ZN1CD1Ev to void (i8*)*), i8* bitcast (%class.C* @tC to i8*), i8* nonnull @__dso_handle) #1 126*9880d681SAndroid Build Coastguard Worker ret void 127*9880d681SAndroid Build Coastguard Worker} 128*9880d681SAndroid Build Coastguard Worker 129*9880d681SAndroid Build Coastguard Workerdeclare void @somefunc() 130*9880d681SAndroid Build Coastguard Workerdefine cxx_fast_tlscc void @test_ccmismatch_notail() { 131*9880d681SAndroid Build Coastguard Worker; A tail call is not possible here because somefunc does not preserve enough 132*9880d681SAndroid Build Coastguard Worker; registers. 133*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_ccmismatch_notail: 134*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: b _somefunc 135*9880d681SAndroid Build Coastguard Worker; CHECK: bl _somefunc 136*9880d681SAndroid Build Coastguard Worker tail call void @somefunc() 137*9880d681SAndroid Build Coastguard Worker ret void 138*9880d681SAndroid Build Coastguard Worker} 139*9880d681SAndroid Build Coastguard Worker 140*9880d681SAndroid Build Coastguard Workerdeclare cxx_fast_tlscc void @some_fast_tls_func() 141*9880d681SAndroid Build Coastguard Workerdefine void @test_ccmismatch_tail() { 142*9880d681SAndroid Build Coastguard Worker; We can perform a tail call here because some_fast_tls_func preserves all 143*9880d681SAndroid Build Coastguard Worker; necessary registers (and more). 144*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_ccmismatch_tail: 145*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: bl _some_fast_tls_func 146*9880d681SAndroid Build Coastguard Worker; CHECK: b _some_fast_tls_func 147*9880d681SAndroid Build Coastguard Worker tail call cxx_fast_tlscc void @some_fast_tls_func() 148*9880d681SAndroid Build Coastguard Worker ret void 149*9880d681SAndroid Build Coastguard Worker} 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Workerattributes #0 = { nounwind "no-frame-pointer-elim"="true" } 152*9880d681SAndroid Build Coastguard Workerattributes #1 = { nounwind } 153