[AVR] Don't select 'MOVW' instructions when they are not supported

We have a subtarget feature which we were ignoring, which was causing us
to generate unsupported instructions for some older chips.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283317 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dylan McKay 2016-10-05 13:38:29 +00:00
parent 3d6fe50568
commit 3beccae0ab

View File

@ -27,6 +27,7 @@
#include "AVR.h"
#include "AVRMachineFunctionInfo.h"
#include "AVRRegisterInfo.h"
#include "AVRTargetMachine.h"
#include "MCTargetDesc/AVRMCTargetDesc.h"
@ -42,22 +43,41 @@ void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL, unsigned DestReg,
unsigned SrcReg, bool KillSrc) const {
const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
const AVRRegisterInfo &TRI = *STI.getRegisterInfo();
unsigned Opc;
if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
Opc = AVR::MOVRdRr;
} else if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
Opc = AVR::MOVWRdRr;
} else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
Opc = AVR::SPREAD;
} else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
Opc = AVR::SPWRITE;
} else {
llvm_unreachable("Impossible reg-to-reg copy");
}
// Not all AVR devices support the 16-bit `MOVW` instruction.
if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
if (STI.hasMOVW()) {
BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
} else {
unsigned DestLo, DestHi, SrcLo, SrcHi;
BuildMI(MBB, MI, DL, get(Opc), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
TRI.splitReg(DestReg, DestLo, DestHi);
TRI.splitReg(SrcReg, SrcLo, SrcHi);
// Copy each individual register with the `MOV` instruction.
BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
.addReg(SrcLo, getKillRegState(KillSrc));
BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
.addReg(SrcHi, getKillRegState(KillSrc));
}
} else {
if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
Opc = AVR::MOVRdRr;
} else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
Opc = AVR::SPREAD;
} else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
Opc = AVR::SPWRITE;
} else {
llvm_unreachable("Impossible reg-to-reg copy");
}
BuildMI(MBB, MI, DL, get(Opc), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
}
}
unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
@ -105,6 +125,9 @@ void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
MachineFunction &MF = *MBB.getParent();
AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
AFI->setHasSpills(true);
DebugLoc DL;
if (MI != MBB.end()) {
@ -460,9 +483,11 @@ unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
case TargetOpcode::DBG_VALUE:
return 0;
case TargetOpcode::INLINEASM: {
const MachineFunction *MF = MI.getParent()->getParent();
const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF->getTarget());
const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();
const MachineFunction &MF = *MI.getParent()->getParent();
const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF.getTarget());
const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
const TargetInstrInfo &TII = *STI.getInstrInfo();
return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
*TM.getMCAsmInfo());
}
@ -470,3 +495,4 @@ unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
}
} // end of namespace llvm