[AArch64][CollectLOH] Fix a regression that prevented us to detect chains of
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-collect-loh.ll
1 ; RUN: llc -mtriple=arm64-apple-ios -O2 -aarch64-collect-loh -aarch64-collect-loh-bb-only=false < %s -o - | FileCheck %s
2 ; RUN: llc -mtriple=arm64-linux-gnu -O2 -aarch64-collect-loh -aarch64-collect-loh-bb-only=false < %s -o - | FileCheck %s --check-prefix=CHECK-ELF
3
4 ; CHECK-ELF-NOT: .loh
5 ; CHECK-ELF-NOT: AdrpAdrp
6 ; CHECK-ELF-NOT: AdrpAdd
7 ; CHECK-ELF-NOT: AdrpLdrGot
8
9 @a = internal unnamed_addr global i32 0, align 4
10 @b = external global i32
11
12 ; Function Attrs: noinline nounwind ssp
13 define void @foo(i32 %t) {
14 entry:
15   %tmp = load i32, i32* @a, align 4
16   %add = add nsw i32 %tmp, %t
17   store i32 %add, i32* @a, align 4
18   ret void
19 }
20
21 ; Function Attrs: nounwind ssp
22 ; Testcase for <rdar://problem/15438605>, AdrpAdrp reuse is valid only when the first adrp
23 ; dominates the second.
24 ; The first adrp comes from the loading of 'a' and the second the loading of 'b'.
25 ; 'a' is loaded in if.then, 'b' in if.end4, if.then does not dominates if.end4.
26 ; CHECK-LABEL: _test
27 ; CHECK: ret
28 ; CHECK-NOT: .loh AdrpAdrp
29 define i32 @test(i32 %t) {
30 entry:
31   %cmp = icmp sgt i32 %t, 5
32   br i1 %cmp, label %if.then, label %if.end4
33
34 if.then:                                          ; preds = %entry
35   %tmp = load i32, i32* @a, align 4
36   %add = add nsw i32 %tmp, %t
37   %cmp1 = icmp sgt i32 %add, 12
38   br i1 %cmp1, label %if.then2, label %if.end4
39
40 if.then2:                                         ; preds = %if.then
41   tail call void @foo(i32 %add)
42   %tmp1 = load i32, i32* @a, align 4
43   br label %if.end4
44
45 if.end4:                                          ; preds = %if.then2, %if.then, %entry
46   %t.addr.0 = phi i32 [ %tmp1, %if.then2 ], [ %t, %if.then ], [ %t, %entry ]
47   %tmp2 = load i32, i32* @b, align 4
48   %add5 = add nsw i32 %tmp2, %t.addr.0
49   tail call void @foo(i32 %add5)
50   %tmp3 = load i32, i32* @b, align 4
51   %add6 = add nsw i32 %tmp3, %t.addr.0
52   ret i32 %add6
53 }
54
55 @C = common global i32 0, align 4
56
57 ; Check that we catch AdrpLdrGotLdr case when we have a simple chain:
58 ; adrp -> ldrgot -> ldr.
59 ; CHECK-LABEL: _getC
60 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
61 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
62 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
63 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
64 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
65 ; CHECK-NEXT: ldr w0, {{\[}}[[LDRGOT_REG]]]
66 ; CHECK-NEXT: ret
67 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
68 define i32 @getC() {
69   %res = load i32, i32* @C, align 4
70   ret i32 %res
71 }
72
73 ; LDRSW supports loading from a literal.
74 ; Make sure we emit AdrpLdrGotLdr for those.
75 ; CHECK-LABEL: _getSExtC
76 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
77 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
78 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
79 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
80 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
81 ; CHECK-NEXT: ldrsw x0, {{\[}}[[LDRGOT_REG]]]
82 ; CHECK-NEXT: ret
83 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
84 define i64 @getSExtC() {
85   %res = load i32, i32* @C, align 4
86   %sextres = sext i32 %res to i64
87   ret i64 %sextres
88 }
89
90 ; It may not be safe to fold the literal in the load if the address is
91 ; used several times.
92 ; Make sure we emit AdrpLdrGot for those.
93 ; CHECK-LABEL: _getSeveralC
94 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
95 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
96 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
97 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
98 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[LDRGOT_REG]]]
99 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
100 ; CHECK-NEXT: str [[ADD]], {{\[}}[[LDRGOT_REG]]]
101 ; CHECK-NEXT: ret
102 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
103 define void @getSeveralC(i32 %t) {
104 entry:
105   %tmp = load i32, i32* @C, align 4
106   %add = add nsw i32 %tmp, %t
107   store i32 %add, i32* @C, align 4
108   ret void
109 }
110
111 ; Make sure we catch that:
112 ; adrp -> ldrgot -> str.
113 ; CHECK-LABEL: _setC
114 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
115 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
116 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
117 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
118 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
119 ; CHECK-NEXT: str w0, {{\[}}[[LDRGOT_REG]]]
120 ; CHECK-NEXT: ret
121 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
122 define void @setC(i32 %t) {
123 entry:
124   store i32 %t, i32* @C, align 4
125   ret void
126 }
127
128 ; Perform the same tests for internal global and a displacement
129 ; in the addressing mode.
130 ; Indeed we will get an ADD for those instead of LOADGot.
131 @InternalC = internal global i32 0, align 4
132
133 ; Check that we catch AdrpAddLdr case when we have a simple chain:
134 ; adrp -> add -> ldr.
135 ; CHECK-LABEL: _getInternalCPlus4
136 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
137 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
138 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
139 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
140 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
141 ; CHECK-NEXT: ldr w0, {{\[}}[[ADDGOT_REG]], #16]
142 ; CHECK-NEXT: ret
143 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
144 define i32 @getInternalCPlus4() {
145   %addr = getelementptr i32, i32* @InternalC, i32 4
146   %res = load i32, i32* %addr, align 4
147   ret i32 %res
148 }
149
150 ; LDRSW supports loading from a literal.
151 ; Make sure we emit AdrpLdrGotLdr for those.
152 ; CHECK-LABEL: _getSExtInternalCPlus4
153 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
154 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
155 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
156 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
157 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
158 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADDGOT_REG]], #16]
159 ; CHECK-NEXT: ret
160 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
161 define i64 @getSExtInternalCPlus4() {
162   %addr = getelementptr i32, i32* @InternalC, i32 4
163   %res = load i32, i32* %addr, align 4
164   %sextres = sext i32 %res to i64
165   ret i64 %sextres
166 }
167
168 ; It may not be safe to fold the literal in the load if the address is
169 ; used several times.
170 ; Make sure we emit AdrpAdd for those.
171 ; CHECK-LABEL: _getSeveralInternalCPlus4
172 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
173 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
174 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
175 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
176 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADDGOT_REG]], #16]
177 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
178 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADDGOT_REG]], #16]
179 ; CHECK-NEXT: ret
180 ; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]]
181 define void @getSeveralInternalCPlus4(i32 %t) {
182 entry:
183   %addr = getelementptr i32, i32* @InternalC, i32 4
184   %tmp = load i32, i32* %addr, align 4
185   %add = add nsw i32 %tmp, %t
186   store i32 %add, i32* %addr, align 4
187   ret void
188 }
189
190 ; Make sure we catch that:
191 ; adrp -> add -> str.
192 ; CHECK-LABEL: _setInternalCPlus4
193 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
194 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
195 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
196 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
197 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
198 ; CHECK-NEXT: str w0, {{\[}}[[ADDGOT_REG]], #16]
199 ; CHECK-NEXT: ret
200 ; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
201 define void @setInternalCPlus4(i32 %t) {
202 entry:
203   %addr = getelementptr i32, i32* @InternalC, i32 4
204   store i32 %t, i32* %addr, align 4
205   ret void
206 }
207
208 ; Check that we catch AdrpAddLdr case when we have a simple chain:
209 ; adrp -> ldr.
210 ; CHECK-LABEL: _getInternalC
211 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
212 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
213 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
214 ; CHECK-NEXT: ldr w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
215 ; CHECK-NEXT: ret
216 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
217 define i32 @getInternalC() {
218   %res = load i32, i32* @InternalC, align 4
219   ret i32 %res
220 }
221
222 ; LDRSW supports loading from a literal.
223 ; Make sure we emit AdrpLdrGotLdr for those.
224 ; CHECK-LABEL: _getSExtInternalC
225 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
226 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
227 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
228 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
229 ; CHECK-NEXT: ret
230 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
231 define i64 @getSExtInternalC() {
232   %res = load i32, i32* @InternalC, align 4
233   %sextres = sext i32 %res to i64
234   ret i64 %sextres
235 }
236
237 ; It may not be safe to fold the literal in the load if the address is
238 ; used several times.
239 ; Make sure we do not catch anything here. We have a adrp alone,
240 ; there is not much we can do about it.
241 ; CHECK-LABEL: _getSeveralInternalC
242 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
243 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
244 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
245 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
246 ; CHECK-NEXT: ret
247 define void @getSeveralInternalC(i32 %t) {
248 entry:
249   %tmp = load i32, i32* @InternalC, align 4
250   %add = add nsw i32 %tmp, %t
251   store i32 %add, i32* @InternalC, align 4
252   ret void
253 }
254
255 ; Make sure we do not catch anything when:
256 ; adrp -> str.
257 ; We cannot fold anything in the str at this point.
258 ; Indeed, strs do not support litterals.
259 ; CHECK-LABEL: _setInternalC
260 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
261 ; CHECK-NEXT: str w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
262 ; CHECK-NEXT: ret
263 define void @setInternalC(i32 %t) {
264 entry:
265   store i32 %t, i32* @InternalC, align 4
266   ret void
267 }
268
269 ; Now check other variant of loads/stores.
270
271 @D = common global i8 0, align 4
272
273 ; LDRB does not support loading from a literal.
274 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
275 ; CHECK-LABEL: _getD
276 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
277 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
278 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
279 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
280 ; CHECK-NEXT: ldrb w0, {{\[}}[[LDRGOT_REG]]]
281 ; CHECK-NEXT: ret
282 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
283 define i8 @getD() {
284   %res = load i8, i8* @D, align 4
285   ret i8 %res
286 }
287
288 ; CHECK-LABEL: _setD
289 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
290 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
291 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
292 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
293 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
294 ; CHECK-NEXT: strb w0, {{\[}}[[LDRGOT_REG]]]
295 ; CHECK-NEXT: ret
296 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
297 define void @setD(i8 %t) {
298   store i8 %t, i8* @D, align 4
299   ret void
300 }
301
302 ; LDRSB supports loading from a literal.
303 ; Make sure we emit AdrpLdrGotLdr for those.
304 ; CHECK-LABEL: _getSExtD
305 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
306 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
307 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
308 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
309 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
310 ; CHECK-NEXT: ldrsb w0, {{\[}}[[LDRGOT_REG]]]
311 ; CHECK-NEXT: ret
312 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
313 define i32 @getSExtD() {
314   %res = load i8, i8* @D, align 4
315   %sextres = sext i8 %res to i32
316   ret i32 %sextres
317 }
318
319 ; LDRSB supports loading from a literal.
320 ; Make sure we emit AdrpLdrGotLdr for those.
321 ; CHECK-LABEL: _getSExt64D
322 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
323 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
324 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
325 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
326 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
327 ; CHECK-NEXT: ldrsb x0, {{\[}}[[LDRGOT_REG]]]
328 ; CHECK-NEXT: ret
329 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
330 define i64 @getSExt64D() {
331   %res = load i8, i8* @D, align 4
332   %sextres = sext i8 %res to i64
333   ret i64 %sextres
334 }
335
336 @E = common global i16 0, align 4
337
338 ; LDRH does not support loading from a literal.
339 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
340 ; CHECK-LABEL: _getE
341 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
342 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
343 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
344 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
345 ; CHECK-NEXT: ldrh w0, {{\[}}[[LDRGOT_REG]]]
346 ; CHECK-NEXT: ret
347 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
348 define i16 @getE() {
349   %res = load i16, i16* @E, align 4
350   ret i16 %res
351 }
352
353 ; LDRSH supports loading from a literal.
354 ; Make sure we emit AdrpLdrGotLdr for those.
355 ; CHECK-LABEL: _getSExtE
356 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
357 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
358 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
359 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
360 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
361 ; CHECK-NEXT: ldrsh w0, {{\[}}[[LDRGOT_REG]]]
362 ; CHECK-NEXT: ret
363 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
364 define i32 @getSExtE() {
365   %res = load i16, i16* @E, align 4
366   %sextres = sext i16 %res to i32
367   ret i32 %sextres
368 }
369
370 ; CHECK-LABEL: _setE
371 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
372 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
373 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
374 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
375 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
376 ; CHECK-NEXT: strh w0, {{\[}}[[LDRGOT_REG]]]
377 ; CHECK-NEXT: ret
378 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
379 define void @setE(i16 %t) {
380   store i16 %t, i16* @E, align 4
381   ret void
382 }
383
384 ; LDRSH supports loading from a literal.
385 ; Make sure we emit AdrpLdrGotLdr for those.
386 ; CHECK-LABEL: _getSExt64E
387 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
388 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
389 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
390 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
391 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
392 ; CHECK-NEXT: ldrsh x0, {{\[}}[[LDRGOT_REG]]]
393 ; CHECK-NEXT: ret
394 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
395 define i64 @getSExt64E() {
396   %res = load i16, i16* @E, align 4
397   %sextres = sext i16 %res to i64
398   ret i64 %sextres
399 }
400
401 @F = common global i64 0, align 4
402
403 ; LDR supports loading from a literal.
404 ; Make sure we emit AdrpLdrGotLdr for those.
405 ; CHECK-LABEL: _getF
406 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
407 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
408 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
409 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
410 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
411 ; CHECK-NEXT: ldr x0, {{\[}}[[LDRGOT_REG]]]
412 ; CHECK-NEXT: ret
413 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
414 define i64 @getF() {
415   %res = load i64, i64* @F, align 4
416   ret i64 %res
417 }
418
419 ; CHECK-LABEL: _setF
420 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
421 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
422 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
423 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
424 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
425 ; CHECK-NEXT: str x0, {{\[}}[[LDRGOT_REG]]]
426 ; CHECK-NEXT: ret
427 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
428 define void @setF(i64 %t) {
429   store i64 %t, i64* @F, align 4
430   ret void
431 }
432
433 @G = common global float 0.0, align 4
434
435 ; LDR float supports loading from a literal.
436 ; Make sure we emit AdrpLdrGotLdr for those.
437 ; CHECK-LABEL: _getG
438 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
439 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
440 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
441 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
442 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
443 ; CHECK-NEXT: ldr s0, {{\[}}[[LDRGOT_REG]]]
444 ; CHECK-NEXT: ret
445 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
446 define float @getG() {
447   %res = load float, float* @G, align 4
448   ret float %res
449 }
450
451 ; CHECK-LABEL: _setG
452 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
453 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
454 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
455 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
456 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
457 ; CHECK-NEXT: str s0, {{\[}}[[LDRGOT_REG]]]
458 ; CHECK-NEXT: ret
459 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
460 define void @setG(float %t) {
461   store float %t, float* @G, align 4
462   ret void
463 }
464
465 @H = common global half 0.0, align 4
466
467 ; LDR half supports loading from a literal.
468 ; Make sure we emit AdrpLdrGotLdr for those.
469 ; CHECK-LABEL: _getH
470 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
471 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
472 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
473 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
474 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
475 ; CHECK-NEXT: ldr h0, {{\[}}[[LDRGOT_REG]]]
476 ; CHECK-NEXT: ret
477 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
478 define half @getH() {
479   %res = load half, half* @H, align 4
480   ret half %res
481 }
482
483 ; CHECK-LABEL: _setH
484 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
485 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
486 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
487 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
488 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
489 ; CHECK-NEXT: str h0, {{\[}}[[LDRGOT_REG]]]
490 ; CHECK-NEXT: ret
491 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
492 define void @setH(half %t) {
493   store half %t, half* @H, align 4
494   ret void
495 }
496
497 @I = common global double 0.0, align 4
498
499 ; LDR double supports loading from a literal.
500 ; Make sure we emit AdrpLdrGotLdr for those.
501 ; CHECK-LABEL: _getI
502 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
503 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
504 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
505 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
506 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
507 ; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
508 ; CHECK-NEXT: ret
509 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
510 define double @getI() {
511   %res = load double, double* @I, align 4
512   ret double %res
513 }
514
515 ; CHECK-LABEL: _setI
516 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
517 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
518 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
519 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
520 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
521 ; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
522 ; CHECK-NEXT: ret
523 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
524 define void @setI(double %t) {
525   store double %t, double* @I, align 4
526   ret void
527 }
528
529 @J = common global <2 x i32> <i32 0, i32 0>, align 4
530
531 ; LDR 64-bit vector supports loading from a literal.
532 ; Make sure we emit AdrpLdrGotLdr for those.
533 ; CHECK-LABEL: _getJ
534 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
535 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
536 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
537 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
538 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
539 ; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
540 ; CHECK-NEXT: ret
541 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
542 define <2 x i32> @getJ() {
543   %res = load <2 x i32>, <2 x i32>* @J, align 4
544   ret <2 x i32> %res
545 }
546
547 ; CHECK-LABEL: _setJ
548 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
549 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
550 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
551 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
552 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
553 ; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
554 ; CHECK-NEXT: ret
555 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
556 define void @setJ(<2 x i32> %t) {
557   store <2 x i32> %t, <2 x i32>* @J, align 4
558   ret void
559 }
560
561 @K = common global <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 4
562
563 ; LDR 128-bit vector supports loading from a literal.
564 ; Make sure we emit AdrpLdrGotLdr for those.
565 ; CHECK-LABEL: _getK
566 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
567 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
568 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
569 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
570 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
571 ; CHECK-NEXT: ldr q0, {{\[}}[[LDRGOT_REG]]]
572 ; CHECK-NEXT: ret
573 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
574 define <4 x i32> @getK() {
575   %res = load <4 x i32>, <4 x i32>* @K, align 4
576   ret <4 x i32> %res
577 }
578
579 ; CHECK-LABEL: _setK
580 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
581 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
582 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
583 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
584 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
585 ; CHECK-NEXT: str q0, {{\[}}[[LDRGOT_REG]]]
586 ; CHECK-NEXT: ret
587 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
588 define void @setK(<4 x i32> %t) {
589   store <4 x i32> %t, <4 x i32>* @K, align 4
590   ret void
591 }
592
593 @L = common global <1 x i8> <i8 0>, align 4
594
595 ; LDR 8-bit vector supports loading from a literal.
596 ; Make sure we emit AdrpLdrGotLdr for those.
597 ; CHECK-LABEL: _getL
598 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
599 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
600 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
601 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
602 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
603 ; CHECK-NEXT: ldr b0, {{\[}}[[LDRGOT_REG]]]
604 ; CHECK-NEXT: ret
605 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
606 define <1 x i8> @getL() {
607   %res = load <1 x i8>, <1 x i8>* @L, align 4
608   ret <1 x i8> %res
609 }
610
611 ; CHECK-LABEL: _setL
612 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
613 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
614 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
615 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
616 ; Ultimately we should generate str b0, but right now, we match the vector
617 ; variant which does not allow to fold the immediate into the store.
618 ; CHECK-NEXT: st1.b { v0 }[0], {{\[}}[[LDRGOT_REG]]]
619 ; CHECK-NEXT: ret
620 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
621 define void @setL(<1 x i8> %t) {
622   store <1 x i8> %t, <1 x i8>* @L, align 4
623   ret void
624 }