1; RUN: llc < %s -emulated-tls -mtriple=i386-linux-gnu -relocation-model=pic | FileCheck -check-prefix=X86 %s
2; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-gnu -relocation-model=pic | FileCheck -check-prefix=X64 %s
3; RUN: llc < %s -emulated-tls -mtriple=i386-linux-android -relocation-model=pic | FileCheck -check-prefix=X86 %s
4; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck -check-prefix=X64 %s
5
6; RUN: llc < %s -mtriple=i386-linux-gnu -relocation-model=pic | FileCheck -check-prefix=NoEMU %s
7; RUN: llc < %s -mtriple=x86_64-linux-gnu -relocation-model=pic | FileCheck -check-prefix=NoEMU %s
8; RUN: llc < %s -mtriple=i386-linux-android -relocation-model=pic | FileCheck -check-prefix=X86 %s
9; RUN: llc < %s -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck -check-prefix=X64 %s
10
11; NoEMU-NOT: __emutls
12
13; Use my_emutls_get_address like __emutls_get_address.
14@my_emutls_v_xyz = external global i8*, align 4
15declare i8* @my_emutls_get_address(i8*)
16
17define i32 @my_get_xyz() {
18; X86-LABEL: my_get_xyz:
19; X86:      movl my_emutls_v_xyz@GOT(%ebx), %eax
20; X86-NEXT: movl %eax, (%esp)
21; X86-NEXT: calll my_emutls_get_address@PLT
22; X64-LABEL: my_get_xyz:
23; X64:      movq my_emutls_v_xyz@GOTPCREL(%rip), %rdi
24; X64-NEXT: callq my_emutls_get_address@PLT
25; X64-NEXT: movl (%rax), %eax
26
27entry:
28  %call = call i8* @my_emutls_get_address(i8* bitcast (i8** @my_emutls_v_xyz to i8*))
29  %0 = bitcast i8* %call to i32*
30  %1 = load i32, i32* %0, align 4
31  ret i32 %1
32}
33
34@i = thread_local global i32 15
35@j = internal thread_local global i32 42
36@k = internal thread_local global i32 0, align 8
37
38define i32 @f1() {
39entry:
40  %tmp1 = load i32, i32* @i
41  ret i32 %tmp1
42}
43
44; X86-LABEL: f1:
45; X86:      movl __emutls_v.i@GOT(%ebx), %eax
46; X86-NEXT: movl %eax, (%esp)
47; X86-NEXT: calll __emutls_get_address@PLT
48; X64-LABEL: f1:
49; X64:      movq __emutls_v.i@GOTPCREL(%rip), %rdi
50; X64-NEXT: callq __emutls_get_address@PLT
51; X64-NEXT: movl (%rax), %eax
52
53@i2 = external thread_local global i32
54
55define i32* @f2() {
56entry:
57  ret i32* @i
58}
59
60; X86-LABEL: f2:
61; X64-LABEL: f2:
62
63
64define i32 @f3() {
65entry:
66  %tmp1 = load i32, i32* @i  ; <i32> [#uses=1]
67  ret i32 %tmp1
68}
69
70; X86-LABEL: f3:
71; X64-LABEL: f3:
72
73
74define i32* @f4() nounwind {
75entry:
76  ret i32* @i
77}
78
79; X86-LABEL: f4:
80; X64-LABEL: f4:
81
82
83define i32 @f5() nounwind {
84entry:
85  %0 = load i32, i32* @j, align 4
86  %1 = load i32, i32* @k, align 4
87  %add = add nsw i32 %0, %1
88  ret i32 %add
89}
90
91; X86-LABEL: f5:
92; X86:      leal __emutls_v.j@GOTOFF(%ebx), %eax
93; X86-NEXT: movl %eax, (%esp)
94; X86-NEXT: calll __emutls_get_address@PLT
95; X86-NEXT: movl (%eax), %esi
96; X86-NEXT: leal __emutls_v.k@GOTOFF(%ebx), %eax
97; X86-NEXT: movl %eax, (%esp)
98; X86-NEXT: calll __emutls_get_address@PLT
99; X86-NEXT: addl (%eax), %esi
100; X86-NEXT: movl %esi, %eax
101
102; X64-LABEL: f5:
103; X64:      leaq __emutls_v.j(%rip), %rdi
104; X64-NEXT: callq __emutls_get_address@PLT
105; X64-NEXT: movl (%rax), %ebx
106; X64-NEXT: leaq __emutls_v.k(%rip), %rdi
107; X64-NEXT: callq __emutls_get_address@PLT
108; X64-NEXT: addl (%rax), %ebx
109; X64-NEXT: movl %ebx, %eax
110
111;;;;; 32-bit targets
112
113; X86:      .data{{$}}
114; X86:      .globl __emutls_v.i
115; X86-LABEL: __emutls_v.i:
116; X86-NEXT: .long 4
117; X86-NEXT: .long 4
118; X86-NEXT: .long 0
119; X86-NEXT: .long __emutls_t.i
120
121; X86:      .section .rodata,
122; X86-LABEL: __emutls_t.i:
123; X86-NEXT: .long 15
124
125; X86:      .data{{$}}
126; X86-NOT:  .globl
127; X86-LABEL: __emutls_v.j:
128; X86-NEXT: .long 4
129; X86-NEXT: .long 4
130; X86-NEXT: .long 0
131; X86-NEXT: .long __emutls_t.j
132
133; X86:      .section .rodata,
134; X86-LABEL: __emutls_t.j:
135; X86-NEXT: .long 42
136
137; X86:      .data{{$}}
138; X86-NOT:  .globl
139; X86-LABEL: __emutls_v.k:
140; X86-NEXT: .long 4
141; X86-NEXT: .long 8
142; X86-NEXT: .long 0
143; X86-NEXT: .long 0
144
145; X86-NOT:   __emutls_t.k:
146
147;;;;; 64-bit targets
148
149; X64:      .data{{$}}
150; X64:      .globl __emutls_v.i
151; X64-LABEL: __emutls_v.i:
152; X64-NEXT: .quad 4
153; X64-NEXT: .quad 4
154; X64-NEXT: .quad 0
155; X64-NEXT: .quad __emutls_t.i
156
157; X64:      .section .rodata,
158; X64-LABEL: __emutls_t.i:
159; X64-NEXT: .long 15
160
161; X64:      .data{{$}}
162; X64-NOT:  .globl
163; X64-LABEL: __emutls_v.j:
164; X64-NEXT: .quad 4
165; X64-NEXT: .quad 4
166; X64-NEXT: .quad 0
167; X64-NEXT: .quad __emutls_t.j
168
169; X64:      .section .rodata,
170; X64-LABEL: __emutls_t.j:
171; X64-NEXT: .long 42
172
173; X64:      .data{{$}}
174; X64-NOT:  .globl
175; X64-LABEL: __emutls_v.k:
176; X64-NEXT: .quad 4
177; X64-NEXT: .quad 8
178; X64-NEXT: .quad 0
179; X64-NEXT: .quad 0
180
181; X64-NOT:   __emutls_t.k:
182