xref: /llvm-project/llvm/test/CodeGen/ARM/cxx-tlscc.ll (revision 4865d89653f36cc16daffdbdec37629b88bb2d54)
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