Merging r258471:
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-tls-dynamics.ll
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 }