1; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 | FileCheck %s 2; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 -enable-shrink-wrap=true | FileCheck --check-prefix=CHECK %s 3; RUN: llc < %s -mtriple=armv7-apple-ios8.0 | FileCheck %s 4; RUN: llc < %s -mtriple=armv7-apple-ios8.0 -enable-shrink-wrap=true | FileCheck --check-prefix=CHECK %s 5 6; RUN: llc < %s -mtriple=armv7k-apple-watchos2.0 -O0 | FileCheck --check-prefix=CHECK-O0 --check-prefix=WATCH-O0 %s 7; RUN: llc < %s -mtriple=armv7-apple-ios8.0 -O0 | FileCheck --check-prefix=CHECK-O0 --check-prefix=IOS-O0 %s 8 9%struct.S = type { i8 } 10 11@sg = internal thread_local global %struct.S zeroinitializer, align 1 12@__dso_handle = external global i8 13@__tls_guard = internal thread_local unnamed_addr global i1 false 14@sum1 = internal thread_local global i32 0, align 4 15 16%class.C = type { i32 } 17@tC = internal thread_local global %class.C zeroinitializer, align 4 18 19declare %struct.S* @_ZN1SC1Ev(%struct.S* returned) 20declare %struct.S* @_ZN1SD1Ev(%struct.S* returned) 21declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) 22 23define cxx_fast_tlscc nonnull %struct.S* @_ZTW2sg() nounwind { 24 %.b.i = load i1, i1* @__tls_guard, align 1 25 br i1 %.b.i, label %__tls_init.exit, label %init.i 26 27init.i: 28 store i1 true, i1* @__tls_guard, align 1 29 %call.i.i = tail call %struct.S* @_ZN1SC1Ev(%struct.S* nonnull @sg) 30 %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) 31 br label %__tls_init.exit 32 33__tls_init.exit: 34 ret %struct.S* @sg 35} 36 37; CHECK-LABEL: _ZTW2sg 38; CHECK: push {lr} 39; CHECK-NOT: push {r1, r2, r3, r4, r7, lr} 40; CHECK-NOT: push {r9, r12} 41; CHECK-NOT: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 42; CHECK-NOT: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 43; CHECK: blx 44; CHECK: bne [[BB_end:.?LBB0_[0-9]+]] 45; CHECK: blx 46; CHECK: tlv_atexit 47; CHECK: [[BB_end]]: 48; CHECK: blx 49; CHECK-NOT: vpop {d0, d1, d2, d3, d4, d5, d6, d7} 50; CHECK-NOT: vpop {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 51; CHECK-NOT: pop {r9, r12} 52; CHECK-NOT: pop {r1, r2, r3, r4, r7, pc} 53; CHECK: pop {lr} 54 55; CHECK-O0-LABEL: _ZTW2sg 56; WATCH-O0: push {r1, r2, r3, r6, r7, lr} 57; IOS-O0: push {r1, r2, r3, r7, lr} 58; CHECK-O0: push {r9, r12} 59; CHECK-O0: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 60; CHECK-O0: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 61; CHECK-O0: blx 62; CHECK-O0: bne [[BB_end:.?LBB0_[0-9]+]] 63; CHECK-O0: blx 64; CHECK-O0: tlv_atexit 65; CHECK-O0: [[BB_end]]: 66; CHECK-O0: blx 67; CHECK-O0: vpop {d0, d1, d2, d3, d4, d5, d6, d7} 68; CHECK-O0: vpop {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 69; CHECK-O0: pop {r9, r12} 70; WATCH-O0: pop {r1, r2, r3, r6, r7, pc} 71; IOS-O0: pop {r1, r2, r3, r7, pc} 72 73; CHECK-LABEL: _ZTW4sum1 74; CHECK-NOT: push {r1, r2, r3, r4, r7, lr} 75; CHECK-NOT: push {r9, r12} 76; CHECK-NOT: vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} 77; CHECK-NOT: vpush {d0, d1, d2, d3, d4, d5, d6, d7} 78; CHECK: blx 79 80; CHECK-O0-LABEL: _ZTW4sum1 81; CHECK-O0-NOT: vpush 82; CHECK-O0-NOT: vstr 83; CHECK-O0-NOT: vpop 84; CHECK-O0-NOT: vldr 85; CHECK-O0: pop 86define cxx_fast_tlscc nonnull i32* @_ZTW4sum1() nounwind { 87 ret i32* @sum1 88} 89 90; Make sure at O0, we don't generate spilling/reloading of the CSRs. 91; CHECK-O0-LABEL: tls_test2 92; CHECK-O0: push 93; CHECK-O0-NOT: vpush 94; CHECK-O0-NOT: vstr 95; CHECK-O0: tls_helper 96; CHECK-O0-NOT: vpop 97; CHECK-O0-NOT: vldr 98; CHECK-O0: pop 99declare cxx_fast_tlscc void @tls_helper() 100define cxx_fast_tlscc %class.C* @tls_test2() #1 { 101 call cxx_fast_tlscc void @tls_helper() 102 ret %class.C* @tC 103} 104 105; Make sure we do not allow tail call when caller and callee have different 106; calling conventions. 107declare %class.C* @_ZN1CD1Ev(%class.C* readnone returned %this) 108; CHECK-LABEL: tls_test 109; CHECK: bl __tlv_atexit 110define cxx_fast_tlscc void @__tls_test() { 111entry: 112 store i32 0, i32* getelementptr inbounds (%class.C, %class.C* @tC, i64 0, i32 0), align 4 113 %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 114 ret void 115} 116 117attributes #0 = { nounwind "no-frame-pointer-elim"="true" } 118attributes #1 = { nounwind } 119