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
4
5; CHECK-ELF-NOT: .loh
6; CHECK-ELF-NOT: AdrpAdrp
7; CHECK-ELF-NOT: AdrpAdd
8; CHECK-ELF-NOT: AdrpLdrGot
9
10@a = internal unnamed_addr global i32 0, align 4
11@b = external global i32
12
13; Function Attrs: noinline nounwind ssp
14define void @foo(i32 %t) {
15entry:
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
20}
21
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
30define i32 @test(i32 %t) {
31entry:
32  %cmp = icmp sgt i32 %t, 5
33  br i1 %cmp, label %if.then, label %if.end4
34
35if.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
40
41if.then2:                                         ; preds = %if.then
42  tail call void @foo(i32 %add)
43  %tmp1 = load i32, i32* @a, align 4
44  br label %if.end4
45
46if.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
54}
55
56@C = common global i32 0, align 4
57
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]]
69define i32 @getC() {
70  %res = load i32, i32* @C, align 4
71  ret i32 %res
72}
73
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]]
85define i64 @getSExtC() {
86  %res = load i32, i32* @C, align 4
87  %sextres = sext i32 %res to i64
88  ret i64 %sextres
89}
90
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]]
104define void @getSeveralC(i32 %t) {
105entry:
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
110}
111
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]]
123define void @setC(i32 %t) {
124entry:
125  store i32 %t, i32* @C, align 4
126  ret void
127}
128
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
133
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]]
145define i32 @getInternalCPlus4() {
146  %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
147  %res = load i32, i32* %addr, align 4
148  ret i32 %res
149}
150
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]]
162define 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
167}
168
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]]
182define void @getSeveralInternalCPlus4(i32 %t) {
183entry:
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
189}
190
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]]
202define void @setInternalCPlus4(i32 %t) {
203entry:
204  %addr = getelementptr inbounds i32, i32* @InternalC, i32 4
205  store i32 %t, i32* %addr, align 4
206  ret void
207}
208
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]]
218define i32 @getInternalC() {
219  %res = load i32, i32* @InternalC, align 4
220  ret i32 %res
221}
222
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]]
232define i64 @getSExtInternalC() {
233  %res = load i32, i32* @InternalC, align 4
234  %sextres = sext i32 %res to i64
235  ret i64 %sextres
236}
237
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
248define void @getSeveralInternalC(i32 %t) {
249entry:
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
254}
255
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
264define void @setInternalC(i32 %t) {
265entry:
266  store i32 %t, i32* @InternalC, align 4
267  ret void
268}
269
270; Now check other variant of loads/stores.
271
272@D = common global i8 0, align 4
273
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]]
284define i8 @getD() {
285  %res = load i8, i8* @D, align 4
286  ret i8 %res
287}
288
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]]
298define void @setD(i8 %t) {
299  store i8 %t, i8* @D, align 4
300  ret void
301}
302
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]]
314define i32 @getSExtD() {
315  %res = load i8, i8* @D, align 4
316  %sextres = sext i8 %res to i32
317  ret i32 %sextres
318}
319
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]]
331define i64 @getSExt64D() {
332  %res = load i8, i8* @D, align 4
333  %sextres = sext i8 %res to i64
334  ret i64 %sextres
335}
336
337@E = common global i16 0, align 4
338
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]]
349define i16 @getE() {
350  %res = load i16, i16* @E, align 4
351  ret i16 %res
352}
353
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]]
365define i32 @getSExtE() {
366  %res = load i16, i16* @E, align 4
367  %sextres = sext i16 %res to i32
368  ret i32 %sextres
369}
370
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]]
380define void @setE(i16 %t) {
381  store i16 %t, i16* @E, align 4
382  ret void
383}
384
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]]
396define i64 @getSExt64E() {
397  %res = load i16, i16* @E, align 4
398  %sextres = sext i16 %res to i64
399  ret i64 %sextres
400}
401
402@F = common global i64 0, align 4
403
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]]
415define i64 @getF() {
416  %res = load i64, i64* @F, align 4
417  ret i64 %res
418}
419
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]]
429define void @setF(i64 %t) {
430  store i64 %t, i64* @F, align 4
431  ret void
432}
433
434@G = common global float 0.0, align 4
435
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]]
447define float @getG() {
448  %res = load float, float* @G, align 4
449  ret float %res
450}
451
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]]
461define void @setG(float %t) {
462  store float %t, float* @G, align 4
463  ret void
464}
465
466@H = common global half 0.0, align 4
467
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]]
479define half @getH() {
480  %res = load half, half* @H, align 4
481  ret half %res
482}
483
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]]
493define void @setH(half %t) {
494  store half %t, half* @H, align 4
495  ret void
496}
497
498@I = common global double 0.0, align 4
499
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]]
511define double @getI() {
512  %res = load double, double* @I, align 4
513  ret double %res
514}
515
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]]
525define void @setI(double %t) {
526  store double %t, double* @I, align 4
527  ret void
528}
529
530@J = common global <2 x i32> <i32 0, i32 0>, align 4
531
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]]
543define <2 x i32> @getJ() {
544  %res = load <2 x i32>, <2 x i32>* @J, align 4
545  ret <2 x i32> %res
546}
547
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]]
557define void @setJ(<2 x i32> %t) {
558  store <2 x i32> %t, <2 x i32>* @J, align 4
559  ret void
560}
561
562@K = common global <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 4
563
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]]
575define <4 x i32> @getK() {
576  %res = load <4 x i32>, <4 x i32>* @K, align 4
577  ret <4 x i32> %res
578}
579
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]]
589define void @setK(<4 x i32> %t) {
590  store <4 x i32> %t, <4 x i32>* @K, align 4
591  ret void
592}
593
594@L = common global <1 x i8> <i8 0>, align 4
595
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]]
607define <1 x i8> @getL() {
608  %res = load <1 x i8>, <1 x i8>* @L, align 4
609  ret <1 x i8> %res
610}
611
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]]
623define void @setL(<1 x i8> %t) {
624  store <1 x i8> %t, <1 x i8>* @L, align 4
625  ret void
626}
627
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]]
645define 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
660}
661
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
665define void @test_r274582(double %x) {
666entry:
667  br i1 undef, label %if.then.i, label %if.end.i
668if.then.i:
669  ret void
670if.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
680}
681declare void @callee(i8* nocapture readonly, ...)
682
683attributes #0 = { "target-cpu"="cyclone" }
684