Refactor setExecutionDomain to be clearer about what it's doing and more robust.

llvm-svn: 162844
This commit is contained in:
Tim Northover 2012-08-29 16:36:07 +00:00
parent 8f5c5ded4e
commit 771f160758
1 changed files with 53 additions and 45 deletions

View File

@ -3397,13 +3397,28 @@ ARMBaseInstrInfo::getExecutionDomain(const MachineInstr *MI) const {
return std::make_pair(ExeGeneric, 0);
}
static unsigned getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI,
unsigned SReg, unsigned &Lane) {
unsigned DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);
Lane = 0;
if (DReg != ARM::NoRegister)
return DReg;
Lane = 1;
DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
assert(DReg && "S-register with no D super-register?");
return DReg;
}
void
ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
unsigned DstReg, SrcReg, DReg;
unsigned Lane;
MachineInstrBuilder MIB(MI);
const TargetRegisterInfo *TRI = &getRegisterInfo();
bool isKill;
switch (MI->getOpcode()) {
default:
llvm_unreachable("cannot handle opcode!");
@ -3414,77 +3429,70 @@ ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
// Zap the predicate operands.
assert(!isPredicated(MI) && "Cannot predicate a VORRd");
MI->RemoveOperand(3);
MI->RemoveOperand(2);
// Change to a VORRd which requires two identical use operands.
// Source instruction is %DDst = VMOVD %DSrc, 14, %noreg (; implicits)
DstReg = MI->getOperand(0).getReg();
SrcReg = MI->getOperand(1).getReg();
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
MI->RemoveOperand(i-1);
// Change to a %DDst = VORRd %DSrc, %DSrc, 14, %noreg (; implicits)
MI->setDesc(get(ARM::VORRd));
// Add the extra source operand and new predicates.
// This will go before any implicit ops.
AddDefaultPred(MachineInstrBuilder(MI).addOperand(MI->getOperand(1)));
AddDefaultPred(MIB.addReg(DstReg, RegState::Define)
.addReg(SrcReg)
.addReg(SrcReg));
break;
case ARM::VMOVRS:
if (Domain != ExeNEON)
break;
assert(!isPredicated(MI) && "Cannot predicate a VGETLN");
// Source instruction is %RDst = VMOVRS %SSrc, 14, %noreg (; implicits)
DstReg = MI->getOperand(0).getReg();
SrcReg = MI->getOperand(1).getReg();
DReg = TRI->getMatchingSuperReg(SrcReg, ARM::ssub_0, &ARM::DPRRegClass);
Lane = 0;
if (DReg == ARM::NoRegister) {
DReg = TRI->getMatchingSuperReg(SrcReg, ARM::ssub_1, &ARM::DPRRegClass);
Lane = 1;
assert(DReg && "S-register with no D super-register?");
}
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
MI->RemoveOperand(i-1);
MI->RemoveOperand(3);
MI->RemoveOperand(2);
MI->RemoveOperand(1);
DReg = getCorrespondingDRegAndLane(TRI, SrcReg, Lane);
// Convert to %RDst = VGETLNi32 %DSrc, Lane, 14, %noreg (; imps)
// Note that DSrc has been widened and the other lane may be undef, which
// contaminates the entire register.
MI->setDesc(get(ARM::VGETLNi32));
MIB.addReg(DReg);
MIB.addImm(Lane);
AddDefaultPred(MIB.addReg(DstReg, RegState::Define)
.addReg(DReg, RegState::Undef)
.addImm(Lane));
MIB->getOperand(1).setIsUndef();
// The old source should be an implicit use, otherwise we might think it
// was dead before here.
MIB.addReg(SrcReg, RegState::Implicit);
AddDefaultPred(MIB);
break;
case ARM::VMOVSR:
if (Domain != ExeNEON)
break;
assert(!isPredicated(MI) && "Cannot predicate a VSETLN");
// Source instruction is %SDst = VMOVSR %RSrc, 14, %noreg (; implicits)
DstReg = MI->getOperand(0).getReg();
SrcReg = MI->getOperand(1).getReg();
DReg = TRI->getMatchingSuperReg(DstReg, ARM::ssub_0, &ARM::DPRRegClass);
Lane = 0;
if (DReg == ARM::NoRegister) {
DReg = TRI->getMatchingSuperReg(DstReg, ARM::ssub_1, &ARM::DPRRegClass);
Lane = 1;
assert(DReg && "S-register with no D super-register?");
}
isKill = MI->getOperand(0).isKill();
MI->RemoveOperand(3);
MI->RemoveOperand(2);
MI->RemoveOperand(1);
MI->RemoveOperand(0);
for (unsigned i = MI->getDesc().getNumOperands(); i; --i)
MI->RemoveOperand(i-1);
DReg = getCorrespondingDRegAndLane(TRI, DstReg, Lane);
// Convert to %DDst = VSETLNi32 %DDst, %RSrc, Lane, 14, %noreg (; imps)
// Again DDst may be undefined at the beginning of this instruction.
MI->setDesc(get(ARM::VSETLNi32));
MIB.addReg(DReg, RegState::Define);
MIB.addReg(DReg, RegState::Undef);
MIB.addReg(SrcReg);
MIB.addImm(Lane);
if (isKill)
MIB->addRegisterKilled(DstReg, TRI, true);
MIB->addRegisterDefined(DstReg, TRI);
AddDefaultPred(MIB);
AddDefaultPred(MIB.addReg(DReg, RegState::Define)
.addReg(DReg, RegState::Undef)
.addReg(SrcReg)
.addImm(Lane));
// The destination must be marked as set.
MIB.addReg(DstReg, RegState::Define | RegState::Implicit);
break;
}