1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs -mtriple=aarch64 -code-model=tiny -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK-PIC
3; RUN: llc -verify-machineinstrs -mtriple=aarch64 -code-model=tiny -relocation-model=pic -fast-isel < %s | FileCheck %s --check-prefix=CHECK-PIC
4; RUN: llc -verify-machineinstrs -mtriple=aarch64 -code-model=tiny -relocation-model=pic -global-isel < %s | FileCheck %s --check-prefix=CHECK-PIC-GLOBISEL
5
6; Note fast-isel tests here will fall back to isel
7
8@src = external local_unnamed_addr global [65536 x i8], align 1
9@dst = external global [65536 x i8], align 1
10@ptr = external local_unnamed_addr global i8*, align 8
11
12define dso_preemptable void @foo1() {
13; CHECK-LABEL: foo1:
14; CHECK:       // %bb.0: // %entry
15; CHECK-NEXT:    ldr x8, :got:src
16; CHECK-NEXT:    ldrb w8, [x8]
17; CHECK-NEXT:    ldr x9, :got:dst
18; CHECK-NEXT:    strb w8, [x9]
19; CHECK-NEXT:    ret
20;
21; CHECK-GLOBISEL-LABEL: foo1:
22; CHECK-GLOBISEL:       // %bb.0: // %entry
23; CHECK-GLOBISEL-NEXT:    ldr x8, :got:src
24; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
25; CHECK-GLOBISEL-NEXT:    ldr x9, :got:dst
26; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
27; CHECK-GLOBISEL-NEXT:    ret
28;
29; CHECK-PIC-LABEL: foo1:
30; CHECK-PIC:       // %bb.0: // %entry
31; CHECK-PIC-NEXT:    ldr x8, :got:src
32; CHECK-PIC-NEXT:    ldrb w8, [x8]
33; CHECK-PIC-NEXT:    ldr x9, :got:dst
34; CHECK-PIC-NEXT:    strb w8, [x9]
35; CHECK-PIC-NEXT:    ret
36;
37; CHECK-PIC-GLOBISEL-LABEL: foo1:
38; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
39; CHECK-PIC-GLOBISEL-NEXT:    ldr x8, :got:src
40; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
41; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, :got:dst
42; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
43; CHECK-PIC-GLOBISEL-NEXT:    ret
44entry:
45  %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @src, i64 0, i64 0), align 1
46  store i8 %0, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @dst, i64 0, i64 0), align 1
47  ret void
48}
49
50define dso_preemptable void @foo2() {
51; CHECK-LABEL: foo2:
52; CHECK:       // %bb.0: // %entry
53; CHECK-NEXT:    ldr x8, :got:ptr
54; CHECK-NEXT:    ldr x9, :got:dst
55; CHECK-NEXT:    str x9, [x8]
56; CHECK-NEXT:    ret
57;
58; CHECK-GLOBISEL-LABEL: foo2:
59; CHECK-GLOBISEL:       // %bb.0: // %entry
60; CHECK-GLOBISEL-NEXT:    ldr x8, :got:ptr
61; CHECK-GLOBISEL-NEXT:    ldr x9, :got:dst
62; CHECK-GLOBISEL-NEXT:    str x9, [x8]
63; CHECK-GLOBISEL-NEXT:    ret
64;
65; CHECK-PIC-LABEL: foo2:
66; CHECK-PIC:       // %bb.0: // %entry
67; CHECK-PIC-NEXT:    ldr x8, :got:ptr
68; CHECK-PIC-NEXT:    ldr x9, :got:dst
69; CHECK-PIC-NEXT:    str x9, [x8]
70; CHECK-PIC-NEXT:    ret
71;
72; CHECK-PIC-GLOBISEL-LABEL: foo2:
73; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
74; CHECK-PIC-GLOBISEL-NEXT:    ldr x8, :got:ptr
75; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, :got:dst
76; CHECK-PIC-GLOBISEL-NEXT:    str x9, [x8]
77; CHECK-PIC-GLOBISEL-NEXT:    ret
78entry:
79  store i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @dst, i64 0, i64 0), i8** @ptr, align 8
80  ret void
81}
82
83define dso_preemptable void @foo3() {
84; FIXME: Needn't adr ptr
85;
86; CHECK-LABEL: foo3:
87; CHECK:       // %bb.0: // %entry
88; CHECK-NEXT:    ldr x8, :got:src
89; CHECK-NEXT:    ldr x9, :got:ptr
90; CHECK-NEXT:    ldrb w8, [x8]
91; CHECK-NEXT:    ldr x9, [x9]
92; CHECK-NEXT:    strb w8, [x9]
93; CHECK-NEXT:    ret
94;
95; CHECK-GLOBISEL-LABEL: foo3:
96; CHECK-GLOBISEL:       // %bb.0: // %entry
97; CHECK-GLOBISEL-NEXT:    ldr x8, :got:src
98; CHECK-GLOBISEL-NEXT:    ldr x9, :got:ptr
99; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
100; CHECK-GLOBISEL-NEXT:    ldr x9, [x9]
101; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
102; CHECK-GLOBISEL-NEXT:    ret
103;
104; CHECK-PIC-LABEL: foo3:
105; CHECK-PIC:       // %bb.0: // %entry
106; CHECK-PIC-NEXT:    ldr x8, :got:src
107; CHECK-PIC-NEXT:    ldr x9, :got:ptr
108; CHECK-PIC-NEXT:    ldrb w8, [x8]
109; CHECK-PIC-NEXT:    ldr x9, [x9]
110; CHECK-PIC-NEXT:    strb w8, [x9]
111; CHECK-PIC-NEXT:    ret
112;
113; CHECK-PIC-GLOBISEL-LABEL: foo3:
114; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
115; CHECK-PIC-GLOBISEL-NEXT:    ldr x8, :got:src
116; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, :got:ptr
117; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
118; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, [x9]
119; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
120; CHECK-PIC-GLOBISEL-NEXT:    ret
121entry:
122  %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @src, i64 0, i64 0), align 1
123  %1 = load i8*, i8** @ptr, align 8
124  store i8 %0, i8* %1, align 1
125  ret void
126}
127
128@lsrc = internal global i8 0, align 4
129@ldst = internal global i8 0, align 4
130@lptr = internal global i8* null, align 8
131
132define dso_preemptable void @bar1() {
133; CHECK-LABEL: bar1:
134; CHECK:       // %bb.0: // %entry
135; CHECK-NEXT:    adr x8, lsrc
136; CHECK-NEXT:    ldrb w8, [x8]
137; CHECK-NEXT:    adr x9, ldst
138; CHECK-NEXT:    strb w8, [x9]
139; CHECK-NEXT:    ret
140;
141; CHECK-GLOBISEL-LABEL: bar1:
142; CHECK-GLOBISEL:       // %bb.0: // %entry
143; CHECK-GLOBISEL-NEXT:    adr x8, lsrc
144; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
145; CHECK-GLOBISEL-NEXT:    adr x9, ldst
146; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
147; CHECK-GLOBISEL-NEXT:    ret
148;
149; CHECK-PIC-LABEL: bar1:
150; CHECK-PIC:       // %bb.0: // %entry
151; CHECK-PIC-NEXT:    adr x8, lsrc
152; CHECK-PIC-NEXT:    adr x9, ldst
153; CHECK-PIC-NEXT:    ldrb w8, [x8]
154; CHECK-PIC-NEXT:    strb w8, [x9]
155; CHECK-PIC-NEXT:    ret
156;
157; CHECK-PIC-GLOBISEL-LABEL: bar1:
158; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
159; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lsrc
160; CHECK-PIC-GLOBISEL-NEXT:    adr x9, ldst
161; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
162; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
163; CHECK-PIC-GLOBISEL-NEXT:    ret
164entry:
165  %0 = load i8, i8* @lsrc, align 4
166  store i8 %0, i8* @ldst, align 4
167  ret void
168}
169
170define dso_preemptable void @bar2() {
171; CHECK-LABEL: bar2:
172; CHECK:       // %bb.0: // %entry
173; CHECK-NEXT:    adr x8, lptr
174; CHECK-NEXT:    adr x9, ldst
175; CHECK-NEXT:    str x9, [x8]
176; CHECK-NEXT:    ret
177;
178; CHECK-GLOBISEL-LABEL: bar2:
179; CHECK-GLOBISEL:       // %bb.0: // %entry
180; CHECK-GLOBISEL-NEXT:    adr x8, lptr
181; CHECK-GLOBISEL-NEXT:    adr x9, ldst
182; CHECK-GLOBISEL-NEXT:    str x9, [x8]
183; CHECK-GLOBISEL-NEXT:    ret
184;
185; CHECK-PIC-LABEL: bar2:
186; CHECK-PIC:       // %bb.0: // %entry
187; CHECK-PIC-NEXT:    adr x8, lptr
188; CHECK-PIC-NEXT:    adr x9, ldst
189; CHECK-PIC-NEXT:    str x9, [x8]
190; CHECK-PIC-NEXT:    ret
191;
192; CHECK-PIC-GLOBISEL-LABEL: bar2:
193; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
194; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lptr
195; CHECK-PIC-GLOBISEL-NEXT:    adr x9, ldst
196; CHECK-PIC-GLOBISEL-NEXT:    str x9, [x8]
197; CHECK-PIC-GLOBISEL-NEXT:    ret
198entry:
199  store i8* @ldst, i8** @lptr, align 8
200  ret void
201}
202
203define dso_preemptable void @bar3() {
204; FIXME: Needn't adr lptr
205;
206; CHECK-LABEL: bar3:
207; CHECK:       // %bb.0: // %entry
208; CHECK-NEXT:    adr x8, lsrc
209; CHECK-NEXT:    ldrb w8, [x8]
210; CHECK-NEXT:    ldr x9, lptr
211; CHECK-NEXT:    strb w8, [x9]
212; CHECK-NEXT:    ret
213;
214; CHECK-GLOBISEL-LABEL: bar3:
215; CHECK-GLOBISEL:       // %bb.0: // %entry
216; CHECK-GLOBISEL-NEXT:    adr x8, lsrc
217; CHECK-GLOBISEL-NEXT:    adr x9, lptr
218; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
219; CHECK-GLOBISEL-NEXT:    ldr x9, [x9]
220; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
221; CHECK-GLOBISEL-NEXT:    ret
222;
223; CHECK-PIC-LABEL: bar3:
224; CHECK-PIC:       // %bb.0: // %entry
225; CHECK-PIC-NEXT:    adr x8, lsrc
226; CHECK-PIC-NEXT:    ldr x9, lptr
227; CHECK-PIC-NEXT:    ldrb w8, [x8]
228; CHECK-PIC-NEXT:    strb w8, [x9]
229; CHECK-PIC-NEXT:    ret
230;
231; CHECK-PIC-GLOBISEL-LABEL: bar3:
232; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
233; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lsrc
234; CHECK-PIC-GLOBISEL-NEXT:    adr x9, lptr
235; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
236; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, [x9]
237; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
238; CHECK-PIC-GLOBISEL-NEXT:    ret
239entry:
240  %0 = load i8, i8* @lsrc, align 4
241  %1 = load i8*, i8** @lptr, align 8
242  store i8 %0, i8* %1, align 1
243  ret void
244}
245
246
247@lbsrc = internal global [65536 x i8] zeroinitializer, align 4
248@lbdst = internal global [65536 x i8] zeroinitializer, align 4
249
250define dso_preemptable void @baz1() {
251; CHECK-LABEL: baz1:
252; CHECK:       // %bb.0: // %entry
253; CHECK-NEXT:    adr x8, lbsrc
254; CHECK-NEXT:    ldrb w8, [x8]
255; CHECK-NEXT:    adr x9, lbdst
256; CHECK-NEXT:    strb w8, [x9]
257; CHECK-NEXT:    ret
258;
259; CHECK-GLOBISEL-LABEL: baz1:
260; CHECK-GLOBISEL:       // %bb.0: // %entry
261; CHECK-GLOBISEL-NEXT:    adr x8, lbsrc
262; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
263; CHECK-GLOBISEL-NEXT:    adr x9, lbdst
264; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
265; CHECK-GLOBISEL-NEXT:    ret
266;
267; CHECK-PIC-LABEL: baz1:
268; CHECK-PIC:       // %bb.0: // %entry
269; CHECK-PIC-NEXT:    adr x8, lbsrc
270; CHECK-PIC-NEXT:    adr x9, lbdst
271; CHECK-PIC-NEXT:    ldrb w8, [x8]
272; CHECK-PIC-NEXT:    strb w8, [x9]
273; CHECK-PIC-NEXT:    ret
274;
275; CHECK-PIC-GLOBISEL-LABEL: baz1:
276; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
277; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lbsrc
278; CHECK-PIC-GLOBISEL-NEXT:    adr x9, lbdst
279; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
280; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
281; CHECK-PIC-GLOBISEL-NEXT:    ret
282entry:
283  %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbsrc, i64 0, i64 0), align 4
284  store i8 %0, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbdst, i64 0, i64 0), align 4
285  ret void
286}
287
288define dso_preemptable void @baz2() {
289; CHECK-LABEL: baz2:
290; CHECK:       // %bb.0: // %entry
291; CHECK-NEXT:    adr x8, lptr
292; CHECK-NEXT:    adr x9, lbdst
293; CHECK-NEXT:    str x9, [x8]
294; CHECK-NEXT:    ret
295;
296; CHECK-GLOBISEL-LABEL: baz2:
297; CHECK-GLOBISEL:       // %bb.0: // %entry
298; CHECK-GLOBISEL-NEXT:    adr x8, lptr
299; CHECK-GLOBISEL-NEXT:    adr x9, lbdst
300; CHECK-GLOBISEL-NEXT:    str x9, [x8]
301; CHECK-GLOBISEL-NEXT:    ret
302;
303; CHECK-PIC-LABEL: baz2:
304; CHECK-PIC:       // %bb.0: // %entry
305; CHECK-PIC-NEXT:    adr x8, lptr
306; CHECK-PIC-NEXT:    adr x9, lbdst
307; CHECK-PIC-NEXT:    str x9, [x8]
308; CHECK-PIC-NEXT:    ret
309;
310; CHECK-PIC-GLOBISEL-LABEL: baz2:
311; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
312; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lptr
313; CHECK-PIC-GLOBISEL-NEXT:    adr x9, lbdst
314; CHECK-PIC-GLOBISEL-NEXT:    str x9, [x8]
315; CHECK-PIC-GLOBISEL-NEXT:    ret
316entry:
317  store i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbdst, i64 0, i64 0), i8** @lptr, align 8
318  ret void
319}
320
321define dso_preemptable void @baz3() {
322; FIXME: Needn't adr lptr
323;
324; CHECK-LABEL: baz3:
325; CHECK:       // %bb.0: // %entry
326; CHECK-NEXT:    adr x8, lbsrc
327; CHECK-NEXT:    ldrb w8, [x8]
328; CHECK-NEXT:    ldr x9, lptr
329; CHECK-NEXT:    strb w8, [x9]
330; CHECK-NEXT:    ret
331;
332; CHECK-GLOBISEL-LABEL: baz3:
333; CHECK-GLOBISEL:       // %bb.0: // %entry
334; CHECK-GLOBISEL-NEXT:    adr x8, lbsrc
335; CHECK-GLOBISEL-NEXT:    adr x9, lptr
336; CHECK-GLOBISEL-NEXT:    ldrb w8, [x8]
337; CHECK-GLOBISEL-NEXT:    ldr x9, [x9]
338; CHECK-GLOBISEL-NEXT:    strb w8, [x9]
339; CHECK-GLOBISEL-NEXT:    ret
340;
341; CHECK-PIC-LABEL: baz3:
342; CHECK-PIC:       // %bb.0: // %entry
343; CHECK-PIC-NEXT:    adr x8, lbsrc
344; CHECK-PIC-NEXT:    ldr x9, lptr
345; CHECK-PIC-NEXT:    ldrb w8, [x8]
346; CHECK-PIC-NEXT:    strb w8, [x9]
347; CHECK-PIC-NEXT:    ret
348;
349; CHECK-PIC-GLOBISEL-LABEL: baz3:
350; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
351; CHECK-PIC-GLOBISEL-NEXT:    adr x8, lbsrc
352; CHECK-PIC-GLOBISEL-NEXT:    adr x9, lptr
353; CHECK-PIC-GLOBISEL-NEXT:    ldrb w8, [x8]
354; CHECK-PIC-GLOBISEL-NEXT:    ldr x9, [x9]
355; CHECK-PIC-GLOBISEL-NEXT:    strb w8, [x9]
356; CHECK-PIC-GLOBISEL-NEXT:    ret
357entry:
358  %0 = load i8, i8* getelementptr inbounds ([65536 x i8], [65536 x i8]* @lbsrc, i64 0, i64 0), align 4
359  %1 = load i8*, i8** @lptr, align 8
360  store i8 %0, i8* %1, align 1
361  ret void
362}
363
364
365declare void @func(...)
366
367define dso_preemptable i8* @externfuncaddr() {
368; CHECK-LABEL: externfuncaddr:
369; CHECK:       // %bb.0: // %entry
370; CHECK-NEXT:    ldr x0, :got:func
371; CHECK-NEXT:    ret
372;
373; CHECK-GLOBISEL-LABEL: externfuncaddr:
374; CHECK-GLOBISEL:       // %bb.0: // %entry
375; CHECK-GLOBISEL-NEXT:    ldr x0, :got:func
376; CHECK-GLOBISEL-NEXT:    ret
377;
378; CHECK-PIC-LABEL: externfuncaddr:
379; CHECK-PIC:       // %bb.0: // %entry
380; CHECK-PIC-NEXT:    ldr x0, :got:func
381; CHECK-PIC-NEXT:    ret
382;
383; CHECK-PIC-GLOBISEL-LABEL: externfuncaddr:
384; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
385; CHECK-PIC-GLOBISEL-NEXT:    ldr x0, :got:func
386; CHECK-PIC-GLOBISEL-NEXT:    ret
387entry:
388      ret i8* bitcast (void (...)* @func to i8*)
389}
390
391define dso_preemptable i8* @localfuncaddr() {
392; CHECK-LABEL: localfuncaddr:
393; CHECK:       // %bb.0: // %entry
394; CHECK-NEXT:    adr x0, externfuncaddr
395; CHECK-NEXT:    ret
396;
397; CHECK-GLOBISEL-LABEL: localfuncaddr:
398; CHECK-GLOBISEL:       // %bb.0: // %entry
399; CHECK-GLOBISEL-NEXT:    adr x0, externfuncaddr
400; CHECK-GLOBISEL-NEXT:    ret
401;
402; CHECK-PIC-LABEL: localfuncaddr:
403; CHECK-PIC:       // %bb.0: // %entry
404; CHECK-PIC-NEXT:    ldr x0, :got:externfuncaddr
405; CHECK-PIC-NEXT:    ret
406;
407; CHECK-PIC-GLOBISEL-LABEL: localfuncaddr:
408; CHECK-PIC-GLOBISEL:       // %bb.0: // %entry
409; CHECK-PIC-GLOBISEL-NEXT:    ldr x0, :got:externfuncaddr
410; CHECK-PIC-GLOBISEL-NEXT:    ret
411entry:
412      ret i8* bitcast (i8* ()* @externfuncaddr to i8*)
413}
414
415