• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s
2
3;
4; Test that we only use the sign/zero extend in the address calculation when
5; necessary.
6;
7; SHIFT
8;
9define i64 @load_addr_shift_zext1(i32 %a, i64 %b) {
10; CHECK-LABEL: load_addr_shift_zext1
11; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
12  %1 = zext i32 %a to i64
13  %2 = shl i64 %1, 3
14  %3 = add i64 %b, %2
15  %4 = inttoptr i64 %3 to i64*
16  %5 = load i64, i64* %4
17  ret i64 %5
18}
19
20define i64 @load_addr_shift_zext2(i32 zeroext %a, i64 %b) {
21; CHECK-LABEL: load_addr_shift_zext2
22; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
23  %1 = zext i32 %a to i64
24  %2 = shl i64 %1, 3
25  %3 = add i64 %b, %2
26  %4 = inttoptr i64 %3 to i64*
27  %5 = load i64, i64* %4
28  ret i64 %5
29}
30
31define i64 @load_addr_shift_zext3(i32 signext %a, i64 %b) {
32; CHECK-LABEL: load_addr_shift_zext3
33; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
34  %1 = zext i32 %a to i64
35  %2 = shl i64 %1, 3
36  %3 = add i64 %b, %2
37  %4 = inttoptr i64 %3 to i64*
38  %5 = load i64, i64* %4
39  ret i64 %5
40}
41
42define i64 @load_addr_shift_sext1(i32 %a, i64 %b) {
43; CHECK-LABEL: load_addr_shift_sext1
44; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
45  %1 = sext i32 %a to i64
46  %2 = shl i64 %1, 3
47  %3 = add i64 %b, %2
48  %4 = inttoptr i64 %3 to i64*
49  %5 = load i64, i64* %4
50  ret i64 %5
51}
52
53define i64 @load_addr_shift_sext2(i32 zeroext %a, i64 %b) {
54; CHECK-LABEL: load_addr_shift_sext2
55; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
56  %1 = sext i32 %a to i64
57  %2 = shl i64 %1, 3
58  %3 = add i64 %b, %2
59  %4 = inttoptr i64 %3 to i64*
60  %5 = load i64, i64* %4
61  ret i64 %5
62}
63
64define i64 @load_addr_shift_sext3(i32 signext %a, i64 %b) {
65; CHECK-LABEL: load_addr_shift_sext3
66; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
67  %1 = sext i32 %a to i64
68  %2 = shl i64 %1, 3
69  %3 = add i64 %b, %2
70  %4 = inttoptr i64 %3 to i64*
71  %5 = load i64, i64* %4
72  ret i64 %5
73}
74
75;
76; MUL
77;
78define i64 @load_addr_mul_zext1(i32 %a, i64 %b) {
79; CHECK-LABEL: load_addr_mul_zext1
80; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
81  %1 = zext i32 %a to i64
82  %2 = mul i64 %1, 8
83  %3 = add i64 %b, %2
84  %4 = inttoptr i64 %3 to i64*
85  %5 = load i64, i64* %4
86  ret i64 %5
87}
88
89define i64 @load_addr_mul_zext2(i32 zeroext %a, i64 %b) {
90; CHECK-LABEL: load_addr_mul_zext2
91; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
92  %1 = zext i32 %a to i64
93  %2 = mul i64 %1, 8
94  %3 = add i64 %b, %2
95  %4 = inttoptr i64 %3 to i64*
96  %5 = load i64, i64* %4
97  ret i64 %5
98}
99
100define i64 @load_addr_mul_zext3(i32 signext %a, i64 %b) {
101; CHECK-LABEL: load_addr_mul_zext3
102; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
103  %1 = zext i32 %a to i64
104  %2 = mul i64 %1, 8
105  %3 = add i64 %b, %2
106  %4 = inttoptr i64 %3 to i64*
107  %5 = load i64, i64* %4
108  ret i64 %5
109}
110
111define i64 @load_addr_mul_sext1(i32 %a, i64 %b) {
112; CHECK-LABEL: load_addr_mul_sext1
113; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
114  %1 = sext i32 %a to i64
115  %2 = mul i64 %1, 8
116  %3 = add i64 %b, %2
117  %4 = inttoptr i64 %3 to i64*
118  %5 = load i64, i64* %4
119  ret i64 %5
120}
121
122define i64 @load_addr_mul_sext2(i32 zeroext %a, i64 %b) {
123; CHECK-LABEL: load_addr_mul_sext2
124; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
125  %1 = sext i32 %a to i64
126  %2 = mul i64 %1, 8
127  %3 = add i64 %b, %2
128  %4 = inttoptr i64 %3 to i64*
129  %5 = load i64, i64* %4
130  ret i64 %5
131}
132
133define i64 @load_addr_mul_sext3(i32 signext %a, i64 %b) {
134; CHECK-LABEL: load_addr_mul_sext3
135; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
136  %1 = sext i32 %a to i64
137  %2 = mul i64 %1, 8
138  %3 = add i64 %b, %2
139  %4 = inttoptr i64 %3 to i64*
140  %5 = load i64, i64* %4
141  ret i64 %5
142}
143
144
145;
146; Test folding of the sign-/zero-extend into the load instruction.
147;
148
149; Unscaled
150define i32 @load_unscaled_zext_i8_to_i32(i64 %a) {
151; CHECK-LABEL: load_unscaled_zext_i8_to_i32
152; CHECK:       ldurb w0, [x0, #-8]
153; CHECK-NOT:   uxtb
154  %1 = sub i64 %a, 8
155  %2 = inttoptr i64 %1 to i8*
156  %3 = load i8, i8* %2
157  %4 = zext i8 %3 to i32
158  ret i32 %4
159}
160
161define i32 @load_unscaled_zext_i16_to_i32(i64 %a) {
162; CHECK-LABEL: load_unscaled_zext_i16_to_i32
163; CHECK:       ldurh w0, [x0, #-8]
164; CHECK-NOT:   uxth
165  %1 = sub i64 %a, 8
166  %2 = inttoptr i64 %1 to i16*
167  %3 = load i16, i16* %2
168  %4 = zext i16 %3 to i32
169  ret i32 %4
170}
171
172define i64 @load_unscaled_zext_i8_to_i64(i64 %a) {
173; CHECK-LABEL: load_unscaled_zext_i8_to_i64
174; CHECK:       ldurb w0, [x0, #-8]
175; CHECK-NOT:   uxtb
176  %1 = sub i64 %a, 8
177  %2 = inttoptr i64 %1 to i8*
178  %3 = load i8, i8* %2
179  %4 = zext i8 %3 to i64
180  ret i64 %4
181}
182
183define i64 @load_unscaled_zext_i16_to_i64(i64 %a) {
184; CHECK-LABEL: load_unscaled_zext_i16_to_i64
185; CHECK:       ldurh w0, [x0, #-8]
186; CHECK-NOT:   uxth
187  %1 = sub i64 %a, 8
188  %2 = inttoptr i64 %1 to i16*
189  %3 = load i16, i16* %2
190  %4 = zext i16 %3 to i64
191  ret i64 %4
192}
193
194define i64 @load_unscaled_zext_i32_to_i64(i64 %a) {
195; CHECK-LABEL: load_unscaled_zext_i32_to_i64
196; CHECK:       ldur w0, [x0, #-8]
197; CHECK-NOT:   uxtw
198  %1 = sub i64 %a, 8
199  %2 = inttoptr i64 %1 to i32*
200  %3 = load i32, i32* %2
201  %4 = zext i32 %3 to i64
202  ret i64 %4
203}
204
205define i32 @load_unscaled_sext_i8_to_i32(i64 %a) {
206; CHECK-LABEL: load_unscaled_sext_i8_to_i32
207; CHECK:       ldursb w0, [x0, #-8]
208; CHECK-NOT:   sxtb
209  %1 = sub i64 %a, 8
210  %2 = inttoptr i64 %1 to i8*
211  %3 = load i8, i8* %2
212  %4 = sext i8 %3 to i32
213  ret i32 %4
214}
215
216define i32 @load_unscaled_sext_i16_to_i32(i64 %a) {
217; CHECK-LABEL: load_unscaled_sext_i16_to_i32
218; CHECK:       ldursh w0, [x0, #-8]
219; CHECK-NOT:   sxth
220  %1 = sub i64 %a, 8
221  %2 = inttoptr i64 %1 to i16*
222  %3 = load i16, i16* %2
223  %4 = sext i16 %3 to i32
224  ret i32 %4
225}
226
227define i64 @load_unscaled_sext_i8_to_i64(i64 %a) {
228; CHECK-LABEL: load_unscaled_sext_i8_to_i64
229; CHECK:       ldursb x0, [x0, #-8]
230; CHECK-NOT:   sxtb
231  %1 = sub i64 %a, 8
232  %2 = inttoptr i64 %1 to i8*
233  %3 = load i8, i8* %2
234  %4 = sext i8 %3 to i64
235  ret i64 %4
236}
237
238define i64 @load_unscaled_sext_i16_to_i64(i64 %a) {
239; CHECK-LABEL: load_unscaled_sext_i16_to_i64
240; CHECK:       ldursh x0, [x0, #-8]
241; CHECK-NOT:   sxth
242  %1 = sub i64 %a, 8
243  %2 = inttoptr i64 %1 to i16*
244  %3 = load i16, i16* %2
245  %4 = sext i16 %3 to i64
246  ret i64 %4
247}
248
249define i64 @load_unscaled_sext_i32_to_i64(i64 %a) {
250; CHECK-LABEL: load_unscaled_sext_i32_to_i64
251; CHECK:       ldursw x0, [x0, #-8]
252; CHECK-NOT:   sxtw
253  %1 = sub i64 %a, 8
254  %2 = inttoptr i64 %1 to i32*
255  %3 = load i32, i32* %2
256  %4 = sext i32 %3 to i64
257  ret i64 %4
258}
259
260; Register
261define i32 @load_register_zext_i8_to_i32(i64 %a, i64 %b) {
262; CHECK-LABEL: load_register_zext_i8_to_i32
263; CHECK:       ldrb w0, [x0, x1]
264; CHECK-NOT:   uxtb
265  %1 = add i64 %a, %b
266  %2 = inttoptr i64 %1 to i8*
267  %3 = load i8, i8* %2
268  %4 = zext i8 %3 to i32
269  ret i32 %4
270}
271
272define i32 @load_register_zext_i16_to_i32(i64 %a, i64 %b) {
273; CHECK-LABEL: load_register_zext_i16_to_i32
274; CHECK:       ldrh w0, [x0, x1]
275; CHECK-NOT:   uxth
276  %1 = add i64 %a, %b
277  %2 = inttoptr i64 %1 to i16*
278  %3 = load i16, i16* %2
279  %4 = zext i16 %3 to i32
280  ret i32 %4
281}
282
283define i64 @load_register_zext_i8_to_i64(i64 %a, i64 %b) {
284; CHECK-LABEL: load_register_zext_i8_to_i64
285; CHECK:       ldrb w0, [x0, x1]
286; CHECK-NOT:   uxtb
287  %1 = add i64 %a, %b
288  %2 = inttoptr i64 %1 to i8*
289  %3 = load i8, i8* %2
290  %4 = zext i8 %3 to i64
291  ret i64 %4
292}
293
294define i64 @load_register_zext_i16_to_i64(i64 %a, i64 %b) {
295; CHECK-LABEL: load_register_zext_i16_to_i64
296; CHECK:       ldrh w0, [x0, x1]
297; CHECK-NOT:   uxth
298  %1 = add i64 %a, %b
299  %2 = inttoptr i64 %1 to i16*
300  %3 = load i16, i16* %2
301  %4 = zext i16 %3 to i64
302  ret i64 %4
303}
304
305define i64 @load_register_zext_i32_to_i64(i64 %a, i64 %b) {
306; CHECK-LABEL: load_register_zext_i32_to_i64
307; CHECK:       ldr w0, [x0, x1]
308; CHECK-NOT:   uxtw
309  %1 = add i64 %a, %b
310  %2 = inttoptr i64 %1 to i32*
311  %3 = load i32, i32* %2
312  %4 = zext i32 %3 to i64
313  ret i64 %4
314}
315
316define i32 @load_register_sext_i8_to_i32(i64 %a, i64 %b) {
317; CHECK-LABEL: load_register_sext_i8_to_i32
318; CHECK:       ldrsb w0, [x0, x1]
319; CHECK-NOT:   sxtb
320  %1 = add i64 %a, %b
321  %2 = inttoptr i64 %1 to i8*
322  %3 = load i8, i8* %2
323  %4 = sext i8 %3 to i32
324  ret i32 %4
325}
326
327define i32 @load_register_sext_i16_to_i32(i64 %a, i64 %b) {
328; CHECK-LABEL: load_register_sext_i16_to_i32
329; CHECK:       ldrsh w0, [x0, x1]
330; CHECK-NOT:   sxth
331  %1 = add i64 %a, %b
332  %2 = inttoptr i64 %1 to i16*
333  %3 = load i16, i16* %2
334  %4 = sext i16 %3 to i32
335  ret i32 %4
336}
337
338define i64 @load_register_sext_i8_to_i64(i64 %a, i64 %b) {
339; CHECK-LABEL: load_register_sext_i8_to_i64
340; CHECK:       ldrsb x0, [x0, x1]
341; CHECK-NOT:   sxtb
342  %1 = add i64 %a, %b
343  %2 = inttoptr i64 %1 to i8*
344  %3 = load i8, i8* %2
345  %4 = sext i8 %3 to i64
346  ret i64 %4
347}
348
349define i64 @load_register_sext_i16_to_i64(i64 %a, i64 %b) {
350; CHECK-LABEL: load_register_sext_i16_to_i64
351; CHECK:       ldrsh x0, [x0, x1]
352; CHECK-NOT:   sxth
353  %1 = add i64 %a, %b
354  %2 = inttoptr i64 %1 to i16*
355  %3 = load i16, i16* %2
356  %4 = sext i16 %3 to i64
357  ret i64 %4
358}
359
360define i64 @load_register_sext_i32_to_i64(i64 %a, i64 %b) {
361; CHECK-LABEL: load_register_sext_i32_to_i64
362; CHECK:       ldrsw x0, [x0, x1]
363; CHECK-NOT:   sxtw
364  %1 = add i64 %a, %b
365  %2 = inttoptr i64 %1 to i32*
366  %3 = load i32, i32* %2
367  %4 = sext i32 %3 to i64
368  ret i64 %4
369}
370
371; Extend
372define i32 @load_extend_zext_i8_to_i32(i64 %a, i32 %b) {
373; CHECK-LABEL: load_extend_zext_i8_to_i32
374; CHECK:       ldrb w0, [x0, w1, sxtw]
375; CHECK-NOT:   uxtb
376  %1 = sext i32 %b to i64
377  %2 = add i64 %a, %1
378  %3 = inttoptr i64 %2 to i8*
379  %4 = load i8, i8* %3
380  %5 = zext i8 %4 to i32
381  ret i32 %5
382}
383
384define i32 @load_extend_zext_i16_to_i32(i64 %a, i32 %b) {
385; CHECK-LABEL: load_extend_zext_i16_to_i32
386; CHECK:       ldrh w0, [x0, w1, sxtw]
387; CHECK-NOT:   uxth
388  %1 = sext i32 %b to i64
389  %2 = add i64 %a, %1
390  %3 = inttoptr i64 %2 to i16*
391  %4 = load i16, i16* %3
392  %5 = zext i16 %4 to i32
393  ret i32 %5
394}
395
396define i64 @load_extend_zext_i8_to_i64(i64 %a, i32 %b) {
397; CHECK-LABEL: load_extend_zext_i8_to_i64
398; CHECK:       ldrb w0, [x0, w1, sxtw]
399; CHECK-NOT:   uxtb
400  %1 = sext i32 %b to i64
401  %2 = add i64 %a, %1
402  %3 = inttoptr i64 %2 to i8*
403  %4 = load i8, i8* %3
404  %5 = zext i8 %4 to i64
405  ret i64 %5
406}
407
408define i64 @load_extend_zext_i16_to_i64(i64 %a, i32 %b) {
409; CHECK-LABEL: load_extend_zext_i16_to_i64
410; CHECK:       ldrh w0, [x0, w1, sxtw]
411; CHECK-NOT:   uxth
412  %1 = sext i32 %b to i64
413  %2 = add i64 %a, %1
414  %3 = inttoptr i64 %2 to i16*
415  %4 = load i16, i16* %3
416  %5 = zext i16 %4 to i64
417  ret i64 %5
418}
419
420define i64 @load_extend_zext_i32_to_i64(i64 %a, i32 %b) {
421; CHECK-LABEL: load_extend_zext_i32_to_i64
422; CHECK:       ldr w0, [x0, w1, sxtw]
423; CHECK-NOT:   uxtw
424  %1 = sext i32 %b to i64
425  %2 = add i64 %a, %1
426  %3 = inttoptr i64 %2 to i32*
427  %4 = load i32, i32* %3
428  %5 = zext i32 %4 to i64
429  ret i64 %5
430}
431
432define i32 @load_extend_sext_i8_to_i32(i64 %a, i32 %b) {
433; CHECK-LABEL: load_extend_sext_i8_to_i32
434; CHECK:       ldrsb w0, [x0, w1, sxtw]
435; CHECK-NOT:   sxtb
436  %1 = sext i32 %b to i64
437  %2 = add i64 %a, %1
438  %3 = inttoptr i64 %2 to i8*
439  %4 = load i8, i8* %3
440  %5 = sext i8 %4 to i32
441  ret i32 %5
442}
443
444define i32 @load_extend_sext_i16_to_i32(i64 %a, i32 %b) {
445; CHECK-LABEL: load_extend_sext_i16_to_i32
446; CHECK:       ldrsh w0, [x0, w1, sxtw]
447; CHECK-NOT:   sxth
448  %1 = sext i32 %b to i64
449  %2 = add i64 %a, %1
450  %3 = inttoptr i64 %2 to i16*
451  %4 = load i16, i16* %3
452  %5 = sext i16 %4 to i32
453  ret i32 %5
454}
455
456define i64 @load_extend_sext_i8_to_i64(i64 %a, i32 %b) {
457; CHECK-LABEL: load_extend_sext_i8_to_i64
458; CHECK:       ldrsb x0, [x0, w1, sxtw]
459; CHECK-NOT:   sxtb
460  %1 = sext i32 %b to i64
461  %2 = add i64 %a, %1
462  %3 = inttoptr i64 %2 to i8*
463  %4 = load i8, i8* %3
464  %5 = sext i8 %4 to i64
465  ret i64 %5
466}
467
468define i64 @load_extend_sext_i16_to_i64(i64 %a, i32 %b) {
469; CHECK-LABEL: load_extend_sext_i16_to_i64
470; CHECK:       ldrsh x0, [x0, w1, sxtw]
471; CHECK-NOT:   sxth
472  %1 = sext i32 %b to i64
473  %2 = add i64 %a, %1
474  %3 = inttoptr i64 %2 to i16*
475  %4 = load i16, i16* %3
476  %5 = sext i16 %4 to i64
477  ret i64 %5
478}
479
480define i64 @load_extend_sext_i32_to_i64(i64 %a, i32 %b) {
481; CHECK-LABEL: load_extend_sext_i32_to_i64
482; CHECK:       ldrsw x0, [x0, w1, sxtw]
483; CHECK-NOT:   sxtw
484  %1 = sext i32 %b to i64
485  %2 = add i64 %a, %1
486  %3 = inttoptr i64 %2 to i32*
487  %4 = load i32, i32* %3
488  %5 = sext i32 %4 to i64
489  ret i64 %5
490}
491
492