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; RUN: llc < %s -march=x86 -mtriple=x86-pc-windows-gnu | FileCheck -check-prefix=MINGW32 %s
6; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-windows-gnu | FileCheck -check-prefix=X64_WIN %s
7
8@i1 = thread_local global i32 15
9@i2 = external thread_local global i32
10@i3 = internal thread_local global i32 15
11@i4 = hidden thread_local global i32 15
12@i5 = external hidden thread_local global i32
13@s1 = thread_local global i16 15
14@b1 = thread_local global i8 0
15
16define i32 @f1() {
17; X32_LINUX-LABEL: f1:
18; X32_LINUX:      movl %gs:i1@NTPOFF, %eax
19; X32_LINUX-NEXT: ret
20; X64_LINUX-LABEL: f1:
21; X64_LINUX:      movl %fs:i1@TPOFF, %eax
22; X64_LINUX-NEXT: ret
23; X32_WIN-LABEL: f1:
24; X32_WIN:      movl __tls_index, %eax
25; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
26; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
27; X32_WIN-NEXT: movl _i1@SECREL32(%eax), %eax
28; X32_WIN-NEXT: ret
29; X64_WIN-LABEL: f1:
30; X64_WIN:      movl _tls_index(%rip), %eax
31; X64_WIN-NEXT: movq %gs:88, %rcx
32; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
33; X64_WIN-NEXT: movl i1@SECREL32(%rax), %eax
34; X64_WIN-NEXT: ret
35; MINGW32-LABEL: _f1:
36; MINGW32: movl __tls_index, %eax
37; MINGW32-NEXT: movl %fs:44, %ecx
38; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
39; MINGW32-NEXT: movl _i1@SECREL32(%eax), %eax
40; MINGW32-NEXT: retl
41
42entry:
43	%tmp1 = load i32* @i1
44	ret i32 %tmp1
45}
46
47define i32* @f2() {
48; X32_LINUX-LABEL: f2:
49; X32_LINUX:      movl %gs:0, %eax
50; X32_LINUX-NEXT: leal i1@NTPOFF(%eax), %eax
51; X32_LINUX-NEXT: ret
52; X64_LINUX-LABEL: f2:
53; X64_LINUX:      movq %fs:0, %rax
54; X64_LINUX-NEXT: leaq i1@TPOFF(%rax), %rax
55; X64_LINUX-NEXT: ret
56; X32_WIN-LABEL: f2:
57; X32_WIN:      movl __tls_index, %eax
58; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
59; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
60; X32_WIN-NEXT: leal _i1@SECREL32(%eax), %eax
61; X32_WIN-NEXT: ret
62; X64_WIN-LABEL: f2:
63; X64_WIN:      movl _tls_index(%rip), %eax
64; X64_WIN-NEXT: movq %gs:88, %rcx
65; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
66; X64_WIN-NEXT: leaq i1@SECREL32(%rax), %rax
67; X64_WIN-NEXT: ret
68; MINGW32-LABEL: _f2:
69; MINGW32: movl __tls_index, %eax
70; MINGW32-NEXT: movl %fs:44, %ecx
71; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
72; MINGW32-NEXT: leal _i1@SECREL32(%eax), %eax
73; MINGW32-NEXT: retl
74
75entry:
76	ret i32* @i1
77}
78
79define i32 @f3() nounwind {
80; X32_LINUX-LABEL: f3:
81; X32_LINUX:      movl i2@INDNTPOFF, %eax
82; X32_LINUX-NEXT: movl %gs:(%eax), %eax
83; X32_LINUX-NEXT: ret
84; X64_LINUX-LABEL: f3:
85; X64_LINUX:      movq i2@GOTTPOFF(%rip), %rax
86; X64_LINUX-NEXT: movl %fs:(%rax), %eax
87; X64_LINUX-NEXT: ret
88; X32_WIN-LABEL: f3:
89; X32_WIN:      movl __tls_index, %eax
90; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
91; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
92; X32_WIN-NEXT: movl _i2@SECREL32(%eax), %eax
93; X32_WIN-NEXT: ret
94; X64_WIN-LABEL: f3:
95; X64_WIN:      movl _tls_index(%rip), %eax
96; X64_WIN-NEXT: movq %gs:88, %rcx
97; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
98; X64_WIN-NEXT: movl i2@SECREL32(%rax), %eax
99; X64_WIN-NEXT: ret
100; MINGW32-LABEL: _f3:
101; MINGW32: movl __tls_index, %eax
102; MINGW32-NEXT: movl %fs:44, %ecx
103; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
104; MINGW32-NEXT: movl _i2@SECREL32(%eax), %eax
105; MINGW32-NEXT: retl
106
107entry:
108	%tmp1 = load i32* @i2
109	ret i32 %tmp1
110}
111
112define i32* @f4() {
113; X32_LINUX-LABEL: f4:
114; X32_LINUX:      movl %gs:0, %eax
115; X32_LINUX-NEXT: addl i2@INDNTPOFF, %eax
116; X32_LINUX-NEXT: ret
117; X64_LINUX-LABEL: f4:
118; X64_LINUX:      movq %fs:0, %rax
119; X64_LINUX-NEXT: addq i2@GOTTPOFF(%rip), %rax
120; X64_LINUX-NEXT: ret
121; X32_WIN-LABEL: f4:
122; X32_WIN:      movl __tls_index, %eax
123; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
124; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
125; X32_WIN-NEXT: leal _i2@SECREL32(%eax), %eax
126; X32_WIN-NEXT: ret
127; X64_WIN-LABEL: f4:
128; X64_WIN:      movl _tls_index(%rip), %eax
129; X64_WIN-NEXT: movq %gs:88, %rcx
130; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
131; X64_WIN-NEXT: leaq i2@SECREL32(%rax), %rax
132; X64_WIN-NEXT: ret
133; MINGW32-LABEL: _f4:
134; MINGW32: movl __tls_index, %eax
135; MINGW32-NEXT: movl %fs:44, %ecx
136; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
137; MINGW32-NEXT: leal _i2@SECREL32(%eax), %eax
138; MINGW32-NEXT: retl
139
140entry:
141	ret i32* @i2
142}
143
144define i32 @f5() nounwind {
145; X32_LINUX-LABEL: f5:
146; X32_LINUX:      movl %gs:i3@NTPOFF, %eax
147; X32_LINUX-NEXT: ret
148; X64_LINUX-LABEL: f5:
149; X64_LINUX:      movl %fs:i3@TPOFF, %eax
150; X64_LINUX-NEXT: ret
151; X32_WIN-LABEL: f5:
152; X32_WIN:      movl __tls_index, %eax
153; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
154; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
155; X32_WIN-NEXT: movl _i3@SECREL32(%eax), %eax
156; X32_WIN-NEXT: ret
157; X64_WIN-LABEL: f5:
158; X64_WIN:      movl _tls_index(%rip), %eax
159; X64_WIN-NEXT: movq %gs:88, %rcx
160; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
161; X64_WIN-NEXT: movl i3@SECREL32(%rax), %eax
162; X64_WIN-NEXT: ret
163; MINGW32-LABEL: _f5:
164; MINGW32: movl __tls_index, %eax
165; MINGW32-NEXT: movl %fs:44, %ecx
166; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
167; MINGW32-NEXT: movl _i3@SECREL32(%eax), %eax
168; MINGW32-NEXT: retl
169
170entry:
171	%tmp1 = load i32* @i3
172	ret i32 %tmp1
173}
174
175define i32* @f6() {
176; X32_LINUX-LABEL: f6:
177; X32_LINUX:      movl %gs:0, %eax
178; X32_LINUX-NEXT: leal i3@NTPOFF(%eax), %eax
179; X32_LINUX-NEXT: ret
180; X64_LINUX-LABEL: f6:
181; X64_LINUX:      movq %fs:0, %rax
182; X64_LINUX-NEXT: leaq i3@TPOFF(%rax), %rax
183; X64_LINUX-NEXT: ret
184; X32_WIN-LABEL: f6:
185; X32_WIN:      movl __tls_index, %eax
186; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
187; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
188; X32_WIN-NEXT: leal _i3@SECREL32(%eax), %eax
189; X32_WIN-NEXT: ret
190; X64_WIN-LABEL: f6:
191; X64_WIN:      movl _tls_index(%rip), %eax
192; X64_WIN-NEXT: movq %gs:88, %rcx
193; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
194; X64_WIN-NEXT: leaq i3@SECREL32(%rax), %rax
195; X64_WIN-NEXT: ret
196; MINGW32-LABEL: _f6:
197; MINGW32: movl __tls_index, %eax
198; MINGW32-NEXT: movl %fs:44, %ecx
199; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
200; MINGW32-NEXT: leal _i3@SECREL32(%eax), %eax
201; MINGW32-NEXT: retl
202
203entry:
204	ret i32* @i3
205}
206
207define i32 @f7() {
208; X32_LINUX-LABEL: f7:
209; X32_LINUX:      movl %gs:i4@NTPOFF, %eax
210; X32_LINUX-NEXT: ret
211; X64_LINUX-LABEL: f7:
212; X64_LINUX:      movl %fs:i4@TPOFF, %eax
213; X64_LINUX-NEXT: ret
214; MINGW32-LABEL: _f7:
215; MINGW32: movl __tls_index, %eax
216; MINGW32-NEXT: movl %fs:44, %ecx
217; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
218; MINGW32-NEXT: movl _i4@SECREL32(%eax), %eax
219; MINGW32-NEXT: retl
220
221entry:
222	%tmp1 = load i32* @i4
223	ret i32 %tmp1
224}
225
226define i32* @f8() {
227; X32_LINUX-LABEL: f8:
228; X32_LINUX:      movl %gs:0, %eax
229; X32_LINUX-NEXT: leal i4@NTPOFF(%eax), %eax
230; X32_LINUX-NEXT: ret
231; X64_LINUX-LABEL: f8:
232; X64_LINUX:      movq %fs:0, %rax
233; X64_LINUX-NEXT: leaq i4@TPOFF(%rax), %rax
234; X64_LINUX-NEXT: ret
235; MINGW32-LABEL: _f8:
236; MINGW32: movl __tls_index, %eax
237; MINGW32-NEXT: movl %fs:44, %ecx
238; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
239; MINGW32-NEXT: leal _i4@SECREL32(%eax), %eax
240; MINGW32-NEXT: retl
241
242entry:
243	ret i32* @i4
244}
245
246define i32 @f9() {
247; X32_LINUX-LABEL: f9:
248; X32_LINUX:      movl %gs:i5@NTPOFF, %eax
249; X32_LINUX-NEXT: ret
250; X64_LINUX-LABEL: f9:
251; X64_LINUX:      movl %fs:i5@TPOFF, %eax
252; X64_LINUX-NEXT: ret
253; MINGW32-LABEL: _f9:
254; MINGW32: movl __tls_index, %eax
255; MINGW32-NEXT: movl %fs:44, %ecx
256; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
257; MINGW32-NEXT: movl _i5@SECREL32(%eax), %eax
258; MINGW32-NEXT: retl
259
260entry:
261	%tmp1 = load i32* @i5
262	ret i32 %tmp1
263}
264
265define i32* @f10() {
266; X32_LINUX-LABEL: f10:
267; X32_LINUX:      movl %gs:0, %eax
268; X32_LINUX-NEXT: leal i5@NTPOFF(%eax), %eax
269; X32_LINUX-NEXT: ret
270; X64_LINUX-LABEL: f10:
271; X64_LINUX:      movq %fs:0, %rax
272; X64_LINUX-NEXT: leaq i5@TPOFF(%rax), %rax
273; X64_LINUX-NEXT: ret
274; MINGW32-LABEL: _f10:
275; MINGW32: movl __tls_index, %eax
276; MINGW32-NEXT: movl %fs:44, %ecx
277; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
278; MINGW32-NEXT: leal _i5@SECREL32(%eax), %eax
279; MINGW32-NEXT: retl
280
281entry:
282	ret i32* @i5
283}
284
285define i16 @f11() {
286; X32_LINUX-LABEL: f11:
287; X32_LINUX:      movzwl %gs:s1@NTPOFF, %eax
288; X32_LINUX:      ret
289; X64_LINUX-LABEL: f11:
290; X64_LINUX:      movzwl %fs:s1@TPOFF, %eax
291; X64_LINUX:      ret
292; X32_WIN-LABEL: f11:
293; X32_WIN:      movl __tls_index, %eax
294; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
295; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
296; X32_WIN-NEXT: movzwl _s1@SECREL32(%eax), %eax
297; X32_WIN:      ret
298; X64_WIN-LABEL: f11:
299; X64_WIN:      movl _tls_index(%rip), %eax
300; X64_WIN-NEXT: movq %gs:88, %rcx
301; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
302; X64_WIN-NEXT: movzwl s1@SECREL32(%rax), %eax
303; X64_WIN:      ret
304; MINGW32-LABEL: _f11:
305; MINGW32: movl __tls_index, %eax
306; MINGW32-NEXT: movl %fs:44, %ecx
307; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
308; MINGW32-NEXT: movzwl  _s1@SECREL32(%eax), %eax
309; MINGW32: retl
310
311entry:
312	%tmp1 = load i16* @s1
313	ret i16 %tmp1
314}
315
316define i32 @f12() {
317; X32_LINUX-LABEL: f12:
318; X32_LINUX:      movswl %gs:s1@NTPOFF, %eax
319; X32_LINUX-NEXT: ret
320; X64_LINUX-LABEL: f12:
321; X64_LINUX:      movswl %fs:s1@TPOFF, %eax
322; X64_LINUX-NEXT: ret
323; X32_WIN-LABEL: f12:
324; X32_WIN:      movl __tls_index, %eax
325; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
326; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
327; X32_WIN-NEXT: movswl _s1@SECREL32(%eax), %eax
328; X32_WIN-NEXT: ret
329; X64_WIN-LABEL: f12:
330; X64_WIN:      movl _tls_index(%rip), %eax
331; X64_WIN-NEXT: movq %gs:88, %rcx
332; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
333; X64_WIN-NEXT: movswl s1@SECREL32(%rax), %eax
334; X64_WIN-NEXT: ret
335; MINGW32-LABEL: _f12:
336; MINGW32: movl __tls_index, %eax
337; MINGW32-NEXT: movl %fs:44, %ecx
338; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
339; MINGW32-NEXT: movswl _s1@SECREL32(%eax), %eax
340; MINGW32-NEXT: retl
341
342
343entry:
344	%tmp1 = load i16* @s1
345  %tmp2 = sext i16 %tmp1 to i32
346	ret i32 %tmp2
347}
348
349define i8 @f13() {
350; X32_LINUX-LABEL: f13:
351; X32_LINUX:      movb %gs:b1@NTPOFF, %al
352; X32_LINUX-NEXT: ret
353; X64_LINUX-LABEL: f13:
354; X64_LINUX:      movb %fs:b1@TPOFF, %al
355; X64_LINUX-NEXT: ret
356; X32_WIN-LABEL: f13:
357; X32_WIN:      movl __tls_index, %eax
358; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
359; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
360; X32_WIN-NEXT: movb _b1@SECREL32(%eax), %al
361; X32_WIN-NEXT: ret
362; X64_WIN-LABEL: f13:
363; X64_WIN:      movl _tls_index(%rip), %eax
364; X64_WIN-NEXT: movq %gs:88, %rcx
365; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
366; X64_WIN-NEXT: movb b1@SECREL32(%rax), %al
367; X64_WIN-NEXT: ret
368; MINGW32-LABEL: _f13:
369; MINGW32: movl __tls_index, %eax
370; MINGW32-NEXT: movl %fs:44, %ecx
371; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
372; MINGW32-NEXT: movb _b1@SECREL32(%eax), %al
373; MINGW32-NEXT: retl
374
375entry:
376	%tmp1 = load i8* @b1
377	ret i8 %tmp1
378}
379
380define i32 @f14() {
381; X32_LINUX-LABEL: f14:
382; X32_LINUX:      movsbl %gs:b1@NTPOFF, %eax
383; X32_LINUX-NEXT: ret
384; X64_LINUX-LABEL: f14:
385; X64_LINUX:      movsbl %fs:b1@TPOFF, %eax
386; X64_LINUX-NEXT: ret
387; X32_WIN-LABEL: f14:
388; X32_WIN:      movl __tls_index, %eax
389; X32_WIN-NEXT: movl %fs:__tls_array, %ecx
390; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax
391; X32_WIN-NEXT: movsbl _b1@SECREL32(%eax), %eax
392; X32_WIN-NEXT: ret
393; X64_WIN-LABEL: f14:
394; X64_WIN:      movl _tls_index(%rip), %eax
395; X64_WIN-NEXT: movq %gs:88, %rcx
396; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax
397; X64_WIN-NEXT: movsbl b1@SECREL32(%rax), %eax
398; X64_WIN-NEXT: ret
399; MINGW32-LABEL: _f14:
400; MINGW32: movl __tls_index, %eax
401; MINGW32-NEXT: movl %fs:44, %ecx
402; MINGW32-NEXT: movl (%ecx,%eax,4), %eax
403; MINGW32-NEXT: movsbl  _b1@SECREL32(%eax), %eax
404; MINGW32-NEXT: retl
405
406entry:
407	%tmp1 = load i8* @b1
408  %tmp2 = sext i8 %tmp1 to i32
409	ret i32 %tmp2
410}
411
412