1# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
3...
4---
5name:            shl_gep_sext_ldrwrow
6alignment:       4
7legalized:       true
8regBankSelected: true
9tracksRegLiveness: true
10frameInfo:
11  maxAlignment:    1
12machineFunctionInfo: {}
13body:             |
14  bb.0:
15    liveins: $w1, $x0
16
17    ; We should be able to fold a shift + extend into the pattern.
18    ; In this case, we should get a roW load with two 1s, representing a shift
19    ; plus sign extend.
20
21    ; CHECK-LABEL: name: shl_gep_sext_ldrwrow
22    ; CHECK: liveins: $w1, $x0
23    ; CHECK: %base:gpr64sp = COPY $x0
24    ; CHECK: %foo:gpr32 = COPY $w1
25    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 1, 1 :: (load 4)
26    ; CHECK: $w0 = COPY %load
27    ; CHECK: RET_ReallyLR implicit $w0
28    %base:gpr(p0) = COPY $x0
29    %foo:gpr(s32) = COPY $w1
30    %ext:gpr(s64) = G_SEXT %foo(s32)
31    %c:gpr(s64) = G_CONSTANT i64 2
32    %offset:gpr(s64) = G_SHL %ext, %c
33    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
34    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
35    $w0 = COPY %load(s32)
36    RET_ReallyLR implicit $w0
37...
38---
39name:            shl_gep_zext_ldrwrow
40alignment:       4
41legalized:       true
42regBankSelected: true
43tracksRegLiveness: true
44frameInfo:
45  maxAlignment:    1
46machineFunctionInfo: {}
47body:             |
48  bb.0:
49    liveins: $w1, $x0
50
51    ; We should be able to fold a shift + extend into the pattern.
52    ; In this case, we should get a roW load with a 0 representing a zero-extend
53    ; and a 1 representing a shift.
54
55    ; CHECK-LABEL: name: shl_gep_zext_ldrwrow
56    ; CHECK: liveins: $w1, $x0
57    ; CHECK: %base:gpr64sp = COPY $x0
58    ; CHECK: %foo:gpr32 = COPY $w1
59    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4)
60    ; CHECK: $w0 = COPY %load
61    ; CHECK: RET_ReallyLR implicit $w0
62    %base:gpr(p0) = COPY $x0
63    %foo:gpr(s32) = COPY $w1
64    %ext:gpr(s64) = G_ZEXT %foo(s32)
65    %c:gpr(s64) = G_CONSTANT i64 2
66    %offset:gpr(s64) = G_SHL %ext, %c
67    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
68    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
69    $w0 = COPY %load(s32)
70    RET_ReallyLR implicit $w0
71...
72---
73name:            shl_gep_anyext_ldrwrow
74alignment:       4
75legalized:       true
76regBankSelected: true
77tracksRegLiveness: true
78frameInfo:
79  maxAlignment:    1
80machineFunctionInfo: {}
81body:             |
82  bb.0:
83    liveins: $w1, $x0
84
85    ; We should be able to fold a shift + extend into the pattern.
86    ; In this case, we should get a roW load with a 0 representing a zero-extend
87    ; and a 1 representing a shift.
88
89    ; CHECK-LABEL: name: shl_gep_anyext_ldrwrow
90    ; CHECK: liveins: $w1, $x0
91    ; CHECK: %base:gpr64sp = COPY $x0
92    ; CHECK: %foo:gpr32 = COPY $w1
93    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4)
94    ; CHECK: $w0 = COPY %load
95    ; CHECK: RET_ReallyLR implicit $w0
96    %base:gpr(p0) = COPY $x0
97    %foo:gpr(s32) = COPY $w1
98    %ext:gpr(s64) = G_ANYEXT %foo(s32)
99    %c:gpr(s64) = G_CONSTANT i64 2
100    %offset:gpr(s64) = G_SHL %ext, %c
101    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
102    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
103    $w0 = COPY %load(s32)
104    RET_ReallyLR implicit $w0
105...
106---
107name:            mul_gep_sext_ldrwrow
108alignment:       4
109legalized:       true
110regBankSelected: true
111tracksRegLiveness: true
112frameInfo:
113  maxAlignment:    1
114machineFunctionInfo: {}
115body:             |
116  bb.0:
117
118    ; We should be able to do the same with multiplies as with shifts.
119
120    liveins: $w1, $x0
121    ; CHECK-LABEL: name: mul_gep_sext_ldrwrow
122    ; CHECK: liveins: $w1, $x0
123    ; CHECK: %base:gpr64sp = COPY $x0
124    ; CHECK: %foo:gpr32 = COPY $w1
125    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 1, 1 :: (load 4)
126    ; CHECK: $w0 = COPY %load
127    ; CHECK: RET_ReallyLR implicit $w0
128    %base:gpr(p0) = COPY $x0
129    %foo:gpr(s32) = COPY $w1
130    %ext:gpr(s64) = G_SEXT %foo(s32)
131    %c:gpr(s64) = G_CONSTANT i64 4
132    %offset:gpr(s64) = G_MUL %c, %ext
133    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
134    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
135    $w0 = COPY %load(s32)
136    RET_ReallyLR implicit $w0
137...
138---
139name:            mul_gep_zext_ldrwrow
140alignment:       4
141legalized:       true
142regBankSelected: true
143tracksRegLiveness: true
144frameInfo:
145  maxAlignment:    1
146machineFunctionInfo: {}
147body:             |
148  bb.0:
149    liveins: $w1, $x0
150
151    ; We should be able to do the same with multiplies as with shifts.
152
153    ; CHECK-LABEL: name: mul_gep_zext_ldrwrow
154    ; CHECK: liveins: $w1, $x0
155    ; CHECK: %base:gpr64sp = COPY $x0
156    ; CHECK: %foo:gpr32 = COPY $w1
157    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4)
158    ; CHECK: $w0 = COPY %load
159    ; CHECK: RET_ReallyLR implicit $w0
160    %base:gpr(p0) = COPY $x0
161    %foo:gpr(s32) = COPY $w1
162    %ext:gpr(s64) = G_ZEXT %foo(s32)
163    %c:gpr(s64) = G_CONSTANT i64 4
164    %offset:gpr(s64) = G_MUL %c, %ext
165    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
166    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
167    $w0 = COPY %load(s32)
168    RET_ReallyLR implicit $w0
169...
170---
171name:            mul_gep_anyext_ldrwrow
172alignment:       4
173legalized:       true
174regBankSelected: true
175tracksRegLiveness: true
176frameInfo:
177  maxAlignment:    1
178machineFunctionInfo: {}
179body:             |
180  bb.0:
181    liveins: $w1, $x0
182
183    ; We should be able to do the same with multiplies as with shifts.
184
185    ; CHECK-LABEL: name: mul_gep_anyext_ldrwrow
186    ; CHECK: liveins: $w1, $x0
187    ; CHECK: %base:gpr64sp = COPY $x0
188    ; CHECK: %foo:gpr32 = COPY $w1
189    ; CHECK: %load:gpr32 = LDRWroW %base, %foo, 0, 1 :: (load 4)
190    ; CHECK: $w0 = COPY %load
191    ; CHECK: RET_ReallyLR implicit $w0
192    %base:gpr(p0) = COPY $x0
193    %foo:gpr(s32) = COPY $w1
194    %ext:gpr(s64) = G_ANYEXT %foo(s32)
195    %c:gpr(s64) = G_CONSTANT i64 4
196    %offset:gpr(s64) = G_MUL %c, %ext
197    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
198    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 4)
199    $w0 = COPY %load(s32)
200    RET_ReallyLR implicit $w0
201...
202---
203name:            ldrdrow
204alignment:       4
205legalized:       true
206regBankSelected: true
207tracksRegLiveness: true
208frameInfo:
209  maxAlignment:    1
210machineFunctionInfo: {}
211body:             |
212  bb.0:
213    liveins: $w1, $x0, $d0
214
215    ; Verify that we can select LDRDroW.
216
217    ; CHECK-LABEL: name: ldrdrow
218    ; CHECK: liveins: $w1, $x0, $d0
219    ; CHECK: %base:gpr64sp = COPY $x0
220    ; CHECK: %foo:gpr32 = COPY $w1
221    ; CHECK: %load:fpr64 = LDRDroW %base, %foo, 1, 1 :: (load 8)
222    ; CHECK: $x0 = COPY %load
223    ; CHECK: RET_ReallyLR implicit $x0
224    %base:gpr(p0) = COPY $x0
225    %foo:gpr(s32) = COPY $w1
226    %ext:gpr(s64) = G_SEXT %foo(s32)
227    %c:gpr(s64) = G_CONSTANT i64 8
228    %offset:gpr(s64) = G_MUL %c, %ext
229    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
230    %load:fpr(<2 x s32>) = G_LOAD %ptr(p0) :: (load 8)
231    $x0 = COPY %load(<2 x s32>)
232    RET_ReallyLR implicit $x0
233...
234---
235name:            ldrxrow
236alignment:       4
237legalized:       true
238regBankSelected: true
239tracksRegLiveness: true
240frameInfo:
241  maxAlignment:    1
242machineFunctionInfo: {}
243body:             |
244  bb.0:
245    liveins: $w1, $x0, $d0
246
247    ; Verify that we can select LDRXroW.
248
249    ; CHECK-LABEL: name: ldrxrow
250    ; CHECK: liveins: $w1, $x0, $d0
251    ; CHECK: %base:gpr64sp = COPY $x0
252    ; CHECK: %foo:gpr32 = COPY $w1
253    ; CHECK: %load:gpr64 = LDRXroW %base, %foo, 1, 1 :: (load 8)
254    ; CHECK: $x0 = COPY %load
255    ; CHECK: RET_ReallyLR implicit $x0
256    %base:gpr(p0) = COPY $x0
257    %foo:gpr(s32) = COPY $w1
258    %ext:gpr(s64) = G_SEXT %foo(s32)
259    %c:gpr(s64) = G_CONSTANT i64 8
260    %offset:gpr(s64) = G_MUL %c, %ext
261    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
262    %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8)
263    $x0 = COPY %load(s64)
264    RET_ReallyLR implicit $x0
265...
266---
267name: ldrbbrow
268alignment:       4
269legalized:       true
270regBankSelected: true
271tracksRegLiveness: true
272frameInfo:
273  maxAlignment:    1
274machineFunctionInfo: {}
275body:             |
276  bb.1.entry:
277    liveins: $x0, $w0, $w1
278
279    ; Verify that we can select LDRBBroW. Note that there is no shift here,
280    ; but we still fold the extend into the addressing mode.
281
282    ; CHECK-LABEL: name: ldrbbrow
283    ; CHECK: liveins: $x0, $w0, $w1
284    ; CHECK: %val:gpr32 = COPY $w1
285    ; CHECK: %base:gpr64sp = COPY $x0
286    ; CHECK: %load:gpr32 = LDRBBroW %base, %val, 1, 0 :: (load 1)
287    ; CHECK: $w0 = COPY %load
288    ; CHECK: RET_ReallyLR implicit $w0
289    %val:gpr(s32) = COPY $w1
290    %base:gpr(p0) = COPY $x0
291    %ext:gpr(s64) = G_SEXT %val(s32)
292    %ptr:gpr(p0) = G_PTR_ADD %base, %ext(s64)
293    %load:gpr(s32) = G_LOAD %ptr(p0) :: (load 1)
294    $w0 = COPY %load(s32)
295    RET_ReallyLR implicit $w0
296...
297---
298name: ldrhrow
299alignment:       4
300legalized:       true
301regBankSelected: true
302tracksRegLiveness: true
303frameInfo:
304  maxAlignment:    1
305machineFunctionInfo: {}
306body:             |
307  bb.1.entry:
308    liveins: $w1, $x0
309
310    ; Verify that we can select ldrhrow.
311
312    ; CHECK-LABEL: name: ldrhrow
313    ; CHECK: liveins: $w1, $x0
314    ; CHECK: %base:gpr64sp = COPY $x0
315    ; CHECK: %foo:gpr32 = COPY $w1
316    ; CHECK: %load:fpr16 = LDRHroW %base, %foo, 1, 1 :: (load 2)
317    ; CHECK: $h0 = COPY %load
318    ; CHECK: RET_ReallyLR implicit $h0
319    %base:gpr(p0) = COPY $x0
320    %foo:gpr(s32) = COPY $w1
321    %ext:gpr(s64) = G_SEXT %foo(s32)
322    %c:gpr(s64) = G_CONSTANT i64 2
323    %offset:gpr(s64) = G_MUL %c, %ext
324    %ptr:gpr(p0) = G_PTR_ADD %base, %offset(s64)
325    %load:fpr(s16) = G_LOAD %ptr(p0) :: (load 2)
326    $h0 = COPY %load(s16)
327    RET_ReallyLR implicit $h0
328...
329---
330name:            bad_and_mask_1
331alignment:       4
332legalized:       true
333regBankSelected: true
334tracksRegLiveness: true
335frameInfo:
336  maxAlignment:    1
337body:             |
338  bb.0:
339    liveins: $x0
340
341    ; We should get a roX load here, not a roW load. We can't use the mask in
342    ; this test for an extend.
343
344    ; CHECK-LABEL: name: bad_and_mask_1
345    ; CHECK: liveins: $x0
346    ; CHECK: %base:gpr64sp = COPY $x0
347    ; CHECK: %imp:gpr64 = IMPLICIT_DEF
348    ; CHECK: %and:gpr64common = ANDXri %imp, 4103
349    ; CHECK: %load:gpr64 = LDRXroX %base, %and, 0, 1 :: (load 8)
350    ; CHECK: $x1 = COPY %load
351    ; CHECK: RET_ReallyLR implicit $x1
352    %base:gpr(p0) = COPY $x0
353    %imp:gpr(s64) = G_IMPLICIT_DEF
354    %bad_mask:gpr(s64) = G_CONSTANT i64 255
355    %and:gpr(s64) = G_AND %imp, %bad_mask
356    %c:gpr(s64) = G_CONSTANT i64 8
357    %mul:gpr(s64) = G_MUL %c, %and
358    %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64)
359    %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8)
360    $x1 = COPY %load(s64)
361    RET_ReallyLR implicit $x1
362...
363---
364name:            bad_and_mask_2
365alignment:       4
366legalized:       true
367regBankSelected: true
368tracksRegLiveness: true
369frameInfo:
370  maxAlignment:    1
371body:             |
372  bb.0:
373    liveins: $x0
374
375    ; We should get a roX load here, not a roW load. We can't use the mask in
376    ; this test for an extend.
377
378    ; CHECK-LABEL: name: bad_and_mask_2
379    ; CHECK: liveins: $x0
380    ; CHECK: %base:gpr64sp = COPY $x0
381    ; CHECK: %imp:gpr64 = IMPLICIT_DEF
382    ; CHECK: %and:gpr64common = ANDXri %imp, 4111
383    ; CHECK: %load:gpr64 = LDRXroX %base, %and, 0, 1 :: (load 8)
384    ; CHECK: $x1 = COPY %load
385    ; CHECK: RET_ReallyLR implicit $x1
386    %base:gpr(p0) = COPY $x0
387    %imp:gpr(s64) = G_IMPLICIT_DEF
388    %bad_mask:gpr(s64) = G_CONSTANT i64 65535
389    %and:gpr(s64) = G_AND %imp, %bad_mask
390    %c:gpr(s64) = G_CONSTANT i64 8
391    %mul:gpr(s64) = G_MUL %c, %and
392    %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64)
393    %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8)
394    $x1 = COPY %load(s64)
395    RET_ReallyLR implicit $x1
396...
397---
398name:            and_uxtw
399alignment:       4
400legalized:       true
401regBankSelected: true
402tracksRegLiveness: true
403frameInfo:
404  maxAlignment:    1
405body:             |
406  bb.0:
407    liveins: $x0
408
409    ; The mask used for the AND here is legal for producing a roW load.
410
411    ; CHECK-LABEL: name: and_uxtw
412    ; CHECK: liveins: $x0
413    ; CHECK: %base:gpr64sp = COPY $x0
414    ; CHECK: %imp:gpr64 = IMPLICIT_DEF
415    ; CHECK: [[COPY:%[0-9]+]]:gpr32all = COPY %imp.sub_32
416    ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
417    ; CHECK: %load:gpr64 = LDRXroW %base, [[COPY1]], 0, 1 :: (load 8)
418    ; CHECK: $x1 = COPY %load
419    ; CHECK: RET_ReallyLR implicit $x1
420    %base:gpr(p0) = COPY $x0
421    %imp:gpr(s64) = G_IMPLICIT_DEF
422    %mask:gpr(s64) = G_CONSTANT i64 4294967295
423    %and:gpr(s64) = G_AND %imp, %mask
424    %c:gpr(s64) = G_CONSTANT i64 8
425    %mul:gpr(s64) = G_MUL %c, %and
426    %ptr:gpr(p0) = G_PTR_ADD %base, %mul(s64)
427    %load:gpr(s64) = G_LOAD %ptr(p0) :: (load 8)
428    $x1 = COPY %load(s64)
429    RET_ReallyLR implicit $x1
430...
431---
432name:            zext_shl_LDRWroW
433alignment:       4
434legalized:       true
435regBankSelected: true
436tracksRegLiveness: true
437liveins:
438  - { reg: '$w0' }
439  - { reg: '$x1' }
440body:             |
441  bb.1:
442    liveins: $w0, $x1
443
444    ; We try to look through the G_ZEXT of the SHL here.
445
446    ; CHECK-LABEL: name: zext_shl_LDRWroW
447    ; CHECK: liveins: $w0, $x1
448    ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
449    ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1
450    ; CHECK: [[ANDWri:%[0-9]+]]:gpr32common = ANDWri [[COPY]], 7
451    ; CHECK: [[LDRWroW:%[0-9]+]]:gpr32 = LDRWroW [[COPY1]], [[ANDWri]], 0, 1 :: (load 4)
452    ; CHECK: $w0 = COPY [[LDRWroW]]
453    ; CHECK: RET_ReallyLR implicit $w0
454    %0:gpr(s32) = COPY $w0
455    %1:gpr(p0) = COPY $x1
456    %2:gpr(s32) = G_CONSTANT i32 255
457    %3:gpr(s32) = G_AND %0, %2
458    %13:gpr(s64) = G_CONSTANT i64 2
459    %12:gpr(s32) = G_SHL %3, %13(s64)
460    %6:gpr(s64) = G_ZEXT %12(s32)
461    %7:gpr(p0) = G_PTR_ADD %1, %6(s64)
462    %9:gpr(s32) = G_LOAD %7(p0) :: (load 4)
463    $w0 = COPY %9(s32)
464    RET_ReallyLR implicit $w0
465
466...
467