Revert 374373: [Codegen] Alter the default promotion for saturating adds and subs
[llvm-core.git] / test / CodeGen / AArch64 / arm64-collect-loh.ll
blob816e5a7cc6fbce87c8b9e442885aaa9902c6029d
1 ; RUN: llc -o - %s -mtriple=arm64-apple-ios -O2 | FileCheck %s
2 ; RUN: llc -o - %s -mtriple=arm64_32-apple-watchos -O2 | FileCheck %s
3 ; RUN: llc -o - %s -mtriple=arm64-linux-gnu -O2 | FileCheck %s --check-prefix=CHECK-ELF
5 ; CHECK-ELF-NOT: .loh
6 ; CHECK-ELF-NOT: AdrpAdrp
7 ; CHECK-ELF-NOT: AdrpAdd
8 ; CHECK-ELF-NOT: AdrpLdrGot
10 @a = internal unnamed_addr global i32 0, align 4
11 @b = external global i32
13 ; Function Attrs: noinline nounwind ssp
14 define void @foo(i32 %t) {
15 entry:
16   %tmp = load i32, i32* @a, align 4
17   %add = add nsw i32 %tmp, %t
18   store i32 %add, i32* @a, align 4
19   ret void
22 ; Function Attrs: nounwind ssp
23 ; Testcase for <rdar://problem/15438605>, AdrpAdrp reuse is valid only when the first adrp
24 ; dominates the second.
25 ; The first adrp comes from the loading of 'a' and the second the loading of 'b'.
26 ; 'a' is loaded in if.then, 'b' in if.end4, if.then does not dominates if.end4.
27 ; CHECK-LABEL: _test
28 ; CHECK: ret
29 ; CHECK-NOT: .loh AdrpAdrp
30 define i32 @test(i32 %t) {
31 entry:
32   %cmp = icmp sgt i32 %t, 5
33   br i1 %cmp, label %if.then, label %if.end4
35 if.then:                                          ; preds = %entry
36   %tmp = load i32, i32* @a, align 4
37   %add = add nsw i32 %tmp, %t
38   %cmp1 = icmp sgt i32 %add, 12
39   br i1 %cmp1, label %if.then2, label %if.end4
41 if.then2:                                         ; preds = %if.then
42   tail call void @foo(i32 %add)
43   %tmp1 = load i32, i32* @a, align 4
44   br label %if.end4
46 if.end4:                                          ; preds = %if.then2, %if.then, %entry
47   %t.addr.0 = phi i32 [ %tmp1, %if.then2 ], [ %t, %if.then ], [ %t, %entry ]
48   %tmp2 = load i32, i32* @b, align 4
49   %add5 = add nsw i32 %tmp2, %t.addr.0
50   tail call void @foo(i32 %add5)
51   %tmp3 = load i32, i32* @b, align 4
52   %add6 = add nsw i32 %tmp3, %t.addr.0
53   ret i32 %add6
56 @C = common global i32 0, align 4
58 ; Check that we catch AdrpLdrGotLdr case when we have a simple chain:
59 ; adrp -> ldrgot -> ldr.
60 ; CHECK-LABEL: _getC
61 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
62 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
63 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
64 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
65 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
66 ; CHECK-NEXT: ldr w0, [x[[LDRGOT_REG]]]
67 ; CHECK-NEXT: ret
68 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
69 define i32 @getC() {
70   %res = load i32, i32* @C, align 4
71   ret i32 %res
74 ; LDRSW supports loading from a literal.
75 ; Make sure we emit AdrpLdrGotLdr for those.
76 ; CHECK-LABEL: _getSExtC
77 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
78 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
79 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
80 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
81 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
82 ; CHECK-NEXT: ldrsw x0, [x[[LDRGOT_REG]]]
83 ; CHECK-NEXT: ret
84 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
85 define i64 @getSExtC() {
86   %res = load i32, i32* @C, align 4
87   %sextres = sext i32 %res to i64
88   ret i64 %sextres
91 ; It may not be safe to fold the literal in the load if the address is
92 ; used several times.
93 ; Make sure we emit AdrpLdrGot for those.
94 ; CHECK-LABEL: _getSeveralC
95 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
96 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
97 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
98 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
99 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], [x[[LDRGOT_REG]]]
100 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
101 ; CHECK-NEXT: str [[ADD]], [x[[LDRGOT_REG]]]
102 ; CHECK-NEXT: ret
103 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
104 define void @getSeveralC(i32 %t) {
105 entry:
106   %tmp = load i32, i32* @C, align 4
107   %add = add nsw i32 %tmp, %t
108   store i32 %add, i32* @C, align 4
109   ret void
112 ; Make sure we catch that:
113 ; adrp -> ldrgot -> str.
114 ; CHECK-LABEL: _setC
115 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
116 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
117 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
118 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
119 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
120 ; CHECK-NEXT: str w0, [x[[LDRGOT_REG]]]
121 ; CHECK-NEXT: ret
122 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
123 define void @setC(i32 %t) {
124 entry:
125   store i32 %t, i32* @C, align 4
126   ret void
129 ; Perform the same tests for internal global and a displacement
130 ; in the addressing mode.
131 ; Indeed we will get an ADD for those instead of LOADGot.
132 @InternalC = internal global i32 0, align 4
134 ; Check that we catch AdrpAddLdr case when we have a simple chain:
135 ; adrp -> add -> ldr.
136 ; CHECK-LABEL: _getInternalCPlus4
137 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
138 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
139 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
140 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
141 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
142 ; CHECK-NEXT: ldr w0, {{\[}}[[ADDGOT_REG]], #16]
143 ; CHECK-NEXT: ret
144 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
145 define i32 @getInternalCPlus4() {
146   %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
147   %res = load i32, i32* %addr, align 4
148   ret i32 %res
151 ; LDRSW supports loading from a literal.
152 ; Make sure we emit AdrpLdrGotLdr for those.
153 ; CHECK-LABEL: _getSExtInternalCPlus4
154 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
155 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
156 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
157 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
158 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
159 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADDGOT_REG]], #16]
160 ; CHECK-NEXT: ret
161 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
162 define i64 @getSExtInternalCPlus4() {
163   %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
164   %res = load i32, i32* %addr, align 4
165   %sextres = sext i32 %res to i64
166   ret i64 %sextres
169 ; It may not be safe to fold the literal in the load if the address is
170 ; used several times.
171 ; Make sure we emit AdrpAdd for those.
172 ; CHECK-LABEL: _getSeveralInternalCPlus4
173 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
174 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
175 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
176 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
177 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADDGOT_REG]], #16]
178 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
179 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADDGOT_REG]], #16]
180 ; CHECK-NEXT: ret
181 ; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]]
182 define void @getSeveralInternalCPlus4(i32 %t) {
183 entry:
184   %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
185   %tmp = load i32, i32* %addr, align 4
186   %add = add nsw i32 %tmp, %t
187   store i32 %add, i32* %addr, align 4
188   ret void
191 ; Make sure we catch that:
192 ; adrp -> add -> str.
193 ; CHECK-LABEL: _setInternalCPlus4
194 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
195 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
196 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
197 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
198 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
199 ; CHECK-NEXT: str w0, {{\[}}[[ADDGOT_REG]], #16]
200 ; CHECK-NEXT: ret
201 ; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
202 define void @setInternalCPlus4(i32 %t) {
203 entry:
204   %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
205   store i32 %t, i32* %addr, align 4
206   ret void
209 ; Check that we catch AdrpAddLdr case when we have a simple chain:
210 ; adrp -> ldr.
211 ; CHECK-LABEL: _getInternalC
212 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
213 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
214 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
215 ; CHECK-NEXT: ldr w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
216 ; CHECK-NEXT: ret
217 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
218 define i32 @getInternalC() {
219   %res = load i32, i32* @InternalC, align 4
220   ret i32 %res
223 ; LDRSW supports loading from a literal.
224 ; Make sure we emit AdrpLdrGotLdr for those.
225 ; CHECK-LABEL: _getSExtInternalC
226 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
227 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
228 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
229 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
230 ; CHECK-NEXT: ret
231 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
232 define i64 @getSExtInternalC() {
233   %res = load i32, i32* @InternalC, align 4
234   %sextres = sext i32 %res to i64
235   ret i64 %sextres
238 ; It may not be safe to fold the literal in the load if the address is
239 ; used several times.
240 ; Make sure we do not catch anything here. We have a adrp alone,
241 ; there is not much we can do about it.
242 ; CHECK-LABEL: _getSeveralInternalC
243 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
244 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
245 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
246 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
247 ; CHECK-NEXT: ret
248 define void @getSeveralInternalC(i32 %t) {
249 entry:
250   %tmp = load i32, i32* @InternalC, align 4
251   %add = add nsw i32 %tmp, %t
252   store i32 %add, i32* @InternalC, align 4
253   ret void
256 ; Make sure we do not catch anything when:
257 ; adrp -> str.
258 ; We cannot fold anything in the str at this point.
259 ; Indeed, strs do not support litterals.
260 ; CHECK-LABEL: _setInternalC
261 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
262 ; CHECK-NEXT: str w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
263 ; CHECK-NEXT: ret
264 define void @setInternalC(i32 %t) {
265 entry:
266   store i32 %t, i32* @InternalC, align 4
267   ret void
270 ; Now check other variant of loads/stores.
272 @D = common global i8 0, align 4
274 ; LDRB does not support loading from a literal.
275 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
276 ; CHECK-LABEL: _getD
277 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
278 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
279 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
280 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
281 ; CHECK-NEXT: ldrb w0, [x[[LDRGOT_REG]]]
282 ; CHECK-NEXT: ret
283 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
284 define i8 @getD() {
285   %res = load i8, i8* @D, align 4
286   ret i8 %res
289 ; CHECK-LABEL: _setD
290 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
291 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
292 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
293 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
294 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
295 ; CHECK-NEXT: strb w0, [x[[LDRGOT_REG]]]
296 ; CHECK-NEXT: ret
297 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
298 define void @setD(i8 %t) {
299   store i8 %t, i8* @D, align 4
300   ret void
303 ; LDRSB supports loading from a literal.
304 ; Make sure we emit AdrpLdrGotLdr for those.
305 ; CHECK-LABEL: _getSExtD
306 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
307 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
308 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
309 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
310 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
311 ; CHECK-NEXT: ldrsb w0, [x[[LDRGOT_REG]]]
312 ; CHECK-NEXT: ret
313 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
314 define i32 @getSExtD() {
315   %res = load i8, i8* @D, align 4
316   %sextres = sext i8 %res to i32
317   ret i32 %sextres
320 ; LDRSB supports loading from a literal.
321 ; Make sure we emit AdrpLdrGotLdr for those.
322 ; CHECK-LABEL: _getSExt64D
323 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
324 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
325 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
326 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
327 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
328 ; CHECK-NEXT: ldrsb x0, [x[[LDRGOT_REG]]]
329 ; CHECK-NEXT: ret
330 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
331 define i64 @getSExt64D() {
332   %res = load i8, i8* @D, align 4
333   %sextres = sext i8 %res to i64
334   ret i64 %sextres
337 @E = common global i16 0, align 4
339 ; LDRH does not support loading from a literal.
340 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
341 ; CHECK-LABEL: _getE
342 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
343 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
344 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
345 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
346 ; CHECK-NEXT: ldrh w0, [x[[LDRGOT_REG]]]
347 ; CHECK-NEXT: ret
348 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
349 define i16 @getE() {
350   %res = load i16, i16* @E, align 4
351   ret i16 %res
354 ; LDRSH supports loading from a literal.
355 ; Make sure we emit AdrpLdrGotLdr for those.
356 ; CHECK-LABEL: _getSExtE
357 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
358 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
359 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
360 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
361 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
362 ; CHECK-NEXT: ldrsh w0, [x[[LDRGOT_REG]]]
363 ; CHECK-NEXT: ret
364 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
365 define i32 @getSExtE() {
366   %res = load i16, i16* @E, align 4
367   %sextres = sext i16 %res to i32
368   ret i32 %sextres
371 ; CHECK-LABEL: _setE
372 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
373 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
374 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
375 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
376 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
377 ; CHECK-NEXT: strh w0, [x[[LDRGOT_REG]]]
378 ; CHECK-NEXT: ret
379 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
380 define void @setE(i16 %t) {
381   store i16 %t, i16* @E, align 4
382   ret void
385 ; LDRSH supports loading from a literal.
386 ; Make sure we emit AdrpLdrGotLdr for those.
387 ; CHECK-LABEL: _getSExt64E
388 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
389 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
390 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
391 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
392 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
393 ; CHECK-NEXT: ldrsh x0, [x[[LDRGOT_REG]]]
394 ; CHECK-NEXT: ret
395 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
396 define i64 @getSExt64E() {
397   %res = load i16, i16* @E, align 4
398   %sextres = sext i16 %res to i64
399   ret i64 %sextres
402 @F = common global i64 0, align 4
404 ; LDR supports loading from a literal.
405 ; Make sure we emit AdrpLdrGotLdr for those.
406 ; CHECK-LABEL: _getF
407 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
408 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
409 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
410 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
411 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
412 ; CHECK-NEXT: ldr x0, [x[[LDRGOT_REG]]]
413 ; CHECK-NEXT: ret
414 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
415 define i64 @getF() {
416   %res = load i64, i64* @F, align 4
417   ret i64 %res
420 ; CHECK-LABEL: _setF
421 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
422 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
423 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
424 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
425 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
426 ; CHECK-NEXT: str x0, [x[[LDRGOT_REG]]]
427 ; CHECK-NEXT: ret
428 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
429 define void @setF(i64 %t) {
430   store i64 %t, i64* @F, align 4
431   ret void
434 @G = common global float 0.0, align 4
436 ; LDR float supports loading from a literal.
437 ; Make sure we emit AdrpLdrGotLdr for those.
438 ; CHECK-LABEL: _getG
439 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
440 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
441 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
442 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
443 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
444 ; CHECK-NEXT: ldr s0, [x[[LDRGOT_REG]]]
445 ; CHECK-NEXT: ret
446 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
447 define float @getG() {
448   %res = load float, float* @G, align 4
449   ret float %res
452 ; CHECK-LABEL: _setG
453 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
454 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
455 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
456 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
457 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
458 ; CHECK-NEXT: str s0, [x[[LDRGOT_REG]]]
459 ; CHECK-NEXT: ret
460 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
461 define void @setG(float %t) {
462   store float %t, float* @G, align 4
463   ret void
466 @H = common global half 0.0, align 4
468 ; LDR half supports loading from a literal.
469 ; Make sure we emit AdrpLdrGotLdr for those.
470 ; CHECK-LABEL: _getH
471 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
472 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
473 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
474 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
475 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
476 ; CHECK-NEXT: ldr h0, [x[[LDRGOT_REG]]]
477 ; CHECK-NEXT: ret
478 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
479 define half @getH() {
480   %res = load half, half* @H, align 4
481   ret half %res
484 ; CHECK-LABEL: _setH
485 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
486 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
487 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
488 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
489 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
490 ; CHECK-NEXT: str h0, [x[[LDRGOT_REG]]]
491 ; CHECK-NEXT: ret
492 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
493 define void @setH(half %t) {
494   store half %t, half* @H, align 4
495   ret void
498 @I = common global double 0.0, align 4
500 ; LDR double supports loading from a literal.
501 ; Make sure we emit AdrpLdrGotLdr for those.
502 ; CHECK-LABEL: _getI
503 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
504 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
505 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
506 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
507 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
508 ; CHECK-NEXT: ldr d0, [x[[LDRGOT_REG]]]
509 ; CHECK-NEXT: ret
510 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
511 define double @getI() {
512   %res = load double, double* @I, align 4
513   ret double %res
516 ; CHECK-LABEL: _setI
517 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
518 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
519 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
520 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
521 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
522 ; CHECK-NEXT: str d0, [x[[LDRGOT_REG]]]
523 ; CHECK-NEXT: ret
524 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
525 define void @setI(double %t) {
526   store double %t, double* @I, align 4
527   ret void
530 @J = common global <2 x i32> <i32 0, i32 0>, align 4
532 ; LDR 64-bit vector supports loading from a literal.
533 ; Make sure we emit AdrpLdrGotLdr for those.
534 ; CHECK-LABEL: _getJ
535 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
536 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
537 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
538 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
539 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
540 ; CHECK-NEXT: ldr d0, [x[[LDRGOT_REG]]]
541 ; CHECK-NEXT: ret
542 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
543 define <2 x i32> @getJ() {
544   %res = load <2 x i32>, <2 x i32>* @J, align 4
545   ret <2 x i32> %res
548 ; CHECK-LABEL: _setJ
549 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
550 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
551 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
552 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
553 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
554 ; CHECK-NEXT: str d0, [x[[LDRGOT_REG]]]
555 ; CHECK-NEXT: ret
556 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
557 define void @setJ(<2 x i32> %t) {
558   store <2 x i32> %t, <2 x i32>* @J, align 4
559   ret void
562 @K = common global <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 4
564 ; LDR 128-bit vector supports loading from a literal.
565 ; Make sure we emit AdrpLdrGotLdr for those.
566 ; CHECK-LABEL: _getK
567 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
568 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
569 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
570 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
571 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
572 ; CHECK-NEXT: ldr q0, [x[[LDRGOT_REG]]]
573 ; CHECK-NEXT: ret
574 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
575 define <4 x i32> @getK() {
576   %res = load <4 x i32>, <4 x i32>* @K, align 4
577   ret <4 x i32> %res
580 ; CHECK-LABEL: _setK
581 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
582 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
583 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
584 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
585 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
586 ; CHECK-NEXT: str q0, [x[[LDRGOT_REG]]]
587 ; CHECK-NEXT: ret
588 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
589 define void @setK(<4 x i32> %t) {
590   store <4 x i32> %t, <4 x i32>* @K, align 4
591   ret void
594 @L = common global <1 x i8> <i8 0>, align 4
596 ; LDR 8-bit vector supports loading from a literal.
597 ; Make sure we emit AdrpLdrGotLdr for those.
598 ; CHECK-LABEL: _getL
599 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
600 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
601 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
602 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
603 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
604 ; CHECK-NEXT: ldr b0, [x[[LDRGOT_REG]]]
605 ; CHECK-NEXT: ret
606 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
607 define <1 x i8> @getL() {
608   %res = load <1 x i8>, <1 x i8>* @L, align 4
609   ret <1 x i8> %res
612 ; CHECK-LABEL: _setL
613 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
614 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
615 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
616 ; CHECK-NEXT: ldr {{[xw]}}[[LDRGOT_REG:[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
617 ; CHECK-NEXT: ; kill
618 ; Ultimately we should generate str b0, but right now, we match the vector
619 ; variant which does not allow to fold the immediate into the store.
620 ; CHECK-NEXT: st1.b { v0 }[0], [x[[LDRGOT_REG]]]
621 ; CHECK-NEXT: ret
622 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
623 define void @setL(<1 x i8> %t) {
624   store <1 x i8> %t, <1 x i8>* @L, align 4
625   ret void
628 ; Make sure we do not assert when we do not track
629 ; all the aliases of a tuple register.
630 ; Indeed the tuple register can be tracked because of
631 ; one of its element, but the other elements of the tuple
632 ; do not need to be tracked and we used to assert on that.
633 ; Note: The test case is fragile in the sense that we need
634 ; a tuple register to appear in the lowering. Thus, the target
635 ; cpu is required to have the problem reproduced.
636 ; CHECK-LABEL: _uninterestingSub
637 ; CHECK: [[LOH_LABEL0:Lloh[0-9]+]]:
638 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], [[CONSTPOOL:lCPI[0-9]+_[0-9]+]]@PAGE
639 ; CHECK: [[LOH_LABEL1:Lloh[0-9]+]]:
640 ; CHECK: ldr q[[IDX:[0-9]+]], {{\[}}[[ADRP_REG]], [[CONSTPOOL]]@PAGEOFF]
641 ; The tuple comes from the next instruction.
642 ; CHECK: ext.16b v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, #1
643 ; CHECK: ret
644 ; CHECK: .loh AdrpLdr [[LOH_LABEL0]], [[LOH_LABEL1]]
645 define void @uninterestingSub(i8* nocapture %row) #0 {
646   %tmp = bitcast i8* %row to <16 x i8>*
647   %tmp1 = load <16 x i8>, <16 x i8>* %tmp, align 16
648   %vext43 = shufflevector <16 x i8> <i8 undef, i8 16, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2>, <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>
649   %add.i.414 = add <16 x i8> zeroinitializer, %vext43
650   store <16 x i8> %add.i.414, <16 x i8>* %tmp, align 16
651   %add.ptr51 = getelementptr inbounds i8, i8* %row, i64 16
652   %tmp2 = bitcast i8* %add.ptr51 to <16 x i8>*
653   %tmp3 = load <16 x i8>, <16 x i8>* %tmp2, align 16
654   %tmp4 = bitcast i8* undef to <16 x i8>*
655   %tmp5 = load <16 x i8>, <16 x i8>* %tmp4, align 16
656   %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>
657   %add.i.402 = add <16 x i8> zeroinitializer, %vext157
658   store <16 x i8> %add.i.402, <16 x i8>* %tmp4, align 16
659   ret void
662 @.str.89 = external unnamed_addr constant [12 x i8], align 1
663 @.str.90 = external unnamed_addr constant [5 x i8], align 1
664 ; CHECK-LABEL: test_r274582
665 define void @test_r274582(double %x) {
666 entry:
667   br i1 undef, label %if.then.i, label %if.end.i
668 if.then.i:
669   ret void
670 if.end.i:
671 ; CHECK: .loh AdrpLdrGot
672 ; CHECK: .loh AdrpLdrGot
673 ; CHECK: .loh AdrpAdrp
674 ; CHECK: .loh AdrpLdr
675   %mul = fmul double %x, 1.000000e-06
676   %add = fadd double %mul, %mul
677   %sub = fsub double %add, %add
678   call void (i8*, ...) @callee(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.89, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.90, i64 0, i64 0), double %sub)
679   unreachable
681 declare void @callee(i8* nocapture readonly, ...) 
683 attributes #0 = { "target-cpu"="cyclone" }