1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 2; RUN: llc < %s -mtriple=i686 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X86 3; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X32 4; RUN: llc < %s -mtriple=x86_64 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X64 5 6@x = thread_local global i32 0, align 4 7@y = internal thread_local global i32 1, align 4 8@z = external hidden thread_local global i32, align 4 9 10define ptr @f1() nounwind { 11; X86-LABEL: f1: 12; X86: # %bb.0: 13; X86-NEXT: pushl %ebp 14; X86-NEXT: pushl %ebx 15; X86-NEXT: pushl %edi 16; X86-NEXT: pushl %esi 17; X86-NEXT: pushl %eax 18; X86-NEXT: calll .L0$pb 19; X86-NEXT: .L0$pb: 20; X86-NEXT: popl %ebx 21; X86-NEXT: .Ltmp0: 22; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %ebx 23; X86-NEXT: #APP 24; X86-NEXT: #NO_APP 25; X86-NEXT: movl %eax, (%esp) # 4-byte Spill 26; X86-NEXT: leal x@tlsdesc(%ebx), %eax 27; X86-NEXT: calll *x@tlscall(%eax) 28; X86-NEXT: addl %gs:0, %eax 29; X86-NEXT: movl (%esp), %ebx # 4-byte Reload 30; X86-NEXT: #APP 31; X86-NEXT: #NO_APP 32; X86-NEXT: addl $4, %esp 33; X86-NEXT: popl %esi 34; X86-NEXT: popl %edi 35; X86-NEXT: popl %ebx 36; X86-NEXT: popl %ebp 37; X86-NEXT: retl 38; 39; X32-LABEL: f1: 40; X32: # %bb.0: 41; X32-NEXT: pushq %rax 42; X32-NEXT: #APP 43; X32-NEXT: #NO_APP 44; X32-NEXT: leal x@tlsdesc(%rip), %eax 45; X32-NEXT: callq *x@tlscall(%eax) 46; X32-NEXT: # kill: def $eax killed $eax def $rax 47; X32-NEXT: addl %fs:0, %eax 48; X32-NEXT: #APP 49; X32-NEXT: #NO_APP 50; X32-NEXT: popq %rcx 51; X32-NEXT: retq 52; 53; X64-LABEL: f1: 54; X64: # %bb.0: 55; X64-NEXT: pushq %rax 56; X64-NEXT: #APP 57; X64-NEXT: #NO_APP 58; X64-NEXT: leaq x@tlsdesc(%rip), %rax 59; X64-NEXT: callq *x@tlscall(%rax) 60; X64-NEXT: addq %fs:0, %rax 61; X64-NEXT: #APP 62; X64-NEXT: #NO_APP 63; X64-NEXT: popq %rcx 64; X64-NEXT: retq 65 %a = call { i32, i32, i32, i32, i32, i32 } asm sideeffect "", "=r,=r,=r,=r,=r,=r,~{dirflag},~{fpsr},~{flags}"() 66 %b = call ptr @llvm.threadlocal.address.p0(ptr @x) 67 %a.0 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 0 68 %a.1 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 1 69 %a.2 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 2 70 %a.3 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 3 71 %a.4 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 4 72 %a.5 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 5 73 call void asm sideeffect "", "r,r,r,r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %a.0, i32 %a.1, i32 %a.2, i32 %a.3, i32 %a.4, i32 %a.5) 74 ret ptr %b 75} 76 77define i32 @f2() nounwind { 78; X86-LABEL: f2: 79; X86: # %bb.0: 80; X86-NEXT: pushl %ebx 81; X86-NEXT: calll .L1$pb 82; X86-NEXT: .L1$pb: 83; X86-NEXT: popl %ebx 84; X86-NEXT: .Ltmp1: 85; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.L1$pb), %ebx 86; X86-NEXT: movl %gs:0, %ecx 87; X86-NEXT: leal x@tlsdesc(%ebx), %eax 88; X86-NEXT: calll *x@tlscall(%eax) 89; X86-NEXT: movl (%eax,%ecx), %eax 90; X86-NEXT: popl %ebx 91; X86-NEXT: retl 92; 93; X32-LABEL: f2: 94; X32: # %bb.0: 95; X32-NEXT: pushq %rax 96; X32-NEXT: movl %fs:0, %ecx 97; X32-NEXT: leal x@tlsdesc(%rip), %eax 98; X32-NEXT: callq *x@tlscall(%eax) 99; X32-NEXT: movl (%eax,%ecx), %eax 100; X32-NEXT: popq %rcx 101; X32-NEXT: retq 102; 103; X64-LABEL: f2: 104; X64: # %bb.0: 105; X64-NEXT: pushq %rax 106; X64-NEXT: movq %fs:0, %rcx 107; X64-NEXT: leaq x@tlsdesc(%rip), %rax 108; X64-NEXT: callq *x@tlscall(%rax) 109; X64-NEXT: movl (%rax,%rcx), %eax 110; X64-NEXT: popq %rcx 111; X64-NEXT: retq 112 %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x) 113 %2 = load i32, ptr %1 114 ret i32 %2 115} 116 117define ptr @f3() nounwind { 118; X86-LABEL: f3: 119; X86: # %bb.0: 120; X86-NEXT: pushl %ebx 121; X86-NEXT: calll .L2$pb 122; X86-NEXT: .L2$pb: 123; X86-NEXT: popl %ebx 124; X86-NEXT: .Ltmp2: 125; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.L2$pb), %ebx 126; X86-NEXT: leal x@tlsdesc(%ebx), %eax 127; X86-NEXT: calll *x@tlscall(%eax) 128; X86-NEXT: addl %gs:0, %eax 129; X86-NEXT: popl %ebx 130; X86-NEXT: retl 131; 132; X32-LABEL: f3: 133; X32: # %bb.0: 134; X32-NEXT: pushq %rax 135; X32-NEXT: leal x@tlsdesc(%rip), %eax 136; X32-NEXT: callq *x@tlscall(%eax) 137; X32-NEXT: # kill: def $eax killed $eax def $rax 138; X32-NEXT: addl %fs:0, %eax 139; X32-NEXT: popq %rcx 140; X32-NEXT: retq 141; 142; X64-LABEL: f3: 143; X64: # %bb.0: 144; X64-NEXT: pushq %rax 145; X64-NEXT: leaq x@tlsdesc(%rip), %rax 146; X64-NEXT: callq *x@tlscall(%rax) 147; X64-NEXT: addq %fs:0, %rax 148; X64-NEXT: popq %rcx 149; X64-NEXT: retq 150 %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x) 151 ret ptr %1 152} 153 154define i32 @f4() nounwind { 155; X86-LABEL: f4: 156; X86: # %bb.0: 157; X86-NEXT: pushl %ebx 158; X86-NEXT: calll .L3$pb 159; X86-NEXT: .L3$pb: 160; X86-NEXT: popl %ebx 161; X86-NEXT: .Ltmp3: 162; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp3-.L3$pb), %ebx 163; X86-NEXT: movl %gs:0, %edx 164; X86-NEXT: leal _TLS_MODULE_BASE_@tlsdesc(%ebx), %eax 165; X86-NEXT: calll *_TLS_MODULE_BASE_@tlscall(%eax) 166; X86-NEXT: movl y@DTPOFF(%eax,%edx), %ecx 167; X86-NEXT: addl z@DTPOFF(%eax,%edx), %ecx 168; X86-NEXT: movl %ecx, %eax 169; X86-NEXT: popl %ebx 170; X86-NEXT: retl 171; 172; X32-LABEL: f4: 173; X32: # %bb.0: 174; X32-NEXT: pushq %rax 175; X32-NEXT: movl %fs:0, %edx 176; X32-NEXT: leal _TLS_MODULE_BASE_@tlsdesc(%rip), %eax 177; X32-NEXT: callq *_TLS_MODULE_BASE_@tlscall(%eax) 178; X32-NEXT: movl y@DTPOFF(%eax,%edx), %ecx 179; X32-NEXT: addl z@DTPOFF(%eax,%edx), %ecx 180; X32-NEXT: movl %ecx, %eax 181; X32-NEXT: popq %rcx 182; X32-NEXT: retq 183; 184; X64-LABEL: f4: 185; X64: # %bb.0: 186; X64-NEXT: pushq %rax 187; X64-NEXT: movq %fs:0, %rdx 188; X64-NEXT: leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax 189; X64-NEXT: callq *_TLS_MODULE_BASE_@tlscall(%rax) 190; X64-NEXT: movl y@DTPOFF(%rax,%rdx), %ecx 191; X64-NEXT: addl z@DTPOFF(%rax,%rdx), %ecx 192; X64-NEXT: movl %ecx, %eax 193; X64-NEXT: popq %rcx 194; X64-NEXT: retq 195 %1 = load i32, ptr @y, align 4 196 %2 = load i32, ptr @z, align 4 197 %3 = add nsw i32 %1, %2 198 ret i32 %3 199} 200