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 ; FIXME: We currently produce "small" code for the tiny model
6 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -code-model=tiny -verify-machineinstrs < %s | FileCheck %s
7 ; FIXME: We currently error for the large code model
8 ; RUN: not llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -code-model=large -verify-machineinstrs < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LARGE
10 ; CHECK-LARGE: ELF TLS only supported in small memory model
12 @general_dynamic_var = external thread_local global i32
14 define i32 @test_generaldynamic() {
15 ; CHECK-LABEL: test_generaldynamic:
17 %val = load i32, i32* @general_dynamic_var
20 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
21 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
22 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
23 ; CHECK-NEXT: .tlsdesccall general_dynamic_var
24 ; CHECK-NEXT: blr [[CALLEE]]
26 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
27 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
28 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
29 ; CHECK-NOLD-NEXT: .tlsdesccall general_dynamic_var
30 ; CHECK-NOLD-NEXT: blr [[CALLEE]]
33 ; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0
34 ; CHECK: ldr w0, [x[[TP]], x0]
35 ; CHECK-NOLD: mrs x[[TP:[0-9]+]], TPIDR_EL0
36 ; CHECK-NOLD: ldr w0, [x[[TP]], x0]
38 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
39 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12
40 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12
41 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL
43 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
44 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12
45 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12
46 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL
50 define i32* @test_generaldynamic_addr() {
51 ; CHECK-LABEL: test_generaldynamic_addr:
53 ret i32* @general_dynamic_var
55 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
56 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
57 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
58 ; CHECK-NEXT: .tlsdesccall general_dynamic_var
59 ; CHECK-NEXT: blr [[CALLEE]]
61 ; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0
62 ; CHECK: add x0, [[TP]], x0
64 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
65 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12
66 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12
67 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL
69 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
70 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12
71 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12
72 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL
76 @local_dynamic_var = external thread_local(localdynamic) global i32
78 define i32 @test_localdynamic() {
79 ; CHECK-LABEL: test_localdynamic:
81 %val = load i32, i32* @local_dynamic_var
84 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_
85 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_]
86 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_
87 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_
88 ; CHECK-NEXT: blr [[CALLEE]]
89 ; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var
90 ; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var
91 ; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
92 ; CHECK: ldr w0, [x[[TPIDR]], x[[TPOFF]]]
94 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var
95 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var]
96 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var
97 ; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var
98 ; CHECK-NOLD-NEXT: blr [[CALLEE]]
99 ; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
100 ; CHECK-NOLD: ldr w0, [x[[TPIDR]], x0]
103 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
104 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12
105 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12
106 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL
107 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12
108 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC
110 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
111 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12
112 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12
113 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL
117 define i32* @test_localdynamic_addr() {
118 ; CHECK-LABEL: test_localdynamic_addr:
120 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_
121 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_]
122 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_
123 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_
124 ; CHECK-NEXT: blr [[CALLEE]]
125 ; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var
126 ; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var
127 ; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
128 ; CHECK: add x0, x[[TPIDR]], x[[TPOFF]]
130 ; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var
131 ; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var]
132 ; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var
133 ; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var
134 ; CHECK-NOLD-NEXT: blr [[CALLEE]]
135 ; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
136 ; CHECK-NOLD: add x0, x[[TPIDR]], x0
137 ret i32* @local_dynamic_var
139 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
140 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12
141 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12
142 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL
143 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12
144 ; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC
146 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
147 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12
148 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12
149 ; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL
152 ; The entire point of the local-dynamic access model is to have a single call to
153 ; the expensive resolver. Make sure we achieve that goal.
155 @local_dynamic_var2 = external thread_local(localdynamic) global i32
157 define i32 @test_localdynamic_deduplicate() {
158 ; CHECK-LABEL: test_localdynamic_deduplicate:
160 %val = load i32, i32* @local_dynamic_var
161 %val2 = load i32, i32* @local_dynamic_var2
163 %sum = add i32 %val, %val2
166 ; CHECK: adrp x[[DTPREL_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_
167 ; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[DTPREL_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_]
168 ; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE
169 ; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_
170 ; CHECK-NEXT: blr [[CALLEE]]
172 ; CHECK-NOT: _TLS_MODULE_BASE_