1 # RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
2 # RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY
5 ; ModuleID = 'generic-virtual-registers-type-error.mir'
6 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
7 target triple = "aarch64--"
8 define void @defaultMapping() {
12 define void @defaultMappingVector() {
16 define void @defaultMapping1Repair() {
20 define void @defaultMapping2Repairs() {
24 define void @defaultMappingDefRepair() {
28 define void @phiPropagation(i32* %src, i32* %dst, i1 %cond) {
30 %srcVal = load i32, i32* %src
31 br i1 %cond, label %end, label %then
33 %res = add i32 %srcVal, 36
36 %toStore = phi i32 [ %srcVal, %entry ], [ %res, %then ]
37 store i32 %toStore, i32* %dst
40 define void @defaultMappingUseRepairPhysReg() {
44 define void @defaultMappingDefRepairPhysReg() {
48 define void @greedyMappingOr() {
52 define void @greedyMappingOrWithConstraints() {
57 define void @ignoreTargetSpecificInst() { ret void }
59 define void @regBankSelected_property() { ret void }
61 define void @bitcast_s32_gpr() { ret void }
62 define void @bitcast_s32_fpr() { ret void }
63 define void @bitcast_s32_gpr_fpr() { ret void }
64 define void @bitcast_s32_fpr_gpr() { ret void }
65 define void @bitcast_s64_gpr() { ret void }
66 define void @bitcast_s64_fpr() { ret void }
67 define void @bitcast_s64_gpr_fpr() { ret void }
68 define void @bitcast_s64_fpr_gpr() { ret void }
70 define i64 @greedyWithChainOfComputation(i64 %arg1, <2 x i32>* %addr) {
71 %varg1 = bitcast i64 %arg1 to <2 x i32>
72 %varg2 = load <2 x i32>, <2 x i32>* %addr
73 %vres = or <2 x i32> %varg1, %varg2
74 %res = bitcast <2 x i32> %vres to i64
78 define i64 @floatingPointLoad(i64 %arg1, double* %addr) {
79 %varg1 = bitcast i64 %arg1 to double
80 %varg2 = load double, double* %addr
81 %vres = fadd double %varg1, %varg2
82 %res = bitcast double %vres to i64
86 define void @floatingPointStore(i64 %arg1, double* %addr) {
87 %varg1 = bitcast i64 %arg1 to double
88 %vres = fadd double %varg1, %varg1
89 store double %vres, double* %addr
95 # Check that we assign a relevant register bank for %0.
96 # Based on the type i32, this should be gpr.
99 # CHECK-LABEL: name: defaultMapping
101 # CHECK: - { id: 0, class: gpr, preferred-register: '' }
102 # CHECK: - { id: 1, class: gpr, preferred-register: '' }
104 - { id: 0, class: _ }
105 - { id: 1, class: _ }
109 ; CHECK: %1(s32) = G_ADD %0
111 %1(s32) = G_ADD %0, %0
115 # Check that we assign a relevant register bank for %0.
116 # Based on the type <2 x i32>, this should be fpr.
117 # FPR is used for both floating point and vector registers.
118 name: defaultMappingVector
120 # CHECK-LABEL: name: defaultMappingVector
122 # CHECK: - { id: 0, class: fpr, preferred-register: '' }
123 # CHECK: - { id: 1, class: fpr, preferred-register: '' }
125 - { id: 0, class: _ }
126 - { id: 1, class: _ }
130 ; CHECK: %0(<2 x s32>) = COPY %d0
131 ; CHECK: %1(<2 x s32>) = G_ADD %0
132 %0(<2 x s32>) = COPY %d0
133 %1(<2 x s32>) = G_ADD %0, %0
137 # Check that we repair the assignment for %0.
138 # Indeed based on the source of the copy it should live
139 # in FPR, but at the use, it should be GPR.
140 name: defaultMapping1Repair
142 # CHECK-LABEL: name: defaultMapping1Repair
144 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
145 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
146 # CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' }
147 # CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' }
149 - { id: 0, class: _ }
150 - { id: 1, class: _ }
151 - { id: 2, class: _ }
155 ; CHECK: %0(s32) = COPY %s0
156 ; CHECK-NEXT: %1(s32) = COPY %w0
157 ; CHECK-NEXT: %3(s32) = COPY %0
158 ; CHECK-NEXT: %2(s32) = G_ADD %3, %1
161 %2(s32) = G_ADD %0, %1
164 # Check that we repair the assignment for %0 differently for both uses.
165 name: defaultMapping2Repairs
167 # CHECK-LABEL: name: defaultMapping2Repairs
169 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
170 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
171 # CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' }
172 # CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' }
174 - { id: 0, class: _ }
175 - { id: 1, class: _ }
179 ; CHECK: %0(s32) = COPY %s0
180 ; CHECK-NEXT: %2(s32) = COPY %0
181 ; CHECK-NEXT: %3(s32) = COPY %0
182 ; CHECK-NEXT: %1(s32) = G_ADD %2, %3
184 %1(s32) = G_ADD %0, %0
188 # Check that we repair the definition of %1.
189 # %1 is forced to be into FPR, but its definition actually
190 # requires that it lives in GPR. Make sure regbankselect
192 name: defaultMappingDefRepair
194 # CHECK-LABEL: name: defaultMappingDefRepair
196 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
197 # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' }
198 # CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' }
200 - { id: 0, class: _ }
201 - { id: 1, class: fpr }
205 ; CHECK: %0(s32) = COPY %w0
206 ; CHECK-NEXT: %2(s32) = G_ADD %0, %0
207 ; CHECK-NEXT: %1(s32) = COPY %2
209 %1(s32) = G_ADD %0, %0
213 # Check that we are able to propagate register banks from phis.
216 tracksRegLiveness: true
218 # CHECK-NEXT: - { id: 0, class: gpr32, preferred-register: '' }
219 # CHECK-NEXT: - { id: 1, class: gpr64sp, preferred-register: '' }
220 # CHECK-NEXT: - { id: 2, class: gpr32, preferred-register: '' }
221 # CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' }
222 # CHECK-NEXT: - { id: 4, class: gpr, preferred-register: '' }
224 - { id: 0, class: gpr32 }
225 - { id: 1, class: gpr64sp }
226 - { id: 2, class: gpr32 }
227 - { id: 3, class: _ }
228 - { id: 4, class: _ }
229 - { id: 5, class: _ }
232 successors: %bb.2.end, %bb.1.then
233 liveins: %x0, %x1, %w2
235 %0 = LDRWui killed %x0, 0 :: (load 4 from %ir.src)
239 TBNZW killed %2, 0, %bb.2.end
242 successors: %bb.2.end
243 %3(s32) = G_ADD %5, %5
246 %4(s32) = PHI %0, %bb.0.entry, %3, %bb.1.then
247 G_STORE killed %4, killed %1 :: (store 4 into %ir.dst)
252 # Make sure we can repair physical register uses as well.
253 name: defaultMappingUseRepairPhysReg
255 # CHECK-LABEL: name: defaultMappingUseRepairPhysReg
257 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
258 # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' }
259 # CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' }
260 # CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' }
262 - { id: 0, class: _ }
263 - { id: 1, class: _ }
264 - { id: 2, class: _ }
268 ; CHECK: %0(s32) = COPY %w0
269 ; CHECK-NEXT: %1(s32) = COPY %s0
270 ; CHECK-NEXT: %3(s32) = COPY %1
271 ; CHECK-NEXT: %2(s32) = G_ADD %0, %3
274 %2(s32) = G_ADD %0, %1
278 # Make sure we can repair physical register defs.
279 name: defaultMappingDefRepairPhysReg
281 # CHECK-LABEL: name: defaultMappingDefRepairPhysReg
283 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
284 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
286 - { id: 0, class: _ }
287 - { id: 1, class: _ }
291 ; CHECK: %0(s32) = COPY %w0
292 ; CHECK-NEXT: %1(s32) = G_ADD %0, %0
293 ; CHECK-NEXT: %s0 = COPY %1
295 %1(s32) = G_ADD %0, %0
300 # Check that the greedy mode is able to switch the
301 # G_OR instruction from fpr to gpr.
302 name: greedyMappingOr
304 # CHECK-LABEL: name: greedyMappingOr
306 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
307 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
309 # Fast mode maps vector instruction on FPR.
310 # FAST-NEXT: - { id: 2, class: fpr, preferred-register: '' }
311 # Fast mode needs two extra copies.
312 # FAST-NEXT: - { id: 3, class: fpr, preferred-register: '' }
313 # FAST-NEXT: - { id: 4, class: fpr, preferred-register: '' }
315 # Greedy mode coalesce the computation on the GPR register
316 # because it is the cheapest.
317 # GREEDY-NEXT: - { id: 2, class: gpr, preferred-register: '' }
320 - { id: 0, class: _ }
321 - { id: 1, class: _ }
322 - { id: 2, class: _ }
326 ; CHECK: %0(<2 x s32>) = COPY %x0
327 ; CHECK-NEXT: %1(<2 x s32>) = COPY %x1
330 ; Fast mode tries to reuse the source of the copy for the destination.
331 ; Now, the default mapping says that %0 and %1 need to be in FPR.
332 ; The repairing code insert two copies to materialize that.
333 ; FAST-NEXT: %3(<2 x s32>) = COPY %0
334 ; FAST-NEXT: %4(<2 x s32>) = COPY %1
335 ; The mapping of G_OR is on FPR.
336 ; FAST-NEXT: %2(<2 x s32>) = G_OR %3, %4
338 ; Greedy mode remapped the instruction on the GPR bank.
339 ; GREEDY-NEXT: %2(<2 x s32>) = G_OR %0, %1
340 %0(<2 x s32>) = COPY %x0
341 %1(<2 x s32>) = COPY %x1
342 %2(<2 x s32>) = G_OR %0, %1
346 # Check that the greedy mode is able to switch the
347 # G_OR instruction from fpr to gpr, while still honoring
349 name: greedyMappingOrWithConstraints
351 # CHECK-LABEL: name: greedyMappingOrWithConstraints
353 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
354 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
355 # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
357 # Fast mode maps vector instruction on FPR.
358 # Fast mode needs two extra copies.
359 # FAST-NEXT: - { id: 3, class: fpr, preferred-register: '' }
360 # FAST-NEXT: - { id: 4, class: fpr, preferred-register: '' }
362 # Greedy mode coalesce the computation on the GPR register because it
363 # is the cheapest, but will need one extra copy to materialize %2 into a FPR.
364 # GREEDY-NEXT: - { id: 3, class: gpr, preferred-register: '' }
367 - { id: 0, class: _ }
368 - { id: 1, class: _ }
369 - { id: 2, class: fpr }
373 ; CHECK: %0(<2 x s32>) = COPY %x0
374 ; CHECK-NEXT: %1(<2 x s32>) = COPY %x1
377 ; Fast mode tries to reuse the source of the copy for the destination.
378 ; Now, the default mapping says that %0 and %1 need to be in FPR.
379 ; The repairing code insert two copies to materialize that.
380 ; FAST-NEXT: %3(<2 x s32>) = COPY %0
381 ; FAST-NEXT: %4(<2 x s32>) = COPY %1
382 ; The mapping of G_OR is on FPR.
383 ; FAST-NEXT: %2(<2 x s32>) = G_OR %3, %4
385 ; Greedy mode remapped the instruction on the GPR bank.
386 ; GREEDY-NEXT: %3(<2 x s32>) = G_OR %0, %1
387 ; We need to keep %2 into FPR because we do not know anything about it.
388 ; GREEDY-NEXT: %2(<2 x s32>) = COPY %3
389 %0(<2 x s32>) = COPY %x0
390 %1(<2 x s32>) = COPY %x1
391 %2(<2 x s32>) = G_OR %0, %1
395 # CHECK-LABEL: name: ignoreTargetSpecificInst
396 name: ignoreTargetSpecificInst
399 # CHECK-NEXT: - { id: 0, class: gpr64, preferred-register: '' }
400 # CHECK-NEXT: - { id: 1, class: gpr64, preferred-register: '' }
402 - { id: 0, class: gpr64 }
403 - { id: 1, class: gpr64 }
408 ; CHECK: %0 = COPY %x0
409 ; CHECK-NEXT: %1 = ADDXrr %0, %0
410 ; CHECK-NEXT: %x0 = COPY %1
411 ; CHECK-NEXT: RET_ReallyLR implicit %x0
416 RET_ReallyLR implicit %x0
420 # Check that we set the "regBankSelected" property.
421 # CHECK-LABEL: name: regBankSelected_property
422 # CHECK: legalized: true
423 # CHECK: regBankSelected: true
424 name: regBankSelected_property
426 regBankSelected: false
432 # CHECK-LABEL: name: bitcast_s32_gpr
433 name: bitcast_s32_gpr
437 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
438 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
440 - { id: 0, class: _ }
441 - { id: 1, class: _ }
444 # CHECK: %0(s32) = COPY %w0
445 # CHECK: %1(s32) = G_BITCAST %0
451 %1(s32) = G_BITCAST %0
455 # CHECK-LABEL: name: bitcast_s32_fpr
456 name: bitcast_s32_fpr
460 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
461 # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' }
463 - { id: 0, class: _ }
464 - { id: 1, class: _ }
467 # CHECK: %0(<2 x s16>) = COPY %s0
468 # CHECK: %1(<2 x s16>) = G_BITCAST %0
473 %0(<2 x s16>) = COPY %s0
474 %1(<2 x s16>) = G_BITCAST %0
478 # CHECK-LABEL: name: bitcast_s32_gpr_fpr
479 name: bitcast_s32_gpr_fpr
483 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
484 # FAST-NEXT: - { id: 1, class: fpr, preferred-register: '' }
485 # GREEDY-NEXT: - { id: 1, class: gpr, preferred-register: '' }
487 - { id: 0, class: _ }
488 - { id: 1, class: _ }
491 # CHECK: %0(s32) = COPY %w0
492 # CHECK: %1(<2 x s16>) = G_BITCAST %0
498 %1(<2 x s16>) = G_BITCAST %0
502 # CHECK-LABEL: name: bitcast_s32_fpr_gpr
503 name: bitcast_s32_fpr_gpr
507 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
508 # FAST-NEXT: - { id: 1, class: gpr, preferred-register: '' }
509 # GREEDY-NEXT: - { id: 1, class: fpr, preferred-register: '' }
511 - { id: 0, class: _ }
512 - { id: 1, class: _ }
515 # CHECK: %0(<2 x s16>) = COPY %s0
516 # CHECK: %1(s32) = G_BITCAST %0
521 %0(<2 x s16>) = COPY %s0
522 %1(s32) = G_BITCAST %0
526 # CHECK-LABEL: name: bitcast_s64_gpr
527 name: bitcast_s64_gpr
531 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
532 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
534 - { id: 0, class: _ }
535 - { id: 1, class: _ }
538 # CHECK: %0(s64) = COPY %x0
539 # CHECK: %1(s64) = G_BITCAST %0
545 %1(s64) = G_BITCAST %0
549 # CHECK-LABEL: name: bitcast_s64_fpr
550 name: bitcast_s64_fpr
554 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
555 # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' }
557 - { id: 0, class: _ }
558 - { id: 1, class: _ }
561 # CHECK: %0(<2 x s32>) = COPY %d0
562 # CHECK: %1(<2 x s32>) = G_BITCAST %0
567 %0(<2 x s32>) = COPY %d0
568 %1(<2 x s32>) = G_BITCAST %0
572 # CHECK-LABEL: name: bitcast_s64_gpr_fpr
573 name: bitcast_s64_gpr_fpr
577 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
578 # FAST-NEXT: - { id: 1, class: fpr, preferred-register: '' }
579 # GREEDY-NEXT: - { id: 1, class: gpr, preferred-register: '' }
581 - { id: 0, class: _ }
582 - { id: 1, class: _ }
584 # CHECK: %0(s64) = COPY %x0
585 # CHECK: %1(<2 x s32>) = G_BITCAST %0
591 %1(<2 x s32>) = G_BITCAST %0
595 # CHECK-LABEL: name: bitcast_s64_fpr_gpr
596 name: bitcast_s64_fpr_gpr
600 # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' }
601 # FAST-NEXT: - { id: 1, class: gpr, preferred-register: '' }
602 # GREEDY-NEXT: - { id: 1, class: fpr, preferred-register: '' }
604 - { id: 0, class: _ }
605 - { id: 1, class: _ }
608 # CHECK: %0(<2 x s32>) = COPY %d0
609 # CHECK: %1(s64) = G_BITCAST %0
614 %0(<2 x s32>) = COPY %d0
615 %1(s64) = G_BITCAST %0
619 # Make sure the greedy mode is able to take advantage of the
620 # alternative mappings of G_LOAD to coalesce the whole chain
621 # of computation on GPR.
622 # CHECK-LABEL: name: greedyWithChainOfComputation
623 name: greedyWithChainOfComputation
627 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
628 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
629 # FAST-NEXT: - { id: 2, class: fpr, preferred-register: '' }
630 # FAST-NEXT: - { id: 3, class: fpr, preferred-register: '' }
631 # FAST-NEXT: - { id: 4, class: fpr, preferred-register: '' }
632 # GREEDY-NEXT: - { id: 2, class: gpr, preferred-register: '' }
633 # GREEDY-NEXT: - { id: 3, class: gpr, preferred-register: '' }
634 # GREEDY-NEXT: - { id: 4, class: gpr, preferred-register: '' }
635 # CHECK-NEXT: - { id: 5, class: gpr, preferred-register: '' }
637 - { id: 0, class: _ }
638 - { id: 1, class: _ }
639 - { id: 2, class: _ }
640 - { id: 3, class: _ }
641 - { id: 4, class: _ }
642 - { id: 5, class: _ }
644 # No repairing should be necessary for both modes.
645 # CHECK: %0(s64) = COPY %x0
646 # CHECK-NEXT: %1(p0) = COPY %x1
647 # CHECK-NEXT: %2(<2 x s32>) = G_BITCAST %0(s64)
648 # CHECK-NEXT: %3(<2 x s32>) = G_LOAD %1(p0) :: (load 8 from %ir.addr)
649 # CHECK-NEXT: %4(<2 x s32>) = G_OR %2, %3
650 # CHECK-NEXT: %5(s64) = G_BITCAST %4(<2 x s32>)
651 # CHECK-NEXT: %x0 = COPY %5(s64)
652 # CHECK-NEXT: RET_ReallyLR implicit %x0
660 %2(<2 x s32>) = G_BITCAST %0(s64)
661 %3(<2 x s32>) = G_LOAD %1(p0) :: (load 8 from %ir.addr)
662 %4(<2 x s32>) = G_OR %2, %3
663 %5(s64) = G_BITCAST %4(<2 x s32>)
665 RET_ReallyLR implicit %x0
670 # Make sure we map what looks like floating point
671 # loads to floating point register bank.
672 # CHECK-LABEL: name: floatingPointLoad
673 name: floatingPointLoad
677 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
678 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
679 # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
680 # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' }
681 # CHECK-NEXT: - { id: 4, class: fpr, preferred-register: '' }
683 - { id: 0, class: _ }
684 - { id: 1, class: _ }
685 - { id: 2, class: _ }
686 - { id: 3, class: _ }
688 # No repairing should be necessary for both modes.
689 # CHECK: %0(s64) = COPY %x0
690 # CHECK-NEXT: %1(p0) = COPY %x1
691 # CHECK-NEXT: %2(s64) = G_LOAD %1(p0) :: (load 8 from %ir.addr)
692 # %0 has been mapped to GPR, we need to repair to match FPR.
693 # CHECK-NEXT: %4(s64) = COPY %0
694 # CHECK-NEXT: %3(s64) = G_FADD %4, %2
695 # CHECK-NEXT: %x0 = COPY %3(s64)
696 # CHECK-NEXT: RET_ReallyLR implicit %x0
704 %2(s64) = G_LOAD %1(p0) :: (load 8 from %ir.addr)
705 %3(s64) = G_FADD %0, %2
707 RET_ReallyLR implicit %x0
712 # Make sure we map what looks like floating point
713 # stores to floating point register bank.
714 # CHECK-LABEL: name: floatingPointStore
715 name: floatingPointStore
719 # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' }
720 # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
721 # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' }
722 # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' }
723 # CHECK-NEXT: - { id: 4, class: fpr, preferred-register: '' }
725 - { id: 0, class: _ }
726 - { id: 1, class: _ }
727 - { id: 2, class: _ }
729 # CHECK: %0(s64) = COPY %x0
730 # CHECK-NEXT: %1(p0) = COPY %x1
731 # %0 has been mapped to GPR, we need to repair to match FPR.
732 # CHECK-NEXT: %3(s64) = COPY %0
733 # CHECK-NEXT: %4(s64) = COPY %0
734 # CHECK-NEXT: %2(s64) = G_FADD %3, %4
735 # CHECK-NEXT: G_STORE %2(s64), %1(p0) :: (store 8 into %ir.addr)
736 # CHECK-NEXT: RET_ReallyLR
744 %2(s64) = G_FADD %0, %0
745 G_STORE %2(s64), %1(p0) :: (store 8 into %ir.addr)