[AArch64] Fix bug in prolog clobbering live reg when shrink wrapping.
[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 }
625
626 ; Make sure we do not assert when we do not track
627 ; all the aliases of a tuple register.
628 ; Indeed the tuple register can be tracked because of
629 ; one of its element, but the other elements of the tuple
630 ; do not need to be tracked and we used to assert on that.
631 ; Note: The test case is fragile in the sense that we need
632 ; a tuple register to appear in the lowering. Thus, the target
633 ; cpu is required to have the problem reproduced.
634 ; CHECK-LABEL: _uninterestingSub
635 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], [[CONSTPOOL:lCPI[0-9]+_[0-9]+]]@PAGE
636 ; CHECK-NEXT: ldr q[[IDX:[0-9]+]], {{\[}}[[ADRP_REG]], [[CONSTPOOL]]@PAGEOFF]
637 ; The tuple comes from the next instruction.
638 ; CHECK-NEXT: tbl.16b v{{[0-9]+}}, { v{{[0-9]+}}, v{{[0-9]+}} }, v[[IDX]]
639 ; CHECK: ret
640 define void @uninterestingSub(i8* nocapture %row) #0 {
641   %tmp = bitcast i8* %row to <16 x i8>*
642   %tmp1 = load <16 x i8>, <16 x i8>* %tmp, align 16
643   %vext43 = shufflevector <16 x i8> <i8 undef, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, <16 x i8> %tmp1, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
644   %add.i.414 = add <16 x i8> zeroinitializer, %vext43
645   store <16 x i8> %add.i.414, <16 x i8>* %tmp, align 16
646   %add.ptr51 = getelementptr inbounds i8, i8* %row, i64 16
647   %tmp2 = bitcast i8* %add.ptr51 to <16 x i8>*
648   %tmp3 = load <16 x i8>, <16 x i8>* %tmp2, align 16
649   %tmp4 = bitcast i8* undef to <16 x i8>*
650   %tmp5 = load <16 x i8>, <16 x i8>* %tmp4, align 16
651   %vext157 = shufflevector <16 x i8> %tmp3, <16 x i8> %tmp5, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
652   %add.i.402 = add <16 x i8> zeroinitializer, %vext157
653   store <16 x i8> %add.i.402, <16 x i8>* %tmp4, align 16
654   ret void
655 }
656
657 attributes #0 = { "target-cpu"="cyclone" }