1; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s
2; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
3; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s
4; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
5
6@i1 = thread_local global i32 15
7@i2 = external thread_local global i32
8@i3 = internal thread_local global i32 15
9@i4 = hidden thread_local global i32 15
10@i5 = external hidden thread_local global i32
11@s1 = thread_local global i16 15
12@b1 = thread_local global i8 0
13
14define i32 @f1() {
15; X32_LINUX-LABEL: f1:
16; X32_LINUX:      movl %gs:i1@NTPOFF, %eax
17; X32_LINUX-NEXT: ret
18; X64_LINUX-LABEL: f1:
19; X64_LINUX:      movl %fs:i1@TPOFF, %eax
20; X64_LINUX-NEXT: ret
21; X32_WIN-LABEL: f1:
22; X32_WIN:      movl __tls_index, %eax
23; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
24; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
25; X32_WIN-NEXT: movl _i1@SECREL32(%eax), %eax
26; X32_WIN-NEXT: ret
27; X64_WIN-LABEL: f1:
28; X64_WIN:      movl _tls_index(%rip), %eax
29; X64_WIN-NEXT: movq %gs:88, %rcx
30; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
31; X64_WIN-NEXT: movl i1@SECREL32(%rax), %eax
32; X64_WIN-NEXT: ret
33
34entry:
35	%tmp1 = load i32* @i1
36	ret i32 %tmp1
37}
38
39define i32* @f2() {
40; X32_LINUX-LABEL: f2:
41; X32_LINUX:      movl %gs:0, %eax
42; X32_LINUX-NEXT: leal i1@NTPOFF(%eax), %eax
43; X32_LINUX-NEXT: ret
44; X64_LINUX-LABEL: f2:
45; X64_LINUX:      movq %fs:0, %rax
46; X64_LINUX-NEXT: leaq i1@TPOFF(%rax), %rax
47; X64_LINUX-NEXT: ret
48; X32_WIN-LABEL: f2:
49; X32_WIN:      movl __tls_index, %eax
50; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
51; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
52; X32_WIN-NEXT: leal _i1@SECREL32(%eax), %eax
53; X32_WIN-NEXT: ret
54; X64_WIN-LABEL: f2:
55; X64_WIN:      movl _tls_index(%rip), %eax
56; X64_WIN-NEXT: movq %gs:88, %rcx
57; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
58; X64_WIN-NEXT: leaq i1@SECREL32(%rax), %rax
59; X64_WIN-NEXT: ret
60
61entry:
62	ret i32* @i1
63}
64
65define i32 @f3() nounwind {
66; X32_LINUX-LABEL: f3:
67; X32_LINUX:      movl i2@INDNTPOFF, %eax
68; X32_LINUX-NEXT: movl %gs:(%eax), %eax
69; X32_LINUX-NEXT: ret
70; X64_LINUX-LABEL: f3:
71; X64_LINUX:      movq i2@GOTTPOFF(%rip), %rax
72; X64_LINUX-NEXT: movl %fs:(%rax), %eax
73; X64_LINUX-NEXT: ret
74; X32_WIN-LABEL: f3:
75; X32_WIN:      movl __tls_index, %eax
76; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
77; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
78; X32_WIN-NEXT: movl _i2@SECREL32(%eax), %eax
79; X32_WIN-NEXT: ret
80; X64_WIN-LABEL: f3:
81; X64_WIN:      movl _tls_index(%rip), %eax
82; X64_WIN-NEXT: movq %gs:88, %rcx
83; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
84; X64_WIN-NEXT: movl i2@SECREL32(%rax), %eax
85; X64_WIN-NEXT: ret
86
87entry:
88	%tmp1 = load i32* @i2
89	ret i32 %tmp1
90}
91
92define i32* @f4() {
93; X32_LINUX-LABEL: f4:
94; X32_LINUX:      movl %gs:0, %eax
95; X32_LINUX-NEXT: addl i2@INDNTPOFF, %eax
96; X32_LINUX-NEXT: ret
97; X64_LINUX-LABEL: f4:
98; X64_LINUX:      movq %fs:0, %rax
99; X64_LINUX-NEXT: addq i2@GOTTPOFF(%rip), %rax
100; X64_LINUX-NEXT: ret
101; X32_WIN-LABEL: f4:
102; X32_WIN:      movl __tls_index, %eax
103; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
104; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
105; X32_WIN-NEXT: leal _i2@SECREL32(%eax), %eax
106; X32_WIN-NEXT: ret
107; X64_WIN-LABEL: f4:
108; X64_WIN:      movl _tls_index(%rip), %eax
109; X64_WIN-NEXT: movq %gs:88, %rcx
110; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
111; X64_WIN-NEXT: leaq i2@SECREL32(%rax), %rax
112; X64_WIN-NEXT: ret
113
114entry:
115	ret i32* @i2
116}
117
118define i32 @f5() nounwind {
119; X32_LINUX-LABEL: f5:
120; X32_LINUX:      movl %gs:i3@NTPOFF, %eax
121; X32_LINUX-NEXT: ret
122; X64_LINUX-LABEL: f5:
123; X64_LINUX:      movl %fs:i3@TPOFF, %eax
124; X64_LINUX-NEXT: ret
125; X32_WIN-LABEL: f5:
126; X32_WIN:      movl __tls_index, %eax
127; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
128; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
129; X32_WIN-NEXT: movl _i3@SECREL32(%eax), %eax
130; X32_WIN-NEXT: ret
131; X64_WIN-LABEL: f5:
132; X64_WIN:      movl _tls_index(%rip), %eax
133; X64_WIN-NEXT: movq %gs:88, %rcx
134; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
135; X64_WIN-NEXT: movl i3@SECREL32(%rax), %eax
136; X64_WIN-NEXT: ret
137
138entry:
139	%tmp1 = load i32* @i3
140	ret i32 %tmp1
141}
142
143define i32* @f6() {
144; X32_LINUX-LABEL: f6:
145; X32_LINUX:      movl %gs:0, %eax
146; X32_LINUX-NEXT: leal i3@NTPOFF(%eax), %eax
147; X32_LINUX-NEXT: ret
148; X64_LINUX-LABEL: f6:
149; X64_LINUX:      movq %fs:0, %rax
150; X64_LINUX-NEXT: leaq i3@TPOFF(%rax), %rax
151; X64_LINUX-NEXT: ret
152; X32_WIN-LABEL: f6:
153; X32_WIN:      movl __tls_index, %eax
154; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
155; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
156; X32_WIN-NEXT: leal _i3@SECREL32(%eax), %eax
157; X32_WIN-NEXT: ret
158; X64_WIN-LABEL: f6:
159; X64_WIN:      movl _tls_index(%rip), %eax
160; X64_WIN-NEXT: movq %gs:88, %rcx
161; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
162; X64_WIN-NEXT: leaq i3@SECREL32(%rax), %rax
163; X64_WIN-NEXT: ret
164
165entry:
166	ret i32* @i3
167}
168
169define i32 @f7() {
170; X32_LINUX-LABEL: f7:
171; X32_LINUX:      movl %gs:i4@NTPOFF, %eax
172; X32_LINUX-NEXT: ret
173; X64_LINUX-LABEL: f7:
174; X64_LINUX:      movl %fs:i4@TPOFF, %eax
175; X64_LINUX-NEXT: ret
176
177entry:
178	%tmp1 = load i32* @i4
179	ret i32 %tmp1
180}
181
182define i32* @f8() {
183; X32_LINUX-LABEL: f8:
184; X32_LINUX:      movl %gs:0, %eax
185; X32_LINUX-NEXT: leal i4@NTPOFF(%eax), %eax
186; X32_LINUX-NEXT: ret
187; X64_LINUX-LABEL: f8:
188; X64_LINUX:      movq %fs:0, %rax
189; X64_LINUX-NEXT: leaq i4@TPOFF(%rax), %rax
190; X64_LINUX-NEXT: ret
191
192entry:
193	ret i32* @i4
194}
195
196define i32 @f9() {
197; X32_LINUX-LABEL: f9:
198; X32_LINUX:      movl %gs:i5@NTPOFF, %eax
199; X32_LINUX-NEXT: ret
200; X64_LINUX-LABEL: f9:
201; X64_LINUX:      movl %fs:i5@TPOFF, %eax
202; X64_LINUX-NEXT: ret
203
204entry:
205	%tmp1 = load i32* @i5
206	ret i32 %tmp1
207}
208
209define i32* @f10() {
210; X32_LINUX-LABEL: f10:
211; X32_LINUX:      movl %gs:0, %eax
212; X32_LINUX-NEXT: leal i5@NTPOFF(%eax), %eax
213; X32_LINUX-NEXT: ret
214; X64_LINUX-LABEL: f10:
215; X64_LINUX:      movq %fs:0, %rax
216; X64_LINUX-NEXT: leaq i5@TPOFF(%rax), %rax
217; X64_LINUX-NEXT: ret
218
219entry:
220	ret i32* @i5
221}
222
223define i16 @f11() {
224; X32_LINUX-LABEL: f11:
225; X32_LINUX:      movzwl %gs:s1@NTPOFF, %eax
226; X32_LINUX:      ret
227; X64_LINUX-LABEL: f11:
228; X64_LINUX:      movzwl %fs:s1@TPOFF, %eax
229; X64_LINUX:      ret
230; X32_WIN-LABEL: f11:
231; X32_WIN:      movl __tls_index, %eax
232; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
233; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
234; X32_WIN-NEXT: movzwl _s1@SECREL32(%eax), %eax
235; X32_WIN:      ret
236; X64_WIN-LABEL: f11:
237; X64_WIN:      movl _tls_index(%rip), %eax
238; X64_WIN-NEXT: movq %gs:88, %rcx
239; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
240; X64_WIN-NEXT: movzwl s1@SECREL32(%rax), %eax
241; X64_WIN:      ret
242
243entry:
244	%tmp1 = load i16* @s1
245	ret i16 %tmp1
246}
247
248define i32 @f12() {
249; X32_LINUX-LABEL: f12:
250; X32_LINUX:      movswl %gs:s1@NTPOFF, %eax
251; X32_LINUX-NEXT: ret
252; X64_LINUX-LABEL: f12:
253; X64_LINUX:      movswl %fs:s1@TPOFF, %eax
254; X64_LINUX-NEXT: ret
255; X32_WIN-LABEL: f12:
256; X32_WIN:      movl __tls_index, %eax
257; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
258; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
259; X32_WIN-NEXT: movswl _s1@SECREL32(%eax), %eax
260; X32_WIN-NEXT: ret
261; X64_WIN-LABEL: f12:
262; X64_WIN:      movl _tls_index(%rip), %eax
263; X64_WIN-NEXT: movq %gs:88, %rcx
264; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
265; X64_WIN-NEXT: movswl s1@SECREL32(%rax), %eax
266; X64_WIN-NEXT: ret
267
268entry:
269	%tmp1 = load i16* @s1
270  %tmp2 = sext i16 %tmp1 to i32
271	ret i32 %tmp2
272}
273
274define i8 @f13() {
275; X32_LINUX-LABEL: f13:
276; X32_LINUX:      movb %gs:b1@NTPOFF, %al
277; X32_LINUX-NEXT: ret
278; X64_LINUX-LABEL: f13:
279; X64_LINUX:      movb %fs:b1@TPOFF, %al
280; X64_LINUX-NEXT: ret
281; X32_WIN-LABEL: f13:
282; X32_WIN:      movl __tls_index, %eax
283; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
284; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
285; X32_WIN-NEXT: movb _b1@SECREL32(%eax), %al
286; X32_WIN-NEXT: ret
287; X64_WIN-LABEL: f13:
288; X64_WIN:      movl _tls_index(%rip), %eax
289; X64_WIN-NEXT: movq %gs:88, %rcx
290; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
291; X64_WIN-NEXT: movb b1@SECREL32(%rax), %al
292; X64_WIN-NEXT: ret
293
294entry:
295	%tmp1 = load i8* @b1
296	ret i8 %tmp1
297}
298
299define i32 @f14() {
300; X32_LINUX-LABEL: f14:
301; X32_LINUX:      movsbl %gs:b1@NTPOFF, %eax
302; X32_LINUX-NEXT: ret
303; X64_LINUX-LABEL: f14:
304; X64_LINUX:      movsbl %fs:b1@TPOFF, %eax
305; X64_LINUX-NEXT: ret
306; X32_WIN-LABEL: f14:
307; X32_WIN:      movl __tls_index, %eax
308; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
309; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
310; X32_WIN-NEXT: movsbl _b1@SECREL32(%eax), %eax
311; X32_WIN-NEXT: ret
312; X64_WIN-LABEL: f14:
313; X64_WIN:      movl _tls_index(%rip), %eax
314; X64_WIN-NEXT: movq %gs:88, %rcx
315; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
316; X64_WIN-NEXT: movsbl b1@SECREL32(%rax), %eax
317; X64_WIN-NEXT: ret
318
319entry:
320	%tmp1 = load i8* @b1
321  %tmp2 = sext i8 %tmp1 to i32
322	ret i32 %tmp2
323}
324
325