XCoreInstrInfo.cpp [plain text]
#include "XCoreMachineFunctionInfo.h"
#include "XCoreInstrInfo.h"
#include "XCore.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "XCoreGenInstrInfo.inc"
#include "llvm/Support/Debug.h"
namespace llvm {
namespace XCore {
enum CondCode {
COND_TRUE,
COND_FALSE,
COND_INVALID
};
}
}
using namespace llvm;
XCoreInstrInfo::XCoreInstrInfo(void)
: TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts)),
RI(*this) {
}
static bool isZeroImm(const MachineOperand &op) {
return op.isImm() && op.getImm() == 0;
}
bool XCoreInstrInfo::isMoveInstr(const MachineInstr &MI,
unsigned &SrcReg, unsigned &DstReg,
unsigned &SrcSR, unsigned &DstSR) const {
SrcSR = DstSR = 0;
if ((MI.getOpcode() == XCore::ADD_2rus || MI.getOpcode() == XCore::SUB_2rus)
&& isZeroImm(MI.getOperand(2))) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
return true;
} else if ((MI.getOpcode() == XCore::OR_3r || MI.getOpcode() == XCore::AND_3r)
&& MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
return true;
}
return false;
}
unsigned
XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
int Opcode = MI->getOpcode();
if (Opcode == XCore::LDWFI)
{
if ((MI->getOperand(1).isFI()) && (MI->getOperand(2).isImm()) && (isZeroImm(MI->getOperand(2))))
{
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
}
}
return 0;
}
unsigned
XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
int &FrameIndex) const {
int Opcode = MI->getOpcode();
if (Opcode == XCore::STWFI)
{
if ((MI->getOperand(1).isFI()) && (MI->getOperand(2).isImm()) && (isZeroImm(MI->getOperand(2))))
{
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
}
}
return 0;
}
bool
XCoreInstrInfo::isInvariantLoad(const MachineInstr *MI) const {
int Opcode = MI->getOpcode();
if (Opcode == XCore::LDWCP_ru6 || Opcode == XCore::LDWCP_lru6) {
return MI->getOperand(1).isCPI();
}
int FrameIndex;
if (isLoadFromStackSlot(MI, FrameIndex)) {
const MachineFrameInfo &MFI =
*MI->getParent()->getParent()->getFrameInfo();
return MFI.isFixedObjectIndex(FrameIndex) &&
MFI.isImmutableObjectIndex(FrameIndex);
}
return false;
}
static inline bool IsBRU(unsigned BrOpc) {
return BrOpc == XCore::BRFU_u6
|| BrOpc == XCore::BRFU_lu6
|| BrOpc == XCore::BRBU_u6
|| BrOpc == XCore::BRBU_lu6;
}
static inline bool IsBRT(unsigned BrOpc) {
return BrOpc == XCore::BRFT_ru6
|| BrOpc == XCore::BRFT_lru6
|| BrOpc == XCore::BRBT_ru6
|| BrOpc == XCore::BRBT_lru6;
}
static inline bool IsBRF(unsigned BrOpc) {
return BrOpc == XCore::BRFF_ru6
|| BrOpc == XCore::BRFF_lru6
|| BrOpc == XCore::BRBF_ru6
|| BrOpc == XCore::BRBF_lru6;
}
static inline bool IsCondBranch(unsigned BrOpc) {
return IsBRF(BrOpc) || IsBRT(BrOpc);
}
static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
{
if (IsBRT(BrOpc)) {
return XCore::COND_TRUE;
} else if (IsBRF(BrOpc)) {
return XCore::COND_FALSE;
} else {
return XCore::COND_INVALID;
}
}
static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
{
switch (CC) {
default: assert(0 && "Illegal condition code!");
case XCore::COND_TRUE : return XCore::BRFT_lru6;
case XCore::COND_FALSE : return XCore::BRFF_lru6;
}
}
static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
{
switch (CC) {
default: assert(0 && "Illegal condition code!");
case XCore::COND_TRUE : return XCore::COND_FALSE;
case XCore::COND_FALSE : return XCore::COND_TRUE;
}
}
bool
XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const {
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
return false;
MachineInstr *LastInst = I;
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
if (IsBRU(LastInst->getOpcode())) {
TBB = LastInst->getOperand(0).getMBB();
return false;
}
XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
if (BranchCode == XCore::COND_INVALID)
return true;
TBB = LastInst->getOperand(1).getMBB();
Cond.push_back(MachineOperand::CreateImm(BranchCode));
Cond.push_back(LastInst->getOperand(0));
return false;
}
MachineInstr *SecondLastInst = I;
if (SecondLastInst && I != MBB.begin() &&
isUnpredicatedTerminator(--I))
return true;
unsigned SecondLastOpc = SecondLastInst->getOpcode();
XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
if (BranchCode != XCore::COND_INVALID
&& IsBRU(LastInst->getOpcode())) {
TBB = SecondLastInst->getOperand(1).getMBB();
Cond.push_back(MachineOperand::CreateImm(BranchCode));
Cond.push_back(SecondLastInst->getOperand(0));
FBB = LastInst->getOperand(0).getMBB();
return false;
}
if (IsBRU(SecondLastInst->getOpcode()) &&
IsBRU(LastInst->getOpcode())) {
TBB = SecondLastInst->getOperand(0).getMBB();
I = LastInst;
if (AllowModify)
I->eraseFromParent();
return false;
}
return true;
}
unsigned
XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond)const{
DebugLoc dl = DebugLoc::getUnknownLoc();
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
assert((Cond.size() == 2 || Cond.size() == 0) &&
"Unexpected number of components!");
if (FBB == 0) { if (Cond.empty()) {
BuildMI(&MBB, dl, get(XCore::BRFU_lu6)).addMBB(TBB);
} else {
unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
BuildMI(&MBB, dl, get(Opc)).addReg(Cond[1].getReg())
.addMBB(TBB);
}
return 1;
}
assert(Cond.size() == 2 && "Unexpected number of components!");
unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
BuildMI(&MBB, dl, get(Opc)).addReg(Cond[1].getReg())
.addMBB(TBB);
BuildMI(&MBB, dl, get(XCore::BRFU_lu6)).addMBB(FBB);
return 2;
}
unsigned
XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin()) return 0;
--I;
if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
return 0;
I->eraseFromParent();
I = MBB.end();
if (I == MBB.begin()) return 1;
--I;
if (!IsCondBranch(I->getOpcode()))
return 1;
I->eraseFromParent();
return 2;
}
bool XCoreInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const {
DebugLoc DL = DebugLoc::getUnknownLoc();
if (I != MBB.end()) DL = I->getDebugLoc();
if (DestRC == SrcRC) {
if (DestRC == XCore::GRRegsRegisterClass) {
BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
.addReg(SrcReg)
.addImm(0);
return true;
} else {
return false;
}
}
if (SrcRC == XCore::RRegsRegisterClass && SrcReg == XCore::SP &&
DestRC == XCore::GRRegsRegisterClass) {
BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg)
.addImm(0);
return true;
}
if (DestRC == XCore::RRegsRegisterClass && DestReg == XCore::SP &&
SrcRC == XCore::GRRegsRegisterClass) {
BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
.addReg(SrcReg);
return true;
}
return false;
}
void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned SrcReg, bool isKill,
int FrameIndex,
const TargetRegisterClass *RC) const
{
DebugLoc DL = DebugLoc::getUnknownLoc();
if (I != MBB.end()) DL = I->getDebugLoc();
BuildMI(MBB, I, DL, get(XCore::STWFI))
.addReg(SrcReg, false, false, isKill)
.addFrameIndex(FrameIndex)
.addImm(0);
}
void XCoreInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
bool isKill, SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const
{
assert(0 && "unimplemented\n");
}
void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const
{
DebugLoc DL = DebugLoc::getUnknownLoc();
if (I != MBB.end()) DL = I->getDebugLoc();
BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
.addFrameIndex(FrameIndex)
.addImm(0);
}
void XCoreInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
SmallVectorImpl<MachineOperand> &Addr,
const TargetRegisterClass *RC,
SmallVectorImpl<MachineInstr*> &NewMIs) const
{
assert(0 && "unimplemented\n");
}
bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const
{
if (CSI.empty()) {
return true;
}
MachineFunction *MF = MBB.getParent();
const MachineFrameInfo *MFI = MF->getFrameInfo();
MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc();
for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
it != CSI.end(); ++it) {
MBB.addLiveIn(it->getReg());
storeRegToStackSlot(MBB, MI, it->getReg(), true,
it->getFrameIdx(), it->getRegClass());
if (emitFrameMoves) {
unsigned SaveLabelId = MMI->NextLabelID();
BuildMI(MBB, MI, DL, get(XCore::DBG_LABEL)).addImm(SaveLabelId);
XFI->getSpillLabels().push_back(
std::pair<unsigned, CalleeSavedInfo>(SaveLabelId, *it));
}
}
return true;
}
bool XCoreInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI) const
{
bool AtStart = MI == MBB.begin();
MachineBasicBlock::iterator BeforeI = MI;
if (!AtStart)
--BeforeI;
for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
it != CSI.end(); ++it) {
loadRegFromStackSlot(MBB, MI, it->getReg(),
it->getFrameIdx(),
it->getRegClass());
assert(MI != MBB.begin() &&
"loadRegFromStackSlot didn't insert any code!");
if (AtStart)
MI = MBB.begin();
else {
MI = BeforeI;
++MI;
}
}
return true;
}
bool XCoreInstrInfo::
BlockHasNoFallThrough(const MachineBasicBlock &MBB) const
{
if (MBB.empty()) return false;
switch (MBB.back().getOpcode()) {
case XCore::RETSP_u6: case XCore::RETSP_lu6:
case XCore::BAU_1r: case XCore::BRFU_u6: case XCore::BRFU_lu6:
case XCore::BRBU_u6:
case XCore::BRBU_lu6:
return true;
default: return false;
}
}
bool XCoreInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
{
assert((Cond.size() == 2) &&
"Invalid XCore branch condition!");
Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
return false;
}