| # RUN: llc -O0 -run-pass=regbankselect %s -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=FAST | |
| # RUN: llc -O0 -run-pass=regbankselect %s -regbankselect-greedy -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY | |
| --- | | |
| ; ModuleID = 'generic-virtual-registers-type-error.mir' | |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" | |
| target triple = "aarch64--" | |
| define void @defaultMapping() { | |
| entry: | |
| ret void | |
| } | |
| define void @defaultMappingVector() { | |
| entry: | |
| ret void | |
| } | |
| define void @defaultMapping1Repair() { | |
| entry: | |
| ret void | |
| } | |
| define void @defaultMapping2Repairs() { | |
| entry: | |
| ret void | |
| } | |
| define void @defaultMappingDefRepair() { | |
| entry: | |
| ret void | |
| } | |
| define void @phiPropagation(i32* %src, i32* %dst, i1 %cond) { | |
| entry: | |
| %srcVal = load i32, i32* %src | |
| br i1 %cond, label %end, label %then | |
| then: | |
| %res = add i32 %srcVal, 36 | |
| br label %end | |
| end: | |
| %toStore = phi i32 [ %srcVal, %entry ], [ %res, %then ] | |
| store i32 %toStore, i32* %dst | |
| ret void | |
| } | |
| define void @defaultMappingUseRepairPhysReg() { | |
| entry: | |
| ret void | |
| } | |
| define void @defaultMappingDefRepairPhysReg() { | |
| entry: | |
| ret void | |
| } | |
| define void @greedyMappingOr() { | |
| entry: | |
| ret void | |
| } | |
| define void @greedyMappingOrWithConstraints() { | |
| entry: | |
| ret void | |
| } | |
| define void @ignoreTargetSpecificInst() { ret void } | |
| define void @regBankSelected_property() { ret void } | |
| define void @bitcast_s32_gpr() { ret void } | |
| define void @bitcast_s32_fpr() { ret void } | |
| define void @bitcast_s32_gpr_fpr() { ret void } | |
| define void @bitcast_s32_fpr_gpr() { ret void } | |
| define void @bitcast_s64_gpr() { ret void } | |
| define void @bitcast_s64_fpr() { ret void } | |
| define void @bitcast_s64_gpr_fpr() { ret void } | |
| define void @bitcast_s64_fpr_gpr() { ret void } | |
| define void @bitcast_s128() { ret void } | |
| define void @copy_s128() { ret void } | |
| define void @copy_s128_from_load() { ret void } | |
| define void @copy_fp16() { ret void } | |
| define i64 @greedyWithChainOfComputation(i64 %arg1, <2 x i32>* %addr) { | |
| %varg1 = bitcast i64 %arg1 to <2 x i32> | |
| %varg2 = load <2 x i32>, <2 x i32>* %addr | |
| %vres = or <2 x i32> %varg1, %varg2 | |
| %res = bitcast <2 x i32> %vres to i64 | |
| ret i64 %res | |
| } | |
| define i64 @floatingPointLoad(i64 %arg1, double* %addr) { | |
| %varg1 = bitcast i64 %arg1 to double | |
| %varg2 = load double, double* %addr | |
| %vres = fadd double %varg1, %varg2 | |
| %res = bitcast double %vres to i64 | |
| ret i64 %res | |
| } | |
| define void @floatingPointStore(i64 %arg1, double* %addr) { | |
| %varg1 = bitcast i64 %arg1 to double | |
| %vres = fadd double %varg1, %varg1 | |
| store double %vres, double* %addr | |
| ret void | |
| } | |
| define void @fp16Ext32() { ret void } | |
| define void @fp16Ext64() { ret void } | |
| define void @fp32Ext64() { ret void } | |
| define half @passFp16(half %p) { | |
| entry: | |
| ret half %p | |
| } | |
| define half @passFp16ViaAllocas(half %p) { | |
| entry: | |
| %p.addr = alloca half, align 2 | |
| store half %p, half* %p.addr, align 2 | |
| %0 = load half, half* %p.addr, align 2 | |
| ret half %0 | |
| } | |
| ... | |
| --- | |
| # Check that we assign a relevant register bank for %0. | |
| # Based on the type i32, this should be gpr. | |
| name: defaultMapping | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $x0 | |
| ; CHECK-LABEL: name: defaultMapping | |
| ; CHECK: %1:gpr(s32) = G_ADD %0 | |
| %0(s32) = COPY $w0 | |
| %1(s32) = G_ADD %0, %0 | |
| ... | |
| --- | |
| # Check that we assign a relevant register bank for %0. | |
| # Based on the type <2 x i32>, this should be fpr. | |
| # FPR is used for both floating point and vector registers. | |
| name: defaultMappingVector | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $d0 | |
| ; CHECK-LABEL: name: defaultMappingVector | |
| ; CHECK: %0:fpr(<2 x s32>) = COPY $d0 | |
| ; CHECK: %1:fpr(<2 x s32>) = G_ADD %0 | |
| %0(<2 x s32>) = COPY $d0 | |
| %1(<2 x s32>) = G_ADD %0, %0 | |
| ... | |
| --- | |
| # Check that we repair the assignment for %0. | |
| # Indeed based on the source of the copy it should live | |
| # in FPR, but at the use, it should be GPR. | |
| name: defaultMapping1Repair | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $s0, $x0 | |
| ; CHECK-LABEL: name: defaultMapping1Repair | |
| ; CHECK: %0:fpr(s32) = COPY $s0 | |
| ; CHECK-NEXT: %1:gpr(s32) = COPY $w0 | |
| ; CHECK-NEXT: %3:gpr(s32) = COPY %0 | |
| ; CHECK-NEXT: %2:gpr(s32) = G_ADD %3, %1 | |
| %0(s32) = COPY $s0 | |
| %1(s32) = COPY $w0 | |
| %2(s32) = G_ADD %0, %1 | |
| ... | |
| # Check that we repair the assignment for %0 differently for both uses. | |
| name: defaultMapping2Repairs | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $s0, $x0 | |
| ; CHECK-LABEL: name: defaultMapping2Repairs | |
| ; CHECK: %0:fpr(s32) = COPY $s0 | |
| ; CHECK-NEXT: %2:gpr(s32) = COPY %0 | |
| ; CHECK-NEXT: %3:gpr(s32) = COPY %0 | |
| ; CHECK-NEXT: %1:gpr(s32) = G_ADD %2, %3 | |
| %0(s32) = COPY $s0 | |
| %1(s32) = G_ADD %0, %0 | |
| ... | |
| --- | |
| # Check that we repair the definition of %1. | |
| # %1 is forced to be into FPR, but its definition actually | |
| # requires that it lives in GPR. Make sure regbankselect | |
| # fixes that. | |
| name: defaultMappingDefRepair | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: fpr } | |
| body: | | |
| bb.0.entry: | |
| liveins: $w0 | |
| ; CHECK-LABEL: name: defaultMappingDefRepair | |
| ; CHECK: %0:gpr(s32) = COPY $w0 | |
| ; CHECK-NEXT: %2:gpr(s32) = G_ADD %0, %0 | |
| ; CHECK-NEXT: %1:fpr(s32) = COPY %2 | |
| %0(s32) = COPY $w0 | |
| %1(s32) = G_ADD %0, %0 | |
| ... | |
| --- | |
| # Check that we are able to propagate register banks from phis. | |
| name: phiPropagation | |
| legalized: true | |
| tracksRegLiveness: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr32, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr64sp, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: gpr32, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 4, class: gpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: gpr32 } | |
| - { id: 1, class: gpr64sp } | |
| - { id: 2, class: gpr32 } | |
| - { id: 3, class: _ } | |
| - { id: 4, class: _ } | |
| - { id: 5, class: _ } | |
| body: | | |
| bb.0.entry: | |
| successors: %bb.2.end, %bb.1.then | |
| liveins: $x0, $x1, $w2 | |
| %0 = LDRWui killed $x0, 0 :: (load 4 from %ir.src) | |
| %5(s32) = COPY %0 | |
| %1(p0) = COPY $x1 | |
| %2 = COPY $w2 | |
| TBNZW killed %2, 0, %bb.2.end | |
| bb.1.then: | |
| successors: %bb.2.end | |
| %3(s32) = G_ADD %5, %5 | |
| bb.2.end: | |
| %4(s32) = PHI %0, %bb.0.entry, %3, %bb.1.then | |
| G_STORE killed %4, killed %1 :: (store 4 into %ir.dst) | |
| RET_ReallyLR | |
| ... | |
| --- | |
| # Make sure we can repair physical register uses as well. | |
| name: defaultMappingUseRepairPhysReg | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $w0, $s0 | |
| ; CHECK-LABEL: name: defaultMappingUseRepairPhysReg | |
| ; CHECK: %0:gpr(s32) = COPY $w0 | |
| ; CHECK-NEXT: %1:fpr(s32) = COPY $s0 | |
| ; CHECK-NEXT: %3:gpr(s32) = COPY %1 | |
| ; CHECK-NEXT: %2:gpr(s32) = G_ADD %0, %3 | |
| %0(s32) = COPY $w0 | |
| %1(s32) = COPY $s0 | |
| %2(s32) = G_ADD %0, %1 | |
| ... | |
| --- | |
| # Make sure we can repair physical register defs. | |
| name: defaultMappingDefRepairPhysReg | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $w0 | |
| ; CHECK-LABEL: name: defaultMappingDefRepairPhysReg | |
| ; CHECK: %0:gpr(s32) = COPY $w0 | |
| ; CHECK-NEXT: %1:gpr(s32) = G_ADD %0, %0 | |
| ; CHECK-NEXT: $s0 = COPY %1 | |
| %0(s32) = COPY $w0 | |
| %1(s32) = G_ADD %0, %0 | |
| $s0 = COPY %1 | |
| ... | |
| --- | |
| # Check that the greedy mode is able to switch the | |
| # G_OR instruction from fpr to gpr. | |
| name: greedyMappingOr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| body: | | |
| bb.0.entry: | |
| liveins: $x0, $x1 | |
| ; CHECK: %0:gpr(<2 x s32>) = COPY $x0 | |
| ; CHECK-NEXT: %1:gpr(<2 x s32>) = COPY $x1 | |
| ; Fast mode tries to reuse the source of the copy for the destination. | |
| ; Now, the default mapping says that %0 and %1 need to be in FPR. | |
| ; The repairing code insert two copies to materialize that. | |
| ; FAST-NEXT: %3:fpr(<2 x s32>) = COPY %0 | |
| ; FAST-NEXT: %4:fpr(<2 x s32>) = COPY %1 | |
| ; The mapping of G_OR is on FPR. | |
| ; FAST-NEXT: %2:fpr(<2 x s32>) = G_OR %3, %4 | |
| ; Greedy mode remapped the instruction on the GPR bank. | |
| ; GREEDY-NEXT: %2:gpr(<2 x s32>) = G_OR %0, %1 | |
| %0(<2 x s32>) = COPY $x0 | |
| %1(<2 x s32>) = COPY $x1 | |
| %2(<2 x s32>) = G_OR %0, %1 | |
| ... | |
| --- | |
| # Check that the greedy mode is able to switch the | |
| # G_OR instruction from fpr to gpr, while still honoring | |
| # %2 constraint. | |
| name: greedyMappingOrWithConstraints | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: fpr } | |
| body: | | |
| bb.0.entry: | |
| liveins: $x0, $x1 | |
| ; CHECK-LABEL: name: greedyMappingOrWithConstraints | |
| ; CHECK: %0:gpr(<2 x s32>) = COPY $x0 | |
| ; CHECK-NEXT: %1:gpr(<2 x s32>) = COPY $x1 | |
| ; Fast mode tries to reuse the source of the copy for the destination. | |
| ; Now, the default mapping says that %0 and %1 need to be in FPR. | |
| ; The repairing code insert two copies to materialize that. | |
| ; FAST-NEXT: %3:fpr(<2 x s32>) = COPY %0 | |
| ; FAST-NEXT: %4:fpr(<2 x s32>) = COPY %1 | |
| ; The mapping of G_OR is on FPR. | |
| ; FAST-NEXT: %2:fpr(<2 x s32>) = G_OR %3, %4 | |
| ; Greedy mode remapped the instruction on the GPR bank. | |
| ; GREEDY-NEXT: %3:gpr(<2 x s32>) = G_OR %0, %1 | |
| ; We need to keep %2 into FPR because we do not know anything about it. | |
| ; GREEDY-NEXT: %2:fpr(<2 x s32>) = COPY %3 | |
| %0(<2 x s32>) = COPY $x0 | |
| %1(<2 x s32>) = COPY $x1 | |
| %2(<2 x s32>) = G_OR %0, %1 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: ignoreTargetSpecificInst | |
| name: ignoreTargetSpecificInst | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr64, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr64, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: gpr64 } | |
| - { id: 1, class: gpr64 } | |
| body: | | |
| bb.0: | |
| liveins: $x0 | |
| ; CHECK: %0:gpr64 = COPY $x0 | |
| ; CHECK-NEXT: %1:gpr64 = ADDXrr %0, %0 | |
| ; CHECK-NEXT: $x0 = COPY %1 | |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 | |
| %0 = COPY $x0 | |
| %1 = ADDXrr %0, %0 | |
| $x0 = COPY %1 | |
| RET_ReallyLR implicit $x0 | |
| ... | |
| --- | |
| # Check that we set the "regBankSelected" property. | |
| # CHECK-LABEL: name: regBankSelected_property | |
| # CHECK: legalized: true | |
| # CHECK: regBankSelected: true | |
| name: regBankSelected_property | |
| legalized: true | |
| regBankSelected: false | |
| body: | | |
| bb.0: | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s32_gpr | |
| name: bitcast_s32_gpr | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:gpr(s32) = COPY $w0 | |
| # CHECK: %1:gpr(s32) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $w0 | |
| %0(s32) = COPY $w0 | |
| %1(s32) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s32_fpr | |
| name: bitcast_s32_fpr | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:fpr(<2 x s16>) = COPY $s0 | |
| # CHECK: %1:fpr(<2 x s16>) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $s0 | |
| %0(<2 x s16>) = COPY $s0 | |
| %1(<2 x s16>) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s32_gpr_fpr | |
| name: bitcast_s32_gpr_fpr | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # FAST-NEXT: - { id: 1, class: fpr, preferred-register: '' } | |
| # GREEDY-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:gpr(s32) = COPY $w0 | |
| # FAST: %1:fpr(<2 x s16>) = G_BITCAST %0 | |
| # GREEDY: %1:gpr(<2 x s16>) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $w0 | |
| %0(s32) = COPY $w0 | |
| %1(<2 x s16>) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s32_fpr_gpr | |
| name: bitcast_s32_fpr_gpr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:fpr(<2 x s16>) = COPY $s0 | |
| # FAST: %1:gpr(s32) = G_BITCAST %0 | |
| # GREEDY: %1:fpr(s32) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $s0 | |
| %0(<2 x s16>) = COPY $s0 | |
| %1(s32) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s64_gpr | |
| name: bitcast_s64_gpr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:gpr(s64) = COPY $x0 | |
| # CHECK: %1:gpr(s64) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $x0 | |
| %0(s64) = COPY $x0 | |
| %1(s64) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s64_fpr | |
| name: bitcast_s64_fpr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:fpr(<2 x s32>) = COPY $d0 | |
| # CHECK: %1:fpr(<2 x s32>) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $d0 | |
| %0(<2 x s32>) = COPY $d0 | |
| %1(<2 x s32>) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s64_gpr_fpr | |
| name: bitcast_s64_gpr_fpr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:gpr(s64) = COPY $x0 | |
| # FAST: %1:fpr(<2 x s32>) = G_BITCAST %0 | |
| # GREEDY: %1:gpr(<2 x s32>) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $x0 | |
| %0(s64) = COPY $x0 | |
| %1(<2 x s32>) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s64_fpr_gpr | |
| name: bitcast_s64_fpr_gpr | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: body: | |
| # CHECK: %0:fpr(<2 x s32>) = COPY $d0 | |
| # FAST: %1:gpr(s64) = G_BITCAST %0 | |
| # GREEDY: %1:fpr(s64) = G_BITCAST %0 | |
| body: | | |
| bb.0: | |
| liveins: $d0 | |
| %0(<2 x s32>) = COPY $d0 | |
| %1(s64) = G_BITCAST %0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: bitcast_s128 | |
| name: bitcast_s128 | |
| legalized: true | |
| tracksRegLiveness: true | |
| registers: | |
| - { id: 0, class: _} | |
| - { id: 1, class: _} | |
| - { id: 2, class: _} | |
| - { id: 3, class: _} | |
| # CHECK: %3:fpr(s128) = G_MERGE_VALUES | |
| # CHECK: %2:fpr(<2 x s64>) = G_BITCAST %3(s128) | |
| body: | | |
| bb.1: | |
| liveins: $x0, $x1 | |
| %0(s64) = COPY $x0 | |
| %1(s64) = COPY $x1 | |
| %3(s128) = G_MERGE_VALUES %0(s64), %1(s64) | |
| %2(<2 x s64>) = G_BITCAST %3(s128) | |
| $q0 = COPY %2(<2 x s64>) | |
| RET_ReallyLR implicit $q0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: copy_s128 | |
| # This test checks that we issue the proper mapping | |
| # for copy of size > 64. | |
| # The mapping should be the same as G_BITCAST. | |
| name: copy_s128 | |
| legalized: true | |
| tracksRegLiveness: true | |
| registers: | |
| - { id: 0, class: _} | |
| - { id: 1, class: _} | |
| - { id: 2, class: _} | |
| - { id: 3, class: _} | |
| - { id: 4, class: _} | |
| # CHECK: %3:fpr(s128) = G_MERGE_VALUES | |
| # CHECK: %4:fpr(s128) = COPY %3(s128) | |
| # CHECK-NEXT: %2:fpr(<2 x s64>) = G_BITCAST %4(s128) | |
| body: | | |
| bb.1: | |
| liveins: $x0, $x1 | |
| %0(s64) = COPY $x0 | |
| %1(s64) = COPY $x1 | |
| %3(s128) = G_MERGE_VALUES %0(s64), %1(s64) | |
| %4(s128) = COPY %3(s128) | |
| %2(<2 x s64>) = G_BITCAST %4(s128) | |
| $q0 = COPY %2(<2 x s64>) | |
| RET_ReallyLR implicit $q0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: copy_s128_from_load | |
| # This test checks that we issue the proper mapping | |
| # for copy of size > 64 when the input is neither | |
| # a physcal register nor a generic register. | |
| # This used to crash when we moved to the statically | |
| # computed mapping, because we were assuming non-physregs | |
| # were generic registers and thus have a type, whereas | |
| # it is not necessarily the case. | |
| name: copy_s128_from_load | |
| legalized: true | |
| tracksRegLiveness: true | |
| registers: | |
| - { id: 0, class: fpr128} | |
| - { id: 1, class: _} | |
| # CHECK: registers: | |
| # CHECK: - { id: 0, class: fpr128, preferred-register: '' } | |
| # CHECK: - { id: 1, class: fpr, preferred-register: '' } | |
| # CHECK: %1:fpr(s128) = COPY %0 | |
| body: | | |
| bb.1: | |
| liveins: $x0 | |
| %0 = LDRQui killed $x0, 0 | |
| %1(s128) = COPY %0 | |
| $q0 = COPY %1(s128) | |
| RET_ReallyLR implicit $q0 | |
| ... | |
| --- | |
| # CHECK-LABEL: name: copy_fp16 | |
| # This test checks that we issue the proper mapping | |
| # for copy of size == 16 when the destination is a fpr | |
| # physical register and the source a gpr. | |
| # We used to crash because we thought that mapping couldn't | |
| # exist in a copy. | |
| name: copy_fp16 | |
| legalized: true | |
| tracksRegLiveness: true | |
| registers: | |
| - { id: 0, class: _} | |
| - { id: 1, class: _} | |
| # CHECK: registers: | |
| # CHECK: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK: %0:gpr(s32) = COPY $w0 | |
| # CHECK-NEXT: %1:gpr(s16) = G_TRUNC %0(s32) | |
| body: | | |
| bb.1: | |
| liveins: $w0 | |
| %0(s32) = COPY $w0 | |
| %1(s16) = G_TRUNC %0(s32) | |
| $h0 = COPY %1(s16) | |
| RET_ReallyLR implicit $h0 | |
| ... | |
| --- | |
| # Make sure the greedy mode is able to take advantage of the | |
| # alternative mappings of G_LOAD to coalesce the whole chain | |
| # of computation on GPR. | |
| # CHECK-LABEL: name: greedyWithChainOfComputation | |
| name: greedyWithChainOfComputation | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| - { id: 3, class: _ } | |
| - { id: 4, class: _ } | |
| - { id: 5, class: _ } | |
| # No repairing should be necessary for both modes. | |
| # CHECK: %0:gpr(s64) = COPY $x0 | |
| # CHECK-NEXT: %1:gpr(p0) = COPY $x1 | |
| # FAST-NEXT: %2:fpr(<2 x s32>) = G_BITCAST %0(s64) | |
| # FAST-NEXT: %3:fpr(<2 x s32>) = G_LOAD %1(p0) :: (load 8 from %ir.addr) | |
| # FAST-NEXT: %4:fpr(<2 x s32>) = G_OR %2, %3 | |
| # GREEDY-NEXT: %2:gpr(<2 x s32>) = G_BITCAST %0(s64) | |
| # GREEDY-NEXT: %3:gpr(<2 x s32>) = G_LOAD %1(p0) :: (load 8 from %ir.addr) | |
| # GREEDY-NEXT: %4:gpr(<2 x s32>) = G_OR %2, %3 | |
| # CHECK-NEXT: %5:gpr(s64) = G_BITCAST %4(<2 x s32>) | |
| # CHECK-NEXT: $x0 = COPY %5(s64) | |
| # CHECK-NEXT: RET_ReallyLR implicit $x0 | |
| body: | | |
| bb.0: | |
| liveins: $x0, $x1 | |
| %0(s64) = COPY $x0 | |
| %1(p0) = COPY $x1 | |
| %2(<2 x s32>) = G_BITCAST %0(s64) | |
| %3(<2 x s32>) = G_LOAD %1(p0) :: (load 8 from %ir.addr) | |
| %4(<2 x s32>) = G_OR %2, %3 | |
| %5(s64) = G_BITCAST %4(<2 x s32>) | |
| $x0 = COPY %5(s64) | |
| RET_ReallyLR implicit $x0 | |
| ... | |
| --- | |
| # Make sure we map what looks like floating point | |
| # loads to floating point register bank. | |
| # CHECK-LABEL: name: floatingPointLoad | |
| name: floatingPointLoad | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 4, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| - { id: 3, class: _ } | |
| # No repairing should be necessary for both modes. | |
| # CHECK: %0:gpr(s64) = COPY $x0 | |
| # CHECK-NEXT: %1:gpr(p0) = COPY $x1 | |
| # CHECK-NEXT: %2:fpr(s64) = G_LOAD %1(p0) :: (load 8 from %ir.addr) | |
| # %0 has been mapped to GPR, we need to repair to match FPR. | |
| # CHECK-NEXT: %4:fpr(s64) = COPY %0 | |
| # CHECK-NEXT: %3:fpr(s64) = G_FADD %4, %2 | |
| # CHECK-NEXT: $x0 = COPY %3(s64) | |
| # CHECK-NEXT: RET_ReallyLR implicit $x0 | |
| body: | | |
| bb.0: | |
| liveins: $x0, $x1 | |
| %0(s64) = COPY $x0 | |
| %1(p0) = COPY $x1 | |
| %2(s64) = G_LOAD %1(p0) :: (load 8 from %ir.addr) | |
| %3(s64) = G_FADD %0, %2 | |
| $x0 = COPY %3(s64) | |
| RET_ReallyLR implicit $x0 | |
| ... | |
| --- | |
| # Make sure we map what looks like floating point | |
| # stores to floating point register bank. | |
| # CHECK-LABEL: name: floatingPointStore | |
| name: floatingPointStore | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 4, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| # CHECK: %0:gpr(s64) = COPY $x0 | |
| # CHECK-NEXT: %1:gpr(p0) = COPY $x1 | |
| # %0 has been mapped to GPR, we need to repair to match FPR. | |
| # CHECK-NEXT: %3:fpr(s64) = COPY %0 | |
| # CHECK-NEXT: %4:fpr(s64) = COPY %0 | |
| # CHECK-NEXT: %2:fpr(s64) = G_FADD %3, %4 | |
| # CHECK-NEXT: G_STORE %2(s64), %1(p0) :: (store 8 into %ir.addr) | |
| # CHECK-NEXT: RET_ReallyLR | |
| body: | | |
| bb.0: | |
| liveins: $x0, $x1 | |
| %0(s64) = COPY $x0 | |
| %1(p0) = COPY $x1 | |
| %2(s64) = G_FADD %0, %0 | |
| G_STORE %2(s64), %1(p0) :: (store 8 into %ir.addr) | |
| RET_ReallyLR | |
| ... | |
| --- | |
| # Make sure we map FPEXT on FPR register bank. | |
| # CHECK-LABEL: name: fp16Ext32 | |
| name: fp16Ext32 | |
| alignment: 2 | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| # CHECK: %1:gpr(s32) = COPY $w0 | |
| # CHECK-NEXT: %0:gpr(s16) = G_TRUNC %1 | |
| # %0 has been mapped to GPR, we need to repair to match FPR. | |
| # CHECK-NEXT: %3:fpr(s16) = COPY %0 | |
| # CHECK-NEXT: %2:fpr(s32) = G_FPEXT %3 | |
| # CHECK-NEXT: $s0 = COPY %2 | |
| # CHECK-NEXT: RET_ReallyLR | |
| body: | | |
| bb.1: | |
| liveins: $w0 | |
| %1(s32) = COPY $w0 | |
| %0(s16) = G_TRUNC %1(s32) | |
| %2(s32) = G_FPEXT %0(s16) | |
| $s0 = COPY %2(s32) | |
| RET_ReallyLR implicit $s0 | |
| ... | |
| --- | |
| # Make sure we map FPEXT on FPR register bank. | |
| # CHECK-LABEL: name: fp16Ext64 | |
| name: fp16Ext64 | |
| alignment: 2 | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 3, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| # CHECK: %1:gpr(s32) = COPY $w0 | |
| # CHECK-NEXT: %0:gpr(s16) = G_TRUNC %1 | |
| # %0 has been mapped to GPR, we need to repair to match FPR. | |
| # CHECK-NEXT: %3:fpr(s16) = COPY %0 | |
| # CHECK-NEXT: %2:fpr(s64) = G_FPEXT %3 | |
| # CHECK-NEXT: $d0 = COPY %2 | |
| # CHECK-NEXT: RET_ReallyLR | |
| body: | | |
| bb.1: | |
| liveins: $w0 | |
| %1(s32) = COPY $w0 | |
| %0(s16) = G_TRUNC %1(s32) | |
| %2(s64) = G_FPEXT %0(s16) | |
| $d0 = COPY %2(s64) | |
| RET_ReallyLR implicit $d0 | |
| ... | |
| --- | |
| # Make sure we map FPEXT on FPR register bank. | |
| # CHECK-LABEL: name: fp32Ext64 | |
| name: fp32Ext64 | |
| alignment: 2 | |
| legalized: true | |
| # CHECK: registers: | |
| # CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 1, class: fpr, preferred-register: '' } | |
| # CHECK-NEXT: - { id: 2, class: fpr, preferred-register: '' } | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| # CHECK: %0:gpr(s32) = COPY $w0 | |
| # %0 has been mapped to GPR, we need to repair to match FPR. | |
| # CHECK-NEXT: %2:fpr(s32) = COPY %0 | |
| # CHECK-NEXT: %1:fpr(s64) = G_FPEXT %2 | |
| # CHECK-NEXT: $d0 = COPY %1 | |
| # CHECK-NEXT: RET_ReallyLR | |
| body: | | |
| bb.1: | |
| liveins: $w0 | |
| %0(s32) = COPY $w0 | |
| %1(s64) = G_FPEXT %0(s32) | |
| $d0 = COPY %1(s64) | |
| RET_ReallyLR implicit $d0 | |
| ... | |
| --- | |
| # Make sure we map FP16 ABI on FPR register bank. | |
| # CHECK-LABEL: name: passFp16 | |
| # CHECK: registers: | |
| # CHECK: - { id: 0, class: fpr, preferred-register: '' } | |
| # CHECK: %0:fpr(s16) = COPY $h0 | |
| # CHECK-NEXT: $h0 = COPY %0(s16) | |
| name: passFp16 | |
| alignment: 2 | |
| legalized: true | |
| registers: | |
| - { id: 0, class: _ } | |
| body: | | |
| bb.1.entry: | |
| liveins: $h0 | |
| %0(s16) = COPY $h0 | |
| $h0 = COPY %0(s16) | |
| RET_ReallyLR implicit $h0 | |
| ... | |
| --- | |
| # Make sure we properly detect fp types through copies. | |
| # In that example, the copy comes from an ABI lowering of a fp type. | |
| # CHECK-LABEL: name: passFp16ViaAllocas | |
| # CHECK: registers: | |
| # CHECK: - { id: 0, class: fpr, preferred-register: '' } | |
| # CHECK: - { id: 1, class: gpr, preferred-register: '' } | |
| # CHECK: - { id: 2, class: fpr, preferred-register: '' } | |
| # | |
| # CHECK: %0:fpr(s16) = COPY $h0 | |
| # CHECK-NEXT: %1:gpr(p0) = G_FRAME_INDEX %stack.0.p.addr | |
| # If we didn't look through the copy for %0, the default mapping | |
| # would have been on GPR and we would have to insert a copy to move | |
| # the value away from FPR (h0). | |
| # CHECK-NEXT: G_STORE %0(s16), %1(p0) :: (store 2 into %ir.p.addr) | |
| # If we didn't look through the copy for %2, the default mapping | |
| # would have been on GPR and we would have to insert a copy to move | |
| # the value to FPR (h0). | |
| # CHECK-NEXT: %2:fpr(s16) = G_LOAD %1(p0) :: (load 2 from %ir.p.addr) | |
| # CHECK-NEXT: $h0 = COPY %2(s16) | |
| name: passFp16ViaAllocas | |
| alignment: 2 | |
| legalized: true | |
| tracksRegLiveness: true | |
| registers: | |
| - { id: 0, class: _ } | |
| - { id: 1, class: _ } | |
| - { id: 2, class: _ } | |
| frameInfo: | |
| maxAlignment: 2 | |
| stack: | |
| - { id: 0, name: p.addr, size: 2, alignment: 2, stack-id: 0 } | |
| body: | | |
| bb.1.entry: | |
| liveins: $h0 | |
| %0(s16) = COPY $h0 | |
| %1(p0) = G_FRAME_INDEX %stack.0.p.addr | |
| G_STORE %0(s16), %1(p0) :: (store 2 into %ir.p.addr) | |
| %2(s16) = G_LOAD %1(p0) :: (load 2 from %ir.p.addr) | |
| $h0 = COPY %2(s16) | |
| RET_ReallyLR implicit $h0 | |
| ... |