mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Split thumb-related stuff into separate classes.
Step 1: ARMInstructionInfo => {ARM,Thumb}InstructionInfo git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c4233af200
commit
d49ea77cbc
@ -20,7 +20,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ARMTargetMachine;
|
||||
class ARMBaseTargetMachine;
|
||||
class FunctionPass;
|
||||
class MachineCodeEmitter;
|
||||
class JITCodeEmitter;
|
||||
@ -28,8 +28,8 @@ class raw_ostream;
|
||||
|
||||
// Enums corresponding to ARM condition codes
|
||||
namespace ARMCC {
|
||||
// The CondCodes constants map directly to the 4-bit encoding of the
|
||||
// condition field for predicated instructions.
|
||||
// The CondCodes constants map directly to the 4-bit encoding of the
|
||||
// condition field for predicated instructions.
|
||||
enum CondCodes {
|
||||
EQ,
|
||||
NE,
|
||||
@ -47,7 +47,7 @@ namespace ARMCC {
|
||||
LE,
|
||||
AL
|
||||
};
|
||||
|
||||
|
||||
inline static CondCodes getOppositeCondition(CondCodes CC){
|
||||
switch (CC) {
|
||||
default: assert(0 && "Unknown condition code");
|
||||
@ -90,17 +90,17 @@ inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
|
||||
}
|
||||
}
|
||||
|
||||
FunctionPass *createARMISelDag(ARMTargetMachine &TM);
|
||||
FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM);
|
||||
FunctionPass *createARMCodePrinterPass(raw_ostream &O,
|
||||
ARMTargetMachine &TM,
|
||||
ARMBaseTargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool Verbose);
|
||||
FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
|
||||
FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
MachineCodeEmitter &MCE);
|
||||
|
||||
FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
|
||||
FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
MachineCodeEmitter &MCE);
|
||||
FunctionPass *createARMJITCodeEmitterPass(ARMTargetMachine &TM,
|
||||
FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
JITCodeEmitter &JCE);
|
||||
|
||||
FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
|
||||
|
@ -176,11 +176,11 @@ namespace {
|
||||
|
||||
namespace llvm {
|
||||
|
||||
FunctionPass *createARMCodeEmitterPass(ARMTargetMachine &TM,
|
||||
FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
MachineCodeEmitter &MCE) {
|
||||
return new Emitter<MachineCodeEmitter>(TM, MCE);
|
||||
}
|
||||
FunctionPass *createARMJITCodeEmitterPass(ARMTargetMachine &TM,
|
||||
FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
return new Emitter<JITCodeEmitter>(TM, JCE);
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ static const unsigned arm_dsubreg_1 = 6;
|
||||
///
|
||||
namespace {
|
||||
class ARMDAGToDAGISel : public SelectionDAGISel {
|
||||
ARMTargetMachine &TM;
|
||||
ARMBaseTargetMachine &TM;
|
||||
|
||||
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const ARMSubtarget *Subtarget;
|
||||
|
||||
public:
|
||||
explicit ARMDAGToDAGISel(ARMTargetMachine &tm)
|
||||
explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm)
|
||||
: SelectionDAGISel(tm), TM(tm),
|
||||
Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
|
||||
}
|
||||
@ -1002,6 +1002,6 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
|
||||
/// createARMISelDag - This pass converts a legalized DAG into a
|
||||
/// ARM-specific DAG, ready for instruction scheduling.
|
||||
///
|
||||
FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) {
|
||||
FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM) {
|
||||
return new ARMDAGToDAGISel(TM);
|
||||
}
|
||||
|
@ -39,11 +39,14 @@ const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
|
||||
return MIB.addReg(0);
|
||||
}
|
||||
|
||||
ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
|
||||
ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &STI)
|
||||
: TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
|
||||
RI(*this, STI) {
|
||||
}
|
||||
|
||||
ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
|
||||
: ARMBaseInstrInfo(STI) {
|
||||
}
|
||||
|
||||
/// Return true if the instruction is a register to register move and
|
||||
/// leave the source and dest operands in the passed parameters.
|
||||
@ -65,10 +68,6 @@ bool ARMInstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
return true;
|
||||
case ARM::MOVr:
|
||||
case ARM::tMOVr:
|
||||
case ARM::tMOVhir2lor:
|
||||
case ARM::tMOVlor2hir:
|
||||
case ARM::tMOVhir2hir:
|
||||
assert(MI.getDesc().getNumOperands() >= 2 &&
|
||||
MI.getOperand(0).isReg() &&
|
||||
MI.getOperand(1).isReg() &&
|
||||
@ -102,14 +101,6 @@ unsigned ARMInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
case ARM::tRestore:
|
||||
if (MI->getOperand(1).isFI() &&
|
||||
MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -137,22 +128,15 @@ unsigned ARMInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
case ARM::tSpill:
|
||||
if (MI->getOperand(1).isFI() &&
|
||||
MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARMInstrInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg,
|
||||
const MachineInstr *Orig) const {
|
||||
void ARMBaseInstrInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg,
|
||||
const MachineInstr *Orig) const {
|
||||
DebugLoc dl = Orig->getDebugLoc();
|
||||
if (Orig->getOpcode() == ARM::MOVi2pieces) {
|
||||
RI.emitLoadConstPool(MBB, I, DestReg, Orig->getOperand(1).getImm(),
|
||||
@ -198,9 +182,9 @@ static unsigned getUnindexedOpcode(unsigned Opc) {
|
||||
}
|
||||
|
||||
MachineInstr *
|
||||
ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
MachineBasicBlock::iterator &MBBI,
|
||||
LiveVariables *LV) const {
|
||||
ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
MachineBasicBlock::iterator &MBBI,
|
||||
LiveVariables *LV) const {
|
||||
if (!EnableARM3Addr)
|
||||
return NULL;
|
||||
|
||||
@ -261,7 +245,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
} else
|
||||
} else
|
||||
UpdateMI = BuildMI(MF, MI->getDebugLoc(),
|
||||
get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg)
|
||||
@ -312,7 +296,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
NewMIs.push_back(UpdateMI);
|
||||
NewMIs.push_back(MemMI);
|
||||
}
|
||||
|
||||
|
||||
// Transfer LiveVariables states, kill / dead info.
|
||||
if (LV) {
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
@ -320,7 +304,7 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
if (MO.isReg() && MO.getReg() &&
|
||||
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
|
||||
unsigned Reg = MO.getReg();
|
||||
|
||||
|
||||
LiveVariables::VarInfo &VI = LV->getVarInfo(Reg);
|
||||
if (MO.isDef()) {
|
||||
MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI;
|
||||
@ -349,18 +333,19 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
}
|
||||
|
||||
// Branch analysis.
|
||||
bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
bool
|
||||
ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
// If the block has no terminators, it just falls into the block after it.
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
|
||||
return false;
|
||||
|
||||
|
||||
// Get the last instruction in the block.
|
||||
MachineInstr *LastInst = I;
|
||||
|
||||
|
||||
// If there is only one terminator instruction, process it.
|
||||
unsigned LastOpc = LastInst->getOpcode();
|
||||
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
|
||||
@ -377,14 +362,14 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
}
|
||||
return true; // Can't handle indirect branch.
|
||||
}
|
||||
|
||||
|
||||
// Get the instruction before it if it is a terminator.
|
||||
MachineInstr *SecondLastInst = I;
|
||||
|
||||
|
||||
// If there are three terminators, we don't know what sort of block this is.
|
||||
if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
|
||||
return true;
|
||||
|
||||
|
||||
// If the block ends with ARM::B/ARM::tB and a ARM::Bcc/ARM::tBcc, handle it.
|
||||
unsigned SecondLastOpc = SecondLastInst->getOpcode();
|
||||
if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) ||
|
||||
@ -395,8 +380,8 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
FBB = LastInst->getOperand(0).getMBB();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the block ends with two unconditional branches, handle it. The second
|
||||
|
||||
// If the block ends with two unconditional branches, handle it. The second
|
||||
// one is not executed, so remove it.
|
||||
if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) &&
|
||||
(LastOpc == ARM::B || LastOpc == ARM::tB)) {
|
||||
@ -417,14 +402,14 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
if (AllowModify)
|
||||
I->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, can't handle this.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned ARMInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
int BOpc = AFI->isThumbFunction() ? ARM::tB : ARM::B;
|
||||
@ -435,26 +420,26 @@ unsigned ARMInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
--I;
|
||||
if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc)
|
||||
return 0;
|
||||
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
|
||||
|
||||
I = MBB.end();
|
||||
|
||||
|
||||
if (I == MBB.begin()) return 1;
|
||||
--I;
|
||||
if (I->getOpcode() != BccOpc)
|
||||
return 1;
|
||||
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned
|
||||
ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const {
|
||||
ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const {
|
||||
// FIXME this should probably have a DebugLoc argument
|
||||
DebugLoc dl = DebugLoc::getUnknownLoc();
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
@ -466,7 +451,7 @@ ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||
"ARM branch conditions have two components!");
|
||||
|
||||
|
||||
if (FBB == 0) {
|
||||
if (Cond.empty()) // Unconditional branch?
|
||||
BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB);
|
||||
@ -475,7 +460,7 @@ ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Two-way conditional branch.
|
||||
BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
|
||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
||||
@ -488,43 +473,18 @@ bool ARMInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC) const {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
if (!AFI->isThumbFunction()) {
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), DestReg)
|
||||
.addReg(SrcReg)));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
} else if (DestRC == ARM::tGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DestRC != SrcRC) {
|
||||
// Not yet supported!
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (DestRC == ARM::SPRRegisterClass)
|
||||
if (DestRC == ARM::GPRRegisterClass)
|
||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), DestReg)
|
||||
.addReg(SrcReg)));
|
||||
else if (DestRC == ARM::SPRRegisterClass)
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYS), DestReg)
|
||||
.addReg(SrcReg));
|
||||
else if (DestRC == ARM::DPRRegisterClass)
|
||||
@ -534,7 +494,7 @@ bool ARMInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
BuildMI(MBB, I, DL, get(ARM::VMOVQ), DestReg).addReg(SrcReg);
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -546,19 +506,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
assert (!AFI->isThumbFunction());
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addReg(0).addImm(0));
|
||||
} else if (RC == ARM::tGPRRegisterClass) {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
assert (AFI->isThumbFunction());
|
||||
BuildMI(MBB, I, DL, get(ARM::tSpill))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
} else if (RC == ARM::DPRRegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FSTD))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
@ -579,16 +529,6 @@ void ARMInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
unsigned Opc = 0;
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (AFI->isThumbFunction()) {
|
||||
Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
|
||||
MachineInstrBuilder MIB =
|
||||
BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
|
||||
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
|
||||
MIB.addOperand(Addr[i]);
|
||||
NewMIs.push_back(MIB);
|
||||
return;
|
||||
}
|
||||
Opc = ARM::STR;
|
||||
} else if (RC == ARM::DPRRegisterClass) {
|
||||
Opc = ARM::FSTD;
|
||||
@ -597,7 +537,7 @@ void ARMInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
|
||||
Opc = ARM::FSTS;
|
||||
}
|
||||
|
||||
MachineInstrBuilder MIB =
|
||||
MachineInstrBuilder MIB =
|
||||
BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
|
||||
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
|
||||
MIB.addOperand(Addr[i]);
|
||||
@ -614,17 +554,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
assert (!AFI->isThumbFunction());
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg)
|
||||
.addFrameIndex(FI).addReg(0).addImm(0));
|
||||
} else if (RC == ARM::tGPRRegisterClass) {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
assert (AFI->isThumbFunction());
|
||||
BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
} else if (RC == ARM::DPRRegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FLDD), DestReg)
|
||||
.addFrameIndex(FI).addImm(0));
|
||||
@ -643,15 +574,6 @@ loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
unsigned Opc = 0;
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (AFI->isThumbFunction()) {
|
||||
Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
|
||||
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
|
||||
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
|
||||
MIB.addOperand(Addr[i]);
|
||||
NewMIs.push_back(MIB);
|
||||
return;
|
||||
}
|
||||
Opc = ARM::LDR;
|
||||
} else if (RC == ARM::DPRRegisterClass) {
|
||||
Opc = ARM::FLDD;
|
||||
@ -668,59 +590,6 @@ loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
|
||||
return;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (!AFI->isThumbFunction() || CSI.empty())
|
||||
return false;
|
||||
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
||||
|
||||
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
// Add the callee-saved register as live-in. It's killed at the spill.
|
||||
MBB.addLiveIn(Reg);
|
||||
MIB.addReg(Reg, RegState::Kill);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (!AFI->isThumbFunction() || CSI.empty())
|
||||
return false;
|
||||
|
||||
bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
|
||||
MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
if (Reg == ARM::LR) {
|
||||
// Special epilogue for vararg functions. See emitEpilogue
|
||||
if (isVarArg)
|
||||
continue;
|
||||
Reg = ARM::PC;
|
||||
PopMI->setDesc(get(ARM::tPOP_RET));
|
||||
MI = MBB.erase(MI);
|
||||
}
|
||||
PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
|
||||
}
|
||||
|
||||
// It's illegal to emit pop instruction without operands.
|
||||
if (PopMI->getNumOperands() > 0)
|
||||
MBB.insert(MI, PopMI);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstr *ARMInstrInfo::
|
||||
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
||||
const SmallVectorImpl<unsigned> &Ops, int FI) const {
|
||||
@ -752,31 +621,6 @@ foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARM::tMOVr:
|
||||
case ARM::tMOVlor2hir:
|
||||
case ARM::tMOVhir2lor:
|
||||
case ARM::tMOVhir2hir: {
|
||||
if (OpNum == 0) { // move -> store
|
||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||
bool isKill = MI->getOperand(1).isKill();
|
||||
if (RI.isPhysicalRegister(SrcReg) && !RI.isLowRegister(SrcReg))
|
||||
// tSpill cannot take a high register operand.
|
||||
break;
|
||||
NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
} else { // move -> load
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
if (RI.isPhysicalRegister(DstReg) && !RI.isLowRegister(DstReg))
|
||||
// tRestore cannot target a high register operand.
|
||||
break;
|
||||
bool isDead = MI->getOperand(0).isDead();
|
||||
NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
|
||||
.addReg(DstReg, RegState::Define | getDeadRegState(isDead))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARM::FCPYS: {
|
||||
unsigned Pred = MI->getOperand(2).getImm();
|
||||
unsigned PredReg = MI->getOperand(3).getReg();
|
||||
@ -816,7 +660,7 @@ foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
bool ARMBaseInstrInfo::
|
||||
canFoldMemoryOperand(const MachineInstr *MI,
|
||||
const SmallVectorImpl<unsigned> &Ops) const {
|
||||
if (Ops.size() != 1) return false;
|
||||
@ -857,9 +701,10 @@ canFoldMemoryOperand(const MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
|
||||
bool
|
||||
ARMBaseInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
|
||||
if (MBB.empty()) return false;
|
||||
|
||||
|
||||
switch (MBB.back().getOpcode()) {
|
||||
case ARM::BX_RET: // Return.
|
||||
case ARM::LDM_RET:
|
||||
@ -877,19 +722,19 @@ bool ARMInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
bool ARMBaseInstrInfo::
|
||||
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
|
||||
ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
|
||||
Cond[0].setImm(ARMCC::getOppositeCondition(CC));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::isPredicated(const MachineInstr *MI) const {
|
||||
bool ARMBaseInstrInfo::isPredicated(const MachineInstr *MI) const {
|
||||
int PIdx = MI->findFirstPredOperandIdx();
|
||||
return PIdx != -1 && MI->getOperand(PIdx).getImm() != ARMCC::AL;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
bool ARMBaseInstrInfo::
|
||||
PredicateInstruction(MachineInstr *MI,
|
||||
const SmallVectorImpl<MachineOperand> &Pred) const {
|
||||
unsigned Opc = MI->getOpcode();
|
||||
@ -910,7 +755,7 @@ PredicateInstruction(MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::
|
||||
bool ARMBaseInstrInfo::
|
||||
SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
const SmallVectorImpl<MachineOperand> &Pred2) const {
|
||||
if (Pred1.size() > 2 || Pred2.size() > 2)
|
||||
@ -937,7 +782,7 @@ SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
}
|
||||
}
|
||||
|
||||
bool ARMInstrInfo::DefinesPredicate(MachineInstr *MI,
|
||||
bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const {
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
if (!TID.getImplicitDefs() && !TID.hasOptionalDef())
|
||||
@ -966,7 +811,7 @@ static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
|
||||
|
||||
/// GetInstSize - Return the size of the specified MachineInstr.
|
||||
///
|
||||
unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
||||
unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
||||
const MachineBasicBlock &MBB = *MI->getParent();
|
||||
const MachineFunction *MF = MBB.getParent();
|
||||
const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
|
||||
@ -974,7 +819,7 @@ unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
||||
// Basic size info comes from the TSFlags field.
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
unsigned TSFlags = TID.TSFlags;
|
||||
|
||||
|
||||
switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
|
||||
default: {
|
||||
// If this machine instr is an inline asm, measure it.
|
||||
@ -1024,7 +869,7 @@ unsigned ARMInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
||||
// FIXME: If we know the size of the function is less than (1 << 16) *2
|
||||
// bytes, we can use 16-bit entries instead. Then there won't be an
|
||||
// alignment issue.
|
||||
return getNumJTEntries(JT, JTI) * 4 +
|
||||
return getNumJTEntries(JT, JTI) * 4 +
|
||||
(MI->getOpcode()==ARM::tBR_JTr ? 2 : 4);
|
||||
}
|
||||
default:
|
||||
|
@ -51,14 +51,14 @@ namespace ARMII {
|
||||
Size8Bytes = 2,
|
||||
Size4Bytes = 3,
|
||||
Size2Bytes = 4,
|
||||
|
||||
|
||||
// IndexMode - Unindex, pre-indexed, or post-indexed. Only valid for load
|
||||
// and store ops
|
||||
// and store ops
|
||||
IndexModeShift = 7,
|
||||
IndexModeMask = 3 << IndexModeShift,
|
||||
IndexModePre = 1,
|
||||
IndexModePost = 2,
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Misc flags.
|
||||
|
||||
@ -146,10 +146,12 @@ namespace ARMII {
|
||||
};
|
||||
}
|
||||
|
||||
class ARMInstrInfo : public TargetInstrInfoImpl {
|
||||
class ARMBaseInstrInfo : public TargetInstrInfoImpl {
|
||||
const ARMRegisterInfo RI;
|
||||
protected:
|
||||
// Can be only subclassed.
|
||||
explicit ARMBaseInstrInfo(const ARMSubtarget &STI);
|
||||
public:
|
||||
explicit ARMInstrInfo(const ARMSubtarget &STI);
|
||||
|
||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
/// such, whenever a client has an instance of instruction info, it should
|
||||
@ -157,17 +159,6 @@ public:
|
||||
///
|
||||
virtual const ARMRegisterInfo &getRegisterInfo() const { return RI; }
|
||||
|
||||
/// Return true if the instruction is a register to register move and return
|
||||
/// the source and dest operands and their sub-register indices by reference.
|
||||
virtual bool isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg, unsigned &DstReg,
|
||||
unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
|
||||
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, const MachineInstr *Orig) const;
|
||||
|
||||
@ -184,6 +175,54 @@ public:
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
virtual bool canFoldMemoryOperand(const MachineInstr *MI,
|
||||
const SmallVectorImpl<unsigned> &Ops) const;
|
||||
|
||||
virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
|
||||
virtual
|
||||
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
// Predication support.
|
||||
virtual bool isPredicated(const MachineInstr *MI) const;
|
||||
|
||||
ARMCC::CondCodes getPredicate(const MachineInstr *MI) const {
|
||||
int PIdx = MI->findFirstPredOperandIdx();
|
||||
return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm()
|
||||
: ARMCC::AL;
|
||||
}
|
||||
|
||||
virtual
|
||||
bool PredicateInstruction(MachineInstr *MI,
|
||||
const SmallVectorImpl<MachineOperand> &Pred) const;
|
||||
|
||||
virtual
|
||||
bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
const SmallVectorImpl<MachineOperand> &Pred2) const;
|
||||
|
||||
virtual bool DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const;
|
||||
|
||||
/// GetInstSize - Returns the size of the specified MachineInstr.
|
||||
///
|
||||
virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const;
|
||||
};
|
||||
|
||||
class ARMInstrInfo : public ARMBaseInstrInfo {
|
||||
public:
|
||||
explicit ARMInstrInfo(const ARMSubtarget &STI);
|
||||
|
||||
/// Return true if the instruction is a register to register move and return
|
||||
/// the source and dest operands and their sub-register indices by reference.
|
||||
virtual bool isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg, unsigned &DstReg,
|
||||
unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
|
||||
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
virtual bool copyRegToReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
@ -208,13 +247,7 @@ public:
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const;
|
||||
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const;
|
||||
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const;
|
||||
|
||||
|
||||
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr* MI,
|
||||
const SmallVectorImpl<unsigned> &Ops,
|
||||
@ -226,37 +259,6 @@ public:
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool canFoldMemoryOperand(const MachineInstr *MI,
|
||||
const SmallVectorImpl<unsigned> &Ops) const;
|
||||
|
||||
virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
|
||||
virtual
|
||||
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
// Predication support.
|
||||
virtual bool isPredicated(const MachineInstr *MI) const;
|
||||
|
||||
ARMCC::CondCodes getPredicate(const MachineInstr *MI) const {
|
||||
int PIdx = MI->findFirstPredOperandIdx();
|
||||
return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm()
|
||||
: ARMCC::AL;
|
||||
}
|
||||
|
||||
virtual
|
||||
bool PredicateInstruction(MachineInstr *MI,
|
||||
const SmallVectorImpl<MachineOperand> &Pred) const;
|
||||
|
||||
virtual
|
||||
bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
const SmallVectorImpl<MachineOperand> &Pred2) const;
|
||||
|
||||
virtual bool DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const;
|
||||
|
||||
/// GetInstSize - Returns the size of the specified MachineInstr.
|
||||
///
|
||||
virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ const char *const llvm::arm_asm_table[] = {
|
||||
0,0
|
||||
};
|
||||
|
||||
ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM):
|
||||
ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM):
|
||||
ARMTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
|
||||
Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
||||
|
||||
@ -55,7 +55,7 @@ ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM):
|
||||
SupportsDebugInformation = true;
|
||||
}
|
||||
|
||||
ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMTargetMachine &TM):
|
||||
ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM):
|
||||
ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) {
|
||||
Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace llvm {
|
||||
|
||||
template <class BaseTAI>
|
||||
struct ARMTargetAsmInfo : public BaseTAI {
|
||||
explicit ARMTargetAsmInfo(const ARMTargetMachine &TM) : BaseTAI(TM) {
|
||||
explicit ARMTargetAsmInfo(const ARMBaseTargetMachine &TM) : BaseTAI(TM) {
|
||||
BaseTAI::AsmTransCBE = arm_asm_table;
|
||||
|
||||
BaseTAI::AlignmentIsInBytes = false;
|
||||
@ -51,11 +51,11 @@ namespace llvm {
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);
|
||||
|
||||
struct ARMDarwinTargetAsmInfo : public ARMTargetAsmInfo<DarwinTargetAsmInfo> {
|
||||
explicit ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM);
|
||||
explicit ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM);
|
||||
};
|
||||
|
||||
struct ARMELFTargetAsmInfo : public ARMTargetAsmInfo<ELFTargetAsmInfo> {
|
||||
explicit ARMELFTargetAsmInfo(const ARMTargetMachine &TM);
|
||||
explicit ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -43,7 +43,7 @@ static RegisterTarget<ThumbTargetMachine> Y("thumb", "Thumb");
|
||||
extern "C" void LLVMInitializeARMTarget() { }
|
||||
|
||||
// No assembler printer by default
|
||||
ARMTargetMachine::AsmPrinterCtorFn ARMTargetMachine::AsmPrinterCtor = 0;
|
||||
ARMBaseTargetMachine::AsmPrinterCtorFn ARMBaseTargetMachine::AsmPrinterCtor = 0;
|
||||
|
||||
/// ThumbTargetMachine - Create an Thumb architecture model.
|
||||
///
|
||||
@ -74,34 +74,36 @@ unsigned ThumbTargetMachine::getModuleMatchQuality(const Module &M) {
|
||||
return getJITMatchQuality()/2;
|
||||
}
|
||||
|
||||
ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
|
||||
: ARMTargetMachine(M, FS, true) {
|
||||
}
|
||||
|
||||
/// TargetMachine ctor - Create an ARM architecture model.
|
||||
///
|
||||
ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS,
|
||||
bool isThumb)
|
||||
ARMBaseTargetMachine::ARMBaseTargetMachine(const Module &M,
|
||||
const std::string &FS,
|
||||
bool isThumb)
|
||||
: Subtarget(M, FS, isThumb),
|
||||
DataLayout(Subtarget.isAPCS_ABI() ?
|
||||
// APCS ABI
|
||||
(isThumb ?
|
||||
std::string("e-p:32:32-f64:32:32-i64:32:32-"
|
||||
"i16:16:32-i8:8:32-i1:8:32-a:0:32") :
|
||||
std::string("e-p:32:32-f64:32:32-i64:32:32")) :
|
||||
// AAPCS ABI
|
||||
(isThumb ?
|
||||
std::string("e-p:32:32-f64:64:64-i64:64:64-"
|
||||
"i16:16:32-i8:8:32-i1:8:32-a:0:32") :
|
||||
std::string("e-p:32:32-f64:64:64-i64:64:64"))),
|
||||
InstrInfo(Subtarget),
|
||||
FrameInfo(Subtarget),
|
||||
JITInfo(),
|
||||
TLInfo(*this),
|
||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||
DefRelocModel = getRelocationModel();
|
||||
}
|
||||
|
||||
ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
|
||||
: ARMBaseTargetMachine(M, FS, false), InstrInfo(Subtarget),
|
||||
DataLayout(Subtarget.isAPCS_ABI() ?
|
||||
std::string("e-p:32:32-f64:32:32-i64:32:32") :
|
||||
std::string("e-p:32:32-f64:64:64-i64:64:64")),
|
||||
TLInfo(*this) {
|
||||
}
|
||||
|
||||
ThumbTargetMachine::ThumbTargetMachine(const Module &M, const std::string &FS)
|
||||
: ARMBaseTargetMachine(M, FS, true), InstrInfo(Subtarget),
|
||||
DataLayout(Subtarget.isAPCS_ABI() ?
|
||||
std::string("e-p:32:32-f64:32:32-i64:32:32-"
|
||||
"i16:16:32-i8:8:32-i1:8:32-a:0:32") :
|
||||
std::string("e-p:32:32-f64:64:64-i64:64:64-"
|
||||
"i16:16:32-i8:8:32-i1:8:32-a:0:32")),
|
||||
TLInfo(*this) {
|
||||
}
|
||||
|
||||
unsigned ARMTargetMachine::getJITMatchQuality() {
|
||||
#if defined(__arm__)
|
||||
return 10;
|
||||
@ -129,7 +131,7 @@ unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
|
||||
}
|
||||
|
||||
|
||||
const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
|
||||
const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
|
||||
switch (Subtarget.TargetType) {
|
||||
case ARMSubtarget::isDarwin:
|
||||
return new ARMDarwinTargetAsmInfo(*this);
|
||||
@ -142,22 +144,22 @@ const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
|
||||
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
bool ARMTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
PM.add(createARMISelDag(*this));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addPreRegAlloc(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
// FIXME: temporarily disabling load / store optimization pass for Thumb mode.
|
||||
if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
|
||||
PM.add(createARMLoadStoreOptimizationPass(true));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
// FIXME: temporarily disabling load / store optimization pass for Thumb mode.
|
||||
if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
|
||||
PM.add(createARMLoadStoreOptimizationPass());
|
||||
@ -170,10 +172,10 @@ bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool Verbose,
|
||||
raw_ostream &Out) {
|
||||
bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool Verbose,
|
||||
raw_ostream &Out) {
|
||||
// Output assembly language.
|
||||
assert(AsmPrinterCtor && "AsmPrinter was not linked in");
|
||||
if (AsmPrinterCtor)
|
||||
@ -183,10 +185,10 @@ bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
|
||||
}
|
||||
|
||||
|
||||
bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
MachineCodeEmitter &MCE) {
|
||||
bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
MachineCodeEmitter &MCE) {
|
||||
// FIXME: Move this to TargetJITInfo!
|
||||
if (DefRelocModel == Reloc::Default)
|
||||
setRelocationModel(Reloc::Static);
|
||||
@ -202,10 +204,10 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
JITCodeEmitter &JCE) {
|
||||
bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
JITCodeEmitter &JCE) {
|
||||
// FIXME: Move this to TargetJITInfo!
|
||||
if (DefRelocModel == Reloc::Default)
|
||||
setRelocationModel(Reloc::Static);
|
||||
@ -221,10 +223,10 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
MachineCodeEmitter &MCE) {
|
||||
bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
MachineCodeEmitter &MCE) {
|
||||
// Machine code emitter pass for ARM.
|
||||
PM.add(createARMCodeEmitterPass(*this, MCE));
|
||||
if (DumpAsm) {
|
||||
@ -236,10 +238,10 @@ bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
JITCodeEmitter &JCE) {
|
||||
bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool DumpAsm,
|
||||
JITCodeEmitter &JCE) {
|
||||
// Machine code emitter pass for ARM.
|
||||
PM.add(createARMJITCodeEmitterPass(*this, JCE));
|
||||
if (DumpAsm) {
|
||||
|
@ -22,18 +22,19 @@
|
||||
#include "ARMJITInfo.h"
|
||||
#include "ARMSubtarget.h"
|
||||
#include "ARMISelLowering.h"
|
||||
#include "ThumbInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
|
||||
class ARMTargetMachine : public LLVMTargetMachine {
|
||||
class ARMBaseTargetMachine : public LLVMTargetMachine {
|
||||
protected:
|
||||
ARMSubtarget Subtarget;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
ARMInstrInfo InstrInfo;
|
||||
|
||||
private:
|
||||
ARMFrameInfo FrameInfo;
|
||||
ARMJITInfo JITInfo;
|
||||
ARMTargetLowering TLInfo;
|
||||
InstrItineraryData InstrItins;
|
||||
Reloc::Model DefRelocModel; // Reloc model before it's overridden.
|
||||
|
||||
@ -41,26 +42,18 @@ protected:
|
||||
// To avoid having target depend on the asmprinter stuff libraries, asmprinter
|
||||
// set this functions to ctor pointer at startup time if they are linked in.
|
||||
typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
|
||||
ARMTargetMachine &tm,
|
||||
ARMBaseTargetMachine &tm,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool verbose);
|
||||
static AsmPrinterCtorFn AsmPrinterCtor;
|
||||
|
||||
public:
|
||||
ARMTargetMachine(const Module &M, const std::string &FS, bool isThumb = false);
|
||||
ARMBaseTargetMachine(const Module &M, const std::string &FS, bool isThumb);
|
||||
|
||||
virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||
virtual const ARMFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||
virtual ARMJITInfo *getJITInfo() { return &JITInfo; }
|
||||
virtual const ARMRegisterInfo *getRegisterInfo() const {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||
virtual ARMTargetLowering *getTargetLowering() const {
|
||||
return const_cast<ARMTargetLowering*>(&TLInfo);
|
||||
}
|
||||
virtual const InstrItineraryData getInstrItineraryData() const {
|
||||
virtual const InstrItineraryData getInstrItineraryData() const {
|
||||
return InstrItins;
|
||||
}
|
||||
|
||||
@ -94,12 +87,50 @@ public:
|
||||
JITCodeEmitter &MCE);
|
||||
};
|
||||
|
||||
/// ARMTargetMachine - ARM target machine.
|
||||
///
|
||||
class ARMTargetMachine : public ARMBaseTargetMachine {
|
||||
ARMInstrInfo InstrInfo;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
ARMTargetLowering TLInfo;
|
||||
public:
|
||||
ARMTargetMachine(const Module &M, const std::string &FS);
|
||||
|
||||
virtual const ARMRegisterInfo *getRegisterInfo() const {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
|
||||
virtual ARMTargetLowering *getTargetLowering() const {
|
||||
return const_cast<ARMTargetLowering*>(&TLInfo);
|
||||
}
|
||||
|
||||
virtual const ARMInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
|
||||
static unsigned getJITMatchQuality();
|
||||
static unsigned getModuleMatchQuality(const Module &M);
|
||||
};
|
||||
|
||||
/// ThumbTargetMachine - Thumb target machine.
|
||||
///
|
||||
class ThumbTargetMachine : public ARMTargetMachine {
|
||||
class ThumbTargetMachine : public ARMBaseTargetMachine {
|
||||
ThumbInstrInfo InstrInfo;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
ARMTargetLowering TLInfo;
|
||||
public:
|
||||
ThumbTargetMachine(const Module &M, const std::string &FS);
|
||||
|
||||
virtual const ARMRegisterInfo *getRegisterInfo() const {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
|
||||
virtual ARMTargetLowering *getTargetLowering() const {
|
||||
return const_cast<ARMTargetLowering*>(&TLInfo);
|
||||
}
|
||||
|
||||
virtual const ThumbInstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
|
||||
static unsigned getJITMatchQuality();
|
||||
static unsigned getModuleMatchQuality(const Module &M);
|
||||
};
|
||||
|
@ -1138,7 +1138,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
|
||||
/// regardless of whether the function is in SSA form.
|
||||
///
|
||||
FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
|
||||
ARMTargetMachine &tm,
|
||||
ARMBaseTargetMachine &tm,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool verbose) {
|
||||
return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
|
||||
@ -1147,7 +1147,7 @@ FunctionPass *llvm::createARMCodePrinterPass(raw_ostream &o,
|
||||
namespace {
|
||||
static struct Register {
|
||||
Register() {
|
||||
ARMTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
|
||||
ARMBaseTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
|
||||
}
|
||||
} Registrator;
|
||||
}
|
||||
|
282
lib/Target/ARM/ThumbInstrInfo.cpp
Normal file
282
lib/Target/ARM/ThumbInstrInfo.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
//===- ThumbInstrInfo.cpp - Thumb Instruction Information --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the Thumb implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMInstrInfo.h"
|
||||
#include "ARM.h"
|
||||
#include "ARMGenInstrInfo.inc"
|
||||
#include "ARMMachineFunctionInfo.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "ThumbInstrInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
ThumbInstrInfo::ThumbInstrInfo(const ARMSubtarget &STI)
|
||||
: ARMBaseInstrInfo(STI) {
|
||||
}
|
||||
|
||||
bool ThumbInstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg, unsigned &DstReg,
|
||||
unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
|
||||
SrcSubIdx = DstSubIdx = 0; // No sub-registers.
|
||||
|
||||
unsigned oc = MI.getOpcode();
|
||||
switch (oc) {
|
||||
default:
|
||||
return false;
|
||||
// FIXME: Thumb2
|
||||
case ARM::tMOVr:
|
||||
case ARM::tMOVhir2lor:
|
||||
case ARM::tMOVlor2hir:
|
||||
case ARM::tMOVhir2hir:
|
||||
assert(MI.getDesc().getNumOperands() >= 2 &&
|
||||
MI.getOperand(0).isReg() &&
|
||||
MI.getOperand(1).isReg() &&
|
||||
"Invalid Thumb MOV instruction");
|
||||
SrcReg = MI.getOperand(1).getReg();
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ThumbInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
switch (MI->getOpcode()) {
|
||||
default: break;
|
||||
// FIXME: Thumb2
|
||||
case ARM::tRestore:
|
||||
if (MI->getOperand(1).isFI() &&
|
||||
MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned ThumbInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
switch (MI->getOpcode()) {
|
||||
default: break;
|
||||
// FIXME: Thumb2
|
||||
case ARM::tSpill:
|
||||
if (MI->getOperand(1).isFI() &&
|
||||
MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ThumbInstrInfo::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();
|
||||
|
||||
// FIXME: Thumb2
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVhir2hir), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVlor2hir), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
} else if (DestRC == ARM::tGPRRegisterClass) {
|
||||
if (SrcRC == ARM::GPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVhir2lor), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
} else if (SrcRC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg).addReg(SrcReg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ThumbInstrInfo::
|
||||
storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned SrcReg, bool isKill, int FI,
|
||||
const TargetRegisterClass *RC) const {
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
|
||||
|
||||
// FIXME: Thumb2
|
||||
if (RC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tSpill))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ThumbInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
|
||||
bool isKill,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const{
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
unsigned Opc = 0;
|
||||
|
||||
// FIXME: Thumb2. Is GPRRegClass here correct?
|
||||
assert(RC == ARM::GPRRegisterClass && "Unknown regclass!");
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
Opc = Addr[0].isFI() ? ARM::tSpill : ARM::tSTR;
|
||||
}
|
||||
|
||||
MachineInstrBuilder MIB =
|
||||
BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
|
||||
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
|
||||
MIB.addOperand(Addr[i]);
|
||||
NewMIs.push_back(MIB);
|
||||
return;
|
||||
}
|
||||
|
||||
void ThumbInstrInfo::
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FI,
|
||||
const TargetRegisterClass *RC) const {
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
||||
|
||||
// FIXME: Thumb2
|
||||
assert(RC == ARM::tGPRRegisterClass && "Unknown regclass!");
|
||||
|
||||
if (RC == ARM::tGPRRegisterClass) {
|
||||
BuildMI(MBB, I, DL, get(ARM::tRestore), DestReg)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ThumbInstrInfo::
|
||||
loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const {
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
unsigned Opc = 0;
|
||||
|
||||
// FIXME: Thumb2. Is GPRRegClass ok here?
|
||||
if (RC == ARM::GPRRegisterClass) {
|
||||
Opc = Addr[0].isFI() ? ARM::tRestore : ARM::tLDR;
|
||||
}
|
||||
|
||||
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
|
||||
for (unsigned i = 0, e = Addr.size(); i != e; ++i)
|
||||
MIB.addOperand(Addr[i]);
|
||||
NewMIs.push_back(MIB);
|
||||
return;
|
||||
}
|
||||
|
||||
bool ThumbInstrInfo::
|
||||
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
if (CSI.empty())
|
||||
return false;
|
||||
|
||||
DebugLoc DL = DebugLoc::getUnknownLoc();
|
||||
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
||||
|
||||
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
// Add the callee-saved register as live-in. It's killed at the spill.
|
||||
MBB.addLiveIn(Reg);
|
||||
MIB.addReg(Reg, RegState::Kill);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThumbInstrInfo::
|
||||
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (CSI.empty())
|
||||
return false;
|
||||
|
||||
bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
|
||||
MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
if (Reg == ARM::LR) {
|
||||
// Special epilogue for vararg functions. See emitEpilogue
|
||||
if (isVarArg)
|
||||
continue;
|
||||
Reg = ARM::PC;
|
||||
PopMI->setDesc(get(ARM::tPOP_RET));
|
||||
MI = MBB.erase(MI);
|
||||
}
|
||||
PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
|
||||
}
|
||||
|
||||
// It's illegal to emit pop instruction without operands.
|
||||
if (PopMI->getNumOperands() > 0)
|
||||
MBB.insert(MI, PopMI);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstr *ThumbInstrInfo::
|
||||
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
|
||||
const SmallVectorImpl<unsigned> &Ops, int FI) const {
|
||||
if (Ops.size() != 1) return NULL;
|
||||
const ARMRegisterInfo &RI = getRegisterInfo();
|
||||
|
||||
unsigned OpNum = Ops[0];
|
||||
unsigned Opc = MI->getOpcode();
|
||||
MachineInstr *NewMI = NULL;
|
||||
switch (Opc) {
|
||||
default: break;
|
||||
case ARM::tMOVr:
|
||||
case ARM::tMOVlor2hir:
|
||||
case ARM::tMOVhir2lor:
|
||||
case ARM::tMOVhir2hir: {
|
||||
if (OpNum == 0) { // move -> store
|
||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||
bool isKill = MI->getOperand(1).isKill();
|
||||
if (RI.isPhysicalRegister(SrcReg) && !RI.isLowRegister(SrcReg))
|
||||
// tSpill cannot take a high register operand.
|
||||
break;
|
||||
NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tSpill))
|
||||
.addReg(SrcReg, getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
} else { // move -> load
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
if (RI.isPhysicalRegister(DstReg) && !RI.isLowRegister(DstReg))
|
||||
// tRestore cannot target a high register operand.
|
||||
break;
|
||||
bool isDead = MI->getOperand(0).isDead();
|
||||
NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::tRestore))
|
||||
.addReg(DstReg, RegState::Define | getDeadRegState(isDead))
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NewMI;
|
||||
}
|
85
lib/Target/ARM/ThumbInstrInfo.h
Normal file
85
lib/Target/ARM/ThumbInstrInfo.h
Normal file
@ -0,0 +1,85 @@
|
||||
//===- ThumbInstrInfo.h - Thumb Instruction Information ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the ARM implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef THUMBINSTRUCTIONINFO_H
|
||||
#define THUMBINSTRUCTIONINFO_H
|
||||
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "ARMRegisterInfo.h"
|
||||
#include "ARM.h"
|
||||
#include "ARMInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class ARMSubtarget;
|
||||
|
||||
class ThumbInstrInfo : public ARMBaseInstrInfo {
|
||||
public:
|
||||
explicit ThumbInstrInfo(const ARMSubtarget &STI);
|
||||
|
||||
/// Return true if the instruction is a register to register move and return
|
||||
/// the source and dest operands and their sub-register indices by reference.
|
||||
virtual bool isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg, unsigned &DstReg,
|
||||
unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
|
||||
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
virtual bool copyRegToReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC) const;
|
||||
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const;
|
||||
|
||||
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const;
|
||||
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const;
|
||||
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const;
|
||||
|
||||
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr* MI,
|
||||
const SmallVectorImpl<unsigned> &Ops,
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr* MI,
|
||||
const SmallVectorImpl<unsigned> &Ops,
|
||||
int FrameIndex) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // THUMBINSTRUCTIONINFO_H
|
Loading…
Reference in New Issue
Block a user