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