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