forked from OSchip/llvm-project
[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. llvm-svn: 295310
This commit is contained in:
parent
6beef3c087
commit
b1701e0b05
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
...
|
||||
|
|
Loading…
Reference in New Issue