mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
More domain conversion; convert VFP VMOVS to NEON instructions in more cases - when we may clobber the other S-lane by converting an S to a D instruction, make an effort to work out if the S lane is clobberable or not.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164114 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3a36444366
commit
97ecb83dff
@ -3425,6 +3425,48 @@ static unsigned getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI,
|
|||||||
return DReg;
|
return DReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane,
|
||||||
|
/// set ImplicitSReg to a register number that must be marked as implicit-use or
|
||||||
|
/// zero if no register needs to be defined as implicit-use.
|
||||||
|
///
|
||||||
|
/// If the function cannot determine if an SPR should be marked implicit use or
|
||||||
|
/// not, it returns false.
|
||||||
|
///
|
||||||
|
/// This function handles cases where an instruction is being modified from taking
|
||||||
|
/// an SPR to a DPR[Lane]. A use of the DPR is being added, which may conflict
|
||||||
|
/// with an earlier def of an SPR corresponding to DPR[Lane^1] (i.e. the other
|
||||||
|
/// lane of the DPR).
|
||||||
|
///
|
||||||
|
/// If the other SPR is defined, an implicit-use of it should be added. Else,
|
||||||
|
/// (including the case where the DPR itself is defined), it should not.
|
||||||
|
///
|
||||||
|
static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI,
|
||||||
|
MachineInstr *MI,
|
||||||
|
unsigned DReg, unsigned Lane,
|
||||||
|
unsigned &ImplicitSReg) {
|
||||||
|
// If the DPR is defined or used already, the other SPR lane will be chained
|
||||||
|
// correctly, so there is nothing to be done.
|
||||||
|
if (MI->definesRegister(DReg, TRI) || MI->readsRegister(DReg, TRI)) {
|
||||||
|
ImplicitSReg = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we need to go searching to see if the SPR is set explicitly.
|
||||||
|
ImplicitSReg = TRI->getSubReg(DReg,
|
||||||
|
(Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
|
||||||
|
MachineBasicBlock::LivenessQueryResult LQR =
|
||||||
|
MI->getParent()->computeRegisterLiveness(TRI, ImplicitSReg, MI);
|
||||||
|
|
||||||
|
if (LQR == MachineBasicBlock::LQR_Live)
|
||||||
|
return true;
|
||||||
|
else if (LQR == MachineBasicBlock::LQR_Unknown)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the register is known not to be live, there is no need to add an
|
||||||
|
// implicit-use.
|
||||||
|
ImplicitSReg = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
||||||
@ -3482,7 +3524,7 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
// was dead before here.
|
// was dead before here.
|
||||||
MIB.addReg(SrcReg, RegState::Implicit);
|
MIB.addReg(SrcReg, RegState::Implicit);
|
||||||
break;
|
break;
|
||||||
case ARM::VMOVSR:
|
case ARM::VMOVSR: {
|
||||||
if (Domain != ExeNEON)
|
if (Domain != ExeNEON)
|
||||||
break;
|
break;
|
||||||
assert(!isPredicated(MI) && "Cannot predicate a VSETLN");
|
assert(!isPredicated(MI) && "Cannot predicate a VSETLN");
|
||||||
@ -3493,12 +3535,9 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
|
|
||||||
DReg = getCorrespondingDRegAndLane(TRI, DstReg, Lane);
|
DReg = getCorrespondingDRegAndLane(TRI, DstReg, Lane);
|
||||||
|
|
||||||
// If we insert both a novel <def> and an <undef> on the DReg, we break
|
unsigned ImplicitSReg;
|
||||||
// any existing dependency chain on the unused lane. Either already being
|
if (!getImplicitSPRUseForDPRUse(TRI, MI, DReg, Lane, ImplicitSReg))
|
||||||
// present means this instruction is in that chain anyway so we can make
|
break;
|
||||||
// the transformation.
|
|
||||||
if (!MI->definesRegister(DReg, TRI) && !MI->readsRegister(DReg, TRI))
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
|
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
|
||||||
MI->RemoveOperand(i-1);
|
MI->RemoveOperand(i-1);
|
||||||
@ -3515,7 +3554,10 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
// The narrower destination must be marked as set to keep previous chains
|
// The narrower destination must be marked as set to keep previous chains
|
||||||
// in place.
|
// in place.
|
||||||
MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
|
MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
|
||||||
|
if (ImplicitSReg != 0)
|
||||||
|
MIB.addReg(ImplicitSReg, RegState::Implicit);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ARM::VMOVS: {
|
case ARM::VMOVS: {
|
||||||
if (Domain != ExeNEON)
|
if (Domain != ExeNEON)
|
||||||
break;
|
break;
|
||||||
@ -3528,12 +3570,9 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
DDst = getCorrespondingDRegAndLane(TRI, DstReg, DstLane);
|
DDst = getCorrespondingDRegAndLane(TRI, DstReg, DstLane);
|
||||||
DSrc = getCorrespondingDRegAndLane(TRI, SrcReg, SrcLane);
|
DSrc = getCorrespondingDRegAndLane(TRI, SrcReg, SrcLane);
|
||||||
|
|
||||||
// If we insert both a novel <def> and an <undef> on the DReg, we break
|
unsigned ImplicitSReg;
|
||||||
// any existing dependency chain on the unused lane. Either already being
|
if (!getImplicitSPRUseForDPRUse(TRI, MI, DSrc, SrcLane, ImplicitSReg))
|
||||||
// present means this instruction is in that chain anyway so we can make
|
break;
|
||||||
// the transformation.
|
|
||||||
if (!MI->definesRegister(DDst, TRI) && !MI->readsRegister(DDst, TRI))
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
|
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
|
||||||
MI->RemoveOperand(i-1);
|
MI->RemoveOperand(i-1);
|
||||||
@ -3551,6 +3590,8 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
// more, so add them in manually.
|
// more, so add them in manually.
|
||||||
MIB.addReg(DstReg, RegState::Implicit | RegState::Define);
|
MIB.addReg(DstReg, RegState::Implicit | RegState::Define);
|
||||||
MIB.addReg(SrcReg, RegState::Implicit);
|
MIB.addReg(SrcReg, RegState::Implicit);
|
||||||
|
if (ImplicitSReg != 0)
|
||||||
|
MIB.addReg(ImplicitSReg, RegState::Implicit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3609,6 +3650,8 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
|
|||||||
// As before, the original destination is no longer represented, add it
|
// As before, the original destination is no longer represented, add it
|
||||||
// implicitly.
|
// implicitly.
|
||||||
MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
|
MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
|
||||||
|
if (ImplicitSReg != 0)
|
||||||
|
MIB.addReg(ImplicitSReg, RegState::Implicit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,22 @@ define float @test_ineligible(float, float %in) {
|
|||||||
; internal fault).
|
; internal fault).
|
||||||
call void @bar()
|
call void @bar()
|
||||||
; CHECL: bl bar
|
; CHECL: bl bar
|
||||||
; CHECK: vmov.f32 {{s[0-9]+}}, {{s[0-9]+}}
|
; CHECK: vext.32
|
||||||
|
; CHECK: vext.32
|
||||||
ret float %val
|
ret float %val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i32 @test_vmovs_no_sreg(i32 %in) {
|
||||||
|
; CHECK: test_vmovs_no_sreg:
|
||||||
|
|
||||||
|
; Check that the movement to and from GPRs takes place in the NEON domain.
|
||||||
|
; CHECK: vmov.32 d
|
||||||
|
%x = bitcast i32 %in to float
|
||||||
|
|
||||||
|
%res = fadd float %x, %x
|
||||||
|
|
||||||
|
; CHECK: vmov.32 r{{[0-9]+}}, d
|
||||||
|
%resi = bitcast float %res to i32
|
||||||
|
|
||||||
|
ret i32 %resi
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user