1 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -verify-machineinstrs < %s | FileCheck %s 2 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s 3 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOLD %s 4 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-NOLD-RELOC %s 5 6 @general_dynamic_var = external thread_local global i32 7 8 define i32 @test_generaldynamic() { 9 ; CHECK-LABEL: test_generaldynamic: 10 11 %val = load i32, i32* @general_dynamic_var 12 ret i32 %val 13 14 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 15 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 16 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 17 ; CHECK-NEXT: .tlsdesccall general_dynamic_var 18 ; CHECK-NEXT: blr [[CALLEE]] 19 20 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 21 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 22 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 23 ; CHECK-NOLD-NEXT: .tlsdesccall general_dynamic_var 24 ; CHECK-NOLD-NEXT: blr [[CALLEE]] 25 26 27 ; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0 28 ; CHECK: ldr w0, [x[[TP]], x0] 29 ; CHECK-NOLD: mrs x[[TP:[0-9]+]], TPIDR_EL0 30 ; CHECK-NOLD: ldr w0, [x[[TP]], x0] 31 32 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 33 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 34 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 35 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 36 37 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 38 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 39 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 40 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 41 42 } 43 44 define i32* @test_generaldynamic_addr() { 45 ; CHECK-LABEL: test_generaldynamic_addr: 46 47 ret i32* @general_dynamic_var 48 49 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 50 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 51 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 52 ; CHECK-NEXT: .tlsdesccall general_dynamic_var 53 ; CHECK-NEXT: blr [[CALLEE]] 54 55 ; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0 56 ; CHECK: add x0, [[TP]], x0 57 58 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 59 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 60 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 61 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 62 63 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 64 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 65 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 66 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 67 68 } 69 70 @local_dynamic_var = external thread_local(localdynamic) global i32 71 72 define i32 @test_localdynamic() { 73 ; CHECK-LABEL: test_localdynamic: 74 75 %val = load i32, i32* @local_dynamic_var 76 ret i32 %val 77 78 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 79 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 80 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 81 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 82 ; CHECK-NEXT: blr [[CALLEE]] 83 ; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var 84 ; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var 85 ; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 86 ; CHECK: ldr w0, [x[[TPIDR]], x[[TPOFF]]] 87 88 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var 89 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] 90 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var 91 ; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var 92 ; CHECK-NOLD-NEXT: blr [[CALLEE]] 93 ; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 94 ; CHECK-NOLD: ldr w0, [x[[TPIDR]], x0] 95 96 97 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 98 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 99 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 100 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 101 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 102 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 103 104 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 105 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 106 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 107 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 108 109 } 110 111 define i32* @test_localdynamic_addr() { 112 ; CHECK-LABEL: test_localdynamic_addr: 113 114 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 115 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 116 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 117 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 118 ; CHECK-NEXT: blr [[CALLEE]] 119 ; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var 120 ; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var 121 ; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 122 ; CHECK: add x0, x[[TPIDR]], x[[TPOFF]] 123 124 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var 125 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] 126 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var 127 ; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var 128 ; CHECK-NOLD-NEXT: blr [[CALLEE]] 129 ; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 130 ; CHECK-NOLD: add x0, x[[TPIDR]], x0 131 ret i32* @local_dynamic_var 132 133 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 134 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 135 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 136 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 137 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 138 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 139 140 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 141 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 142 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 143 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 144 } 145 146 ; The entire point of the local-dynamic access model is to have a single call to 147 ; the expensive resolver. Make sure we achieve that goal. 148 149 @local_dynamic_var2 = external thread_local(localdynamic) global i32 150 151 define i32 @test_localdynamic_deduplicate() { 152 ; CHECK-LABEL: test_localdynamic_deduplicate: 153 154 %val = load i32, i32* @local_dynamic_var 155 %val2 = load i32, i32* @local_dynamic_var2 156 157 %sum = add i32 %val, %val2 158 ret i32 %sum 159 160 ; CHECK: adrp x[[DTPREL_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 161 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[DTPREL_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 162 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE 163 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 164 ; CHECK-NEXT: blr [[CALLEE]] 165 166 ; CHECK-NOT: _TLS_MODULE_BASE_ 167 168 ; CHECK: ret 169 } 170