From 0c9edc1bdb7ffd791816edd6e301b573f85f54b5 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Thu, 16 Feb 2017 12:19:57 +0000 Subject: [PATCH] [ARM] GlobalISel: Select G_SEQUENCE and G_EXTRACT Since they're only used for passing around double precision floating point values into the general purpose registers, we'll lower them to VMOVDRR and VMOVRRD. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295310 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstructionSelector.cpp | 78 +++++++++++++++++++ .../ARM/GlobalISel/arm-instruction-select.mir | 45 +++++++++++ 2 files changed, 123 insertions(+) diff --git a/lib/Target/ARM/ARMInstructionSelector.cpp b/lib/Target/ARM/ARMInstructionSelector.cpp index 5201ddba781..e456534ddf9 100644 --- a/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/lib/Target/ARM/ARMInstructionSelector.cpp @@ -102,6 +102,74 @@ static bool selectFAdd(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, return true; } +static bool selectSequence(MachineInstrBuilder &MIB, + const ARMBaseInstrInfo &TII, + MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI) { + assert(TII.getSubtarget().hasVFP2() && "Can't select sequence without VFP"); + + // We only support G_SEQUENCE as a way to stick together two scalar GPRs + // into one DPR. + unsigned VReg0 = MIB->getOperand(0).getReg(); + (void)VReg0; + assert(MRI.getType(VReg0).getSizeInBits() == 64 && + RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + unsigned VReg1 = MIB->getOperand(1).getReg(); + (void)VReg1; + assert(MRI.getType(VReg1).getSizeInBits() == 32 && + RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + unsigned VReg2 = MIB->getOperand(3).getReg(); + (void)VReg2; + assert(MRI.getType(VReg2).getSizeInBits() == 32 && + RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + + // Remove the operands corresponding to the offsets. + MIB->RemoveOperand(4); + MIB->RemoveOperand(2); + + MIB->setDesc(TII.get(ARM::VMOVDRR)); + MIB.add(predOps(ARMCC::AL)); + + return true; +} + +static bool selectExtract(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, + MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI) { + assert(TII.getSubtarget().hasVFP2() && "Can't select extract without VFP"); + + // We only support G_EXTRACT as a way to break up one DPR into two GPRs. + unsigned VReg0 = MIB->getOperand(0).getReg(); + (void)VReg0; + assert(MRI.getType(VReg0).getSizeInBits() == 32 && + RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + unsigned VReg1 = MIB->getOperand(1).getReg(); + (void)VReg1; + assert(MRI.getType(VReg1).getSizeInBits() == 32 && + RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + unsigned VReg2 = MIB->getOperand(2).getReg(); + (void)VReg2; + assert(MRI.getType(VReg2).getSizeInBits() == 64 && + RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID && + "Unsupported operand for G_SEQUENCE"); + + // Remove the operands corresponding to the offsets. + MIB->RemoveOperand(4); + MIB->RemoveOperand(3); + + MIB->setDesc(TII.get(ARM::VMOVRRD)); + MIB.add(predOps(ARMCC::AL)); + + return true; +} + /// Select the opcode for simple extensions (that translate to a single SXT/UXT /// instruction). Extension operations more complicated than that should not /// invoke this. @@ -237,6 +305,16 @@ bool ARMInstructionSelector::select(MachineInstr &I) const { MIB.addImm(0).add(predOps(ARMCC::AL)); break; } + case G_SEQUENCE: { + if (!selectSequence(MIB, TII, MRI, TRI, RBI)) + return false; + break; + } + case G_EXTRACT: { + if (!selectExtract(MIB, TII, MRI, TRI, RBI)) + return false; + break; + } default: return false; } diff --git a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir index 659c52c338d..0acb32edcd4 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir @@ -14,6 +14,8 @@ define void @test_load_from_stack() { ret void } + define void @test_soft_fp_double() #0 { ret void } + attributes #0 = { "target-features"="+vfp2,-neonfp" } ... --- @@ -328,3 +330,46 @@ body: | BX_RET 14, _ ; CHECK: BX_RET 14, _ ... +--- +name: test_soft_fp_double +# CHECK-LABEL: name: test_soft_fp_double +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: fprb } + - { id: 3, class: gprb } + - { id: 4, class: gprb } +# CHECK-DAG: id: {{[0-9]+}}, class: gpr +# CHECK-DAG: id: {{[0-9]+}}, class: gpr +# CHECK-DAG: id: {{[0-9]+}}, class: gpr +# CHECK-DAG: id: {{[0-9]+}}, class: gpr +# CHECK-DAG: id: [[DREG:[0-9]+]], class: dpr +body: | + bb.0: + liveins: %r0, %r1, %r2, %r3 + + %0(s32) = COPY %r2 + ; CHECK: [[IN1:%[0-9]+]] = COPY %r2 + + %1(s32) = COPY %r3 + ; CHECK: [[IN2:%[0-9]+]] = COPY %r3 + + %2(s64) = G_SEQUENCE %0(s32), 0, %1(s32), 1 + ; CHECK: %[[DREG]] = VMOVDRR [[IN1]], [[IN2]] + + %3(s32), %4(s32) = G_EXTRACT %2(s64), 0, 32 + ; CHECK: [[OUT1:%[0-9]+]], [[OUT2:%[0-9]+]] = VMOVRRD %[[DREG]] + + %r0 = COPY %3 + ; CHECK: %r0 = COPY [[OUT1]] + + %r1 = COPY %4 + ; CHECK: %r1 = COPY [[OUT2]] + + BX_RET 14, _, implicit %r0, implicit %r1 + ; CHECK: BX_RET 14, _, implicit %r0, implicit %r1 +... -- 2.50.1