xref: /llvm-project/llvm/test/CodeGen/AArch64/ldst-unsignedimm.ll (revision 5ddce70ef0e5a641d7fea95e31fc5e2439cb98cb)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu | FileCheck --check-prefixes=CHECK,CHECK-FP %s
3; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -mattr=-fp-armv8 | FileCheck --check-prefixes=CHECK,CHECK-NOFP %s
4
5@var_8bit = dso_local global i8 0
6@var_16bit = dso_local global i16 0
7@var_32bit = dso_local global i32 0
8@var_64bit = dso_local global i64 0
9
10@var_float = dso_local global float 0.0
11@var_double = dso_local global double 0.0
12
13define i32 @ld_s8_32() {
14; CHECK-LABEL: ld_s8_32:
15; CHECK:       // %bb.0:
16; CHECK-NEXT:    adrp x8, var_8bit
17; CHECK-NEXT:    ldrsb w0, [x8, :lo12:var_8bit]
18; CHECK-NEXT:    ret
19   %val8_sext32 = load i8, ptr @var_8bit
20   %val32_signed = sext i8 %val8_sext32 to i32
21   ret i32 %val32_signed
22}
23
24define i32 @ld_u8_32() {
25; CHECK-LABEL: ld_u8_32:
26; CHECK:       // %bb.0:
27; CHECK-NEXT:    adrp x8, var_8bit
28; CHECK-NEXT:    ldrb w0, [x8, :lo12:var_8bit]
29; CHECK-NEXT:    ret
30  %val8_zext32 = load i8, ptr @var_8bit
31  %val32_unsigned = zext i8 %val8_zext32 to i32
32  ret i32 %val32_unsigned
33}
34
35define i64 @ld_s8_64() {
36; CHECK-LABEL: ld_s8_64:
37; CHECK:       // %bb.0:
38; CHECK-NEXT:    adrp x8, var_8bit
39; CHECK-NEXT:    ldrsb x0, [x8, :lo12:var_8bit]
40; CHECK-NEXT:    ret
41  %val8_sext64 = load i8, ptr @var_8bit
42  %val64_signed = sext i8 %val8_sext64 to i64
43  ret i64 %val64_signed
44}
45
46define i64 @ld_u8_64() {
47; CHECK-LABEL: ld_u8_64:
48; CHECK:       // %bb.0:
49; CHECK-NEXT:    adrp x8, var_8bit
50; CHECK-NEXT:    ldrb w0, [x8, :lo12:var_8bit]
51; CHECK-NEXT:    ret
52  %val8_zext64 = load i8, ptr @var_8bit
53  %val64_unsigned = zext i8 %val8_zext64 to i64
54  ret i64 %val64_unsigned
55}
56
57define i8 @ld_a8_8() {
58; CHECK-LABEL: ld_a8_8:
59; CHECK:       // %bb.0:
60; CHECK-NEXT:    adrp x8, var_8bit
61; CHECK-NEXT:    ldrb w8, [x8, :lo12:var_8bit]
62; CHECK-NEXT:    add w0, w8, #1
63; CHECK-NEXT:    ret
64  %val8_anyext = load i8, ptr @var_8bit
65  %newval8 = add i8 %val8_anyext, 1
66  ret i8 %newval8
67}
68
69define void @st_i32_8(i32 %val32) {
70; CHECK-LABEL: st_i32_8:
71; CHECK:       // %bb.0:
72; CHECK-NEXT:    adrp x8, var_8bit
73; CHECK-NEXT:    strb w0, [x8, :lo12:var_8bit]
74; CHECK-NEXT:    ret
75  %val8_trunc32 = trunc i32 %val32 to i8
76  store i8 %val8_trunc32, ptr @var_8bit
77  ret void
78}
79
80define void @st_i64_8(i64 %val64) {
81; CHECK-LABEL: st_i64_8:
82; CHECK:       // %bb.0:
83; CHECK-NEXT:    adrp x8, var_8bit
84; CHECK-NEXT:    strb w0, [x8, :lo12:var_8bit]
85; CHECK-NEXT:    ret
86  %val8_trunc64 = trunc i64 %val64 to i8
87  store i8 %val8_trunc64, ptr @var_8bit
88  ret void
89}
90
91
92define i32 @ld_s16_32() {
93; CHECK-LABEL: ld_s16_32:
94; CHECK:       // %bb.0:
95; CHECK-NEXT:    adrp x8, var_16bit
96; CHECK-NEXT:    ldrsh w0, [x8, :lo12:var_16bit]
97; CHECK-NEXT:    ret
98   %val16_sext32 = load i16, ptr @var_16bit
99   %val32_signed = sext i16 %val16_sext32 to i32
100   ret i32 %val32_signed
101}
102
103define i32 @ld_u16_32() {
104; CHECK-LABEL: ld_u16_32:
105; CHECK:       // %bb.0:
106; CHECK-NEXT:    adrp x8, var_16bit
107; CHECK-NEXT:    ldrh w0, [x8, :lo12:var_16bit]
108; CHECK-NEXT:    ret
109  %val16_zext32 = load i16, ptr @var_16bit
110  %val32_unsigned = zext i16 %val16_zext32 to i32
111  ret i32 %val32_unsigned
112}
113
114define i64 @ld_s16_64() {
115; CHECK-LABEL: ld_s16_64:
116; CHECK:       // %bb.0:
117; CHECK-NEXT:    adrp x8, var_16bit
118; CHECK-NEXT:    ldrsh x0, [x8, :lo12:var_16bit]
119; CHECK-NEXT:    ret
120  %val16_sext64 = load i16, ptr @var_16bit
121  %val64_signed = sext i16 %val16_sext64 to i64
122  ret i64 %val64_signed
123}
124
125define i64 @ld_u16_64() {
126; CHECK-LABEL: ld_u16_64:
127; CHECK:       // %bb.0:
128; CHECK-NEXT:    adrp x8, var_16bit
129; CHECK-NEXT:    ldrh w0, [x8, :lo12:var_16bit]
130; CHECK-NEXT:    ret
131  %val16_zext64 = load i16, ptr @var_16bit
132  %val64_unsigned = zext i16 %val16_zext64 to i64
133  ret i64 %val64_unsigned
134}
135
136define i16 @ld_a16_16() {
137; CHECK-LABEL: ld_a16_16:
138; CHECK:       // %bb.0:
139; CHECK-NEXT:    adrp x8, var_16bit
140; CHECK-NEXT:    ldrh w8, [x8, :lo12:var_16bit]
141; CHECK-NEXT:    add w0, w8, #1
142; CHECK-NEXT:    ret
143  %val16_anyext = load i16, ptr @var_16bit
144  %newval16 = add i16 %val16_anyext, 1
145  ret i16 %newval16
146}
147
148define void @st_i32_16(i32 %val32) {
149; CHECK-LABEL: st_i32_16:
150; CHECK:       // %bb.0:
151; CHECK-NEXT:    adrp x8, var_16bit
152; CHECK-NEXT:    strh w0, [x8, :lo12:var_16bit]
153; CHECK-NEXT:    ret
154  %val16_trunc32 = trunc i32 %val32 to i16
155  store i16 %val16_trunc32, ptr @var_16bit
156  ret void
157}
158
159define void @st_i64_16(i64 %val64) {
160; CHECK-LABEL: st_i64_16:
161; CHECK:       // %bb.0:
162; CHECK-NEXT:    adrp x8, var_16bit
163; CHECK-NEXT:    strh w0, [x8, :lo12:var_16bit]
164; CHECK-NEXT:    ret
165  %val16_trunc64 = trunc i64 %val64 to i16
166  store i16 %val16_trunc64, ptr @var_16bit
167  ret void
168}
169
170
171define i64 @ld_s32_64() {
172; CHECK-LABEL: ld_s32_64:
173; CHECK:       // %bb.0:
174; CHECK-NEXT:    adrp x8, var_32bit
175; CHECK-NEXT:    ldrsw x0, [x8, :lo12:var_32bit]
176; CHECK-NEXT:    ret
177  %val32_sext64 = load i32, ptr @var_32bit
178  %val64_signed = sext i32 %val32_sext64 to i64
179  ret i64 %val64_signed
180}
181
182define i64 @ld_u32_64() {
183; CHECK-LABEL: ld_u32_64:
184; CHECK:       // %bb.0:
185; CHECK-NEXT:    adrp x8, var_32bit
186; CHECK-NEXT:    ldr w0, [x8, :lo12:var_32bit]
187; CHECK-NEXT:    ret
188  %val32_zext64 = load i32, ptr @var_32bit
189  %val64_unsigned = zext i32 %val32_zext64 to i64
190  ret i64 %val64_unsigned
191}
192
193define i32 @ld_a32_32() {
194; CHECK-LABEL: ld_a32_32:
195; CHECK:       // %bb.0:
196; CHECK-NEXT:    adrp x8, var_32bit
197; CHECK-NEXT:    ldr w8, [x8, :lo12:var_32bit]
198; CHECK-NEXT:    add w0, w8, #1
199; CHECK-NEXT:    ret
200  %val32_anyext = load i32, ptr @var_32bit
201  %newval32 = add i32 %val32_anyext, 1
202  ret i32 %newval32
203}
204
205define void @st_i64_32(i64 %val64) {
206; CHECK-LABEL: st_i64_32:
207; CHECK:       // %bb.0:
208; CHECK-NEXT:    adrp x8, var_32bit
209; CHECK-NEXT:    str w0, [x8, :lo12:var_32bit]
210; CHECK-NEXT:    ret
211  %val32_trunc64 = trunc i64 %val64 to i32
212  store i32 %val32_trunc64, ptr @var_32bit
213  ret void
214}
215
216
217@arr8 = dso_local global ptr null
218@arr16 = dso_local global ptr null
219@arr32 = dso_local global ptr null
220@arr64 = dso_local global ptr null
221
222; Now check that our selection copes with accesses more complex than a
223; single symbol. Permitted offsets should be folded into the loads and
224; stores. Since all forms use the same Operand it's only necessary to
225; check the various access-sizes involved.
226
227define i8 @ld_i8_1(ptr %arr8_addr) {
228; CHECK-LABEL: ld_i8_1:
229; CHECK:       // %bb.0:
230; CHECK-NEXT:    ldrb w0, [x0, #1]
231; CHECK-NEXT:    ret
232  %arr8_sub1_addr = getelementptr i8, ptr %arr8_addr, i64 1
233  %arr8_sub1 = load volatile i8, ptr %arr8_sub1_addr
234  ret i8 %arr8_sub1
235}
236
237define i8 @ld_i8_4095(ptr %arr8_addr) {
238; CHECK-LABEL: ld_i8_4095:
239; CHECK:       // %bb.0:
240; CHECK-NEXT:    ldrb w0, [x0, #4095]
241; CHECK-NEXT:    ret
242  %arr8_sub4095_addr = getelementptr i8, ptr %arr8_addr, i64 4095
243  %arr8_sub4095 = load volatile i8, ptr %arr8_sub4095_addr
244  ret i8 %arr8_sub4095
245}
246
247define i16 @ld_i16_1(ptr %arr16_addr) {
248; CHECK-LABEL: ld_i16_1:
249; CHECK:       // %bb.0:
250; CHECK-NEXT:    ldrh w0, [x0, #2]
251; CHECK-NEXT:    ret
252  %arr16_sub1_addr = getelementptr i16, ptr %arr16_addr, i64 1
253  %arr16_sub1 = load volatile i16, ptr %arr16_sub1_addr
254  ret i16 %arr16_sub1
255}
256
257define i16 @ld_i16_4095(ptr %arr16_addr) {
258; CHECK-LABEL: ld_i16_4095:
259; CHECK:       // %bb.0:
260; CHECK-NEXT:    ldrh w0, [x0, #8190]
261; CHECK-NEXT:    ret
262  %arr16_sub4095_addr = getelementptr i16, ptr %arr16_addr, i64 4095
263  %arr16_sub4095 = load volatile i16, ptr %arr16_sub4095_addr
264  ret i16 %arr16_sub4095
265}
266
267define i32 @ld_i32_1(ptr %arr32_addr) {
268; CHECK-LABEL: ld_i32_1:
269; CHECK:       // %bb.0:
270; CHECK-NEXT:    ldr w0, [x0, #4]
271; CHECK-NEXT:    ret
272  %arr32_sub1_addr = getelementptr i32, ptr %arr32_addr, i64 1
273  %arr32_sub1 = load volatile i32, ptr %arr32_sub1_addr
274  ret i32 %arr32_sub1
275}
276
277define i32 @ld_i32_4095(ptr %arr32_addr) {
278; CHECK-LABEL: ld_i32_4095:
279; CHECK:       // %bb.0:
280; CHECK-NEXT:    ldr w0, [x0, #16380]
281; CHECK-NEXT:    ret
282  %arr32_sub4095_addr = getelementptr i32, ptr %arr32_addr, i64 4095
283  %arr32_sub4095 = load volatile i32, ptr %arr32_sub4095_addr
284  ret i32 %arr32_sub4095
285}
286
287define i64 @ld_i64_1(ptr %arr64_addr) {
288; CHECK-LABEL: ld_i64_1:
289; CHECK:       // %bb.0:
290; CHECK-NEXT:    ldr x0, [x0, #8]
291; CHECK-NEXT:    ret
292  %arr64_sub1_addr = getelementptr i64, ptr %arr64_addr, i64 1
293  %arr64_sub1 = load volatile i64, ptr %arr64_sub1_addr
294  ret i64 %arr64_sub1
295}
296
297define i64 @ld_i64_4095(ptr %arr64_addr) {
298; CHECK-LABEL: ld_i64_4095:
299; CHECK:       // %bb.0:
300; CHECK-NEXT:    ldr x0, [x0, #32760]
301; CHECK-NEXT:    ret
302  %arr64_sub4095_addr = getelementptr i64, ptr %arr64_addr, i64 4095
303  %arr64_sub4095 = load volatile i64, ptr %arr64_sub4095_addr
304  ret i64 %arr64_sub4095
305}
306
307define dso_local void @ldst_float() {
308; CHECK-FP-LABEL: ldst_float:
309; CHECK-FP:       // %bb.0:
310; CHECK-FP-NEXT:    adrp x8, var_float
311; CHECK-FP-NEXT:    ldr s0, [x8, :lo12:var_float]
312; CHECK-FP-NEXT:    str s0, [x8, :lo12:var_float]
313; CHECK-FP-NEXT:    ret
314;
315; CHECK-NOFP-LABEL: ldst_float:
316; CHECK-NOFP:       // %bb.0:
317; CHECK-NOFP-NEXT:    adrp x8, var_float
318; CHECK-NOFP-NEXT:    ldr w9, [x8, :lo12:var_float]
319; CHECK-NOFP-NEXT:    str w9, [x8, :lo12:var_float]
320; CHECK-NOFP-NEXT:    ret
321  %valfp = load volatile float, ptr @var_float
322  store volatile float %valfp, ptr @var_float
323  ret void
324}
325
326define dso_local void @ldst_double() {
327; CHECK-FP-LABEL: ldst_double:
328; CHECK-FP:       // %bb.0:
329; CHECK-FP-NEXT:    adrp x8, var_double
330; CHECK-FP-NEXT:    ldr d0, [x8, :lo12:var_double]
331; CHECK-FP-NEXT:    str d0, [x8, :lo12:var_double]
332; CHECK-FP-NEXT:    ret
333;
334; CHECK-NOFP-LABEL: ldst_double:
335; CHECK-NOFP:       // %bb.0:
336; CHECK-NOFP-NEXT:    adrp x8, var_double
337; CHECK-NOFP-NEXT:    ldr x9, [x8, :lo12:var_double]
338; CHECK-NOFP-NEXT:    str x9, [x8, :lo12:var_double]
339; CHECK-NOFP-NEXT:    ret
340  %valfp = load volatile double, ptr @var_double
341  store volatile double %valfp, ptr @var_double
342  ret void
343}
344