1 ; RUN: llc -o - %s -mtriple=arm64-apple-ios -O2 | FileCheck %s
2 ; RUN: llc -o - %s -mtriple=arm64-linux-gnu -O2 | FileCheck %s --check-prefix=CHECK-ELF
5 ; CHECK-ELF-NOT: AdrpAdrp
6 ; CHECK-ELF-NOT: AdrpAdd
7 ; CHECK-ELF-NOT: AdrpLdrGot
9 @a = internal unnamed_addr global i32 0, align 4
10 @b = external global i32
12 ; Function Attrs: noinline nounwind ssp
13 define void @foo(i32 %t) {
15 %tmp = load i32, i32* @a, align 4
16 %add = add nsw i32 %tmp, %t
17 store i32 %add, i32* @a, align 4
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.
28 ; CHECK-NOT: .loh AdrpAdrp
29 define i32 @test(i32 %t) {
31 %cmp = icmp sgt i32 %t, 5
32 br i1 %cmp, label %if.then, label %if.end4
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
40 if.then2: ; preds = %if.then
41 tail call void @foo(i32 %add)
42 %tmp1 = load i32, i32* @a, align 4
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
55 @C = common global i32 0, align 4
57 ; Check that we catch AdrpLdrGotLdr case when we have a simple chain:
58 ; adrp -> ldrgot -> ldr.
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]]]
67 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
69 %res = load i32, i32* @C, align 4
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]]]
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
90 ; It may not be safe to fold the literal in the load if the address is
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]]]
102 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
103 define void @getSeveralC(i32 %t) {
105 %tmp = load i32, i32* @C, align 4
106 %add = add nsw i32 %tmp, %t
107 store i32 %add, i32* @C, align 4
111 ; Make sure we catch that:
112 ; adrp -> ldrgot -> str.
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]]]
121 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
122 define void @setC(i32 %t) {
124 store i32 %t, i32* @C, align 4
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
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]
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
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]
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
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]
180 ; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]]
181 define void @getSeveralInternalCPlus4(i32 %t) {
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
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]
200 ; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
201 define void @setInternalCPlus4(i32 %t) {
203 %addr = getelementptr i32, i32* @InternalC, i32 4
204 store i32 %t, i32* %addr, align 4
208 ; Check that we catch AdrpAddLdr case when we have a simple chain:
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]
216 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
217 define i32 @getInternalC() {
218 %res = load i32, i32* @InternalC, align 4
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]
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
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]
247 define void @getSeveralInternalC(i32 %t) {
249 %tmp = load i32, i32* @InternalC, align 4
250 %add = add nsw i32 %tmp, %t
251 store i32 %add, i32* @InternalC, align 4
255 ; Make sure we do not catch anything when:
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]
263 define void @setInternalC(i32 %t) {
265 store i32 %t, i32* @InternalC, align 4
269 ; Now check other variant of loads/stores.
271 @D = common global i8 0, align 4
273 ; LDRB does not support loading from a literal.
274 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
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]]]
282 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
284 %res = load i8, i8* @D, align 4
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]]]
296 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
297 define void @setD(i8 %t) {
298 store i8 %t, i8* @D, align 4
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]]]
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
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]]]
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
336 @E = common global i16 0, align 4
338 ; LDRH does not support loading from a literal.
339 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
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]]]
347 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
349 %res = load i16, i16* @E, align 4
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]]]
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
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]]]
378 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
379 define void @setE(i16 %t) {
380 store i16 %t, i16* @E, align 4
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]]]
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
401 @F = common global i64 0, align 4
403 ; LDR supports loading from a literal.
404 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
413 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
415 %res = load i64, i64* @F, align 4
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]]]
427 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
428 define void @setF(i64 %t) {
429 store i64 %t, i64* @F, align 4
433 @G = common global float 0.0, align 4
435 ; LDR float supports loading from a literal.
436 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
445 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
446 define float @getG() {
447 %res = load float, float* @G, align 4
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]]]
459 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
460 define void @setG(float %t) {
461 store float %t, float* @G, align 4
465 @H = common global half 0.0, align 4
467 ; LDR half supports loading from a literal.
468 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
477 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
478 define half @getH() {
479 %res = load half, half* @H, align 4
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]]]
491 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
492 define void @setH(half %t) {
493 store half %t, half* @H, align 4
497 @I = common global double 0.0, align 4
499 ; LDR double supports loading from a literal.
500 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
509 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
510 define double @getI() {
511 %res = load double, double* @I, align 4
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]]]
523 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
524 define void @setI(double %t) {
525 store double %t, double* @I, align 4
529 @J = common global <2 x i32> <i32 0, i32 0>, align 4
531 ; LDR 64-bit vector supports loading from a literal.
532 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
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
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]]]
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
561 @K = common global <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 4
563 ; LDR 128-bit vector supports loading from a literal.
564 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
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
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]]]
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
593 @L = common global <1 x i8> <i8 0>, align 4
595 ; LDR 8-bit vector supports loading from a literal.
596 ; Make sure we emit AdrpLdrGotLdr for those.
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]]]
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
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]
617 ; Ultimately we should generate str b0, but right now, we match the vector
618 ; variant which does not allow to fold the immediate into the store.
619 ; CHECK-NEXT: st1.b { v0 }[0], {{\[}}[[LDRGOT_REG]]]
621 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
622 define void @setL(<1 x i8> %t) {
623 store <1 x i8> %t, <1 x i8>* @L, align 4
627 ; Make sure we do not assert when we do not track
628 ; all the aliases of a tuple register.
629 ; Indeed the tuple register can be tracked because of
630 ; one of its element, but the other elements of the tuple
631 ; do not need to be tracked and we used to assert on that.
632 ; Note: The test case is fragile in the sense that we need
633 ; a tuple register to appear in the lowering. Thus, the target
634 ; cpu is required to have the problem reproduced.
635 ; CHECK-LABEL: _uninterestingSub
636 ; CHECK: [[LOH_LABEL0:Lloh[0-9]+]]:
637 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], [[CONSTPOOL:lCPI[0-9]+_[0-9]+]]@PAGE
638 ; CHECK: [[LOH_LABEL1:Lloh[0-9]+]]:
639 ; CHECK: ldr q[[IDX:[0-9]+]], {{\[}}[[ADRP_REG]], [[CONSTPOOL]]@PAGEOFF]
640 ; The tuple comes from the next instruction.
641 ; CHECK: ext.16b v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, #1
643 ; CHECK: .loh AdrpLdr [[LOH_LABEL0]], [[LOH_LABEL1]]
644 define void @uninterestingSub(i8* nocapture %row) #0 {
645 %tmp = bitcast i8* %row to <16 x i8>*
646 %tmp1 = load <16 x i8>, <16 x i8>* %tmp, align 16
647 %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>
648 %add.i.414 = add <16 x i8> zeroinitializer, %vext43
649 store <16 x i8> %add.i.414, <16 x i8>* %tmp, align 16
650 %add.ptr51 = getelementptr inbounds i8, i8* %row, i64 16
651 %tmp2 = bitcast i8* %add.ptr51 to <16 x i8>*
652 %tmp3 = load <16 x i8>, <16 x i8>* %tmp2, align 16
653 %tmp4 = bitcast i8* undef to <16 x i8>*
654 %tmp5 = load <16 x i8>, <16 x i8>* %tmp4, align 16
655 %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>
656 %add.i.402 = add <16 x i8> zeroinitializer, %vext157
657 store <16 x i8> %add.i.402, <16 x i8>* %tmp4, align 16
661 @.str.89 = external unnamed_addr constant [12 x i8], align 1
662 @.str.90 = external unnamed_addr constant [5 x i8], align 1
663 ; CHECK-LABEL: test_r274582
664 define void @test_r274582(double %x) {
666 br i1 undef, label %if.then.i, label %if.end.i
670 ; CHECK: .loh AdrpLdrGot
671 ; CHECK: .loh AdrpLdrGot
672 ; CHECK: .loh AdrpAdrp
673 ; CHECK: .loh AdrpLdr
674 %mul = fmul double %x, 1.000000e-06
675 %add = fadd double %mul, %mul
676 %sub = fsub double %add, %add
677 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)
680 declare void @callee(i8* nocapture readonly, ...)
682 attributes #0 = { "target-cpu"="cyclone" }