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:
Anton Korobeynikov 2009-06-26 21:28:53 +00:00
parent c4233af200
commit d49ea77cbc
12 changed files with 596 additions and 349 deletions

View File

@ -20,7 +20,7 @@
namespace llvm {
class ARMTargetMachine;
class ARMBaseTargetMachine;
class FunctionPass;
class MachineCodeEmitter;
class JITCodeEmitter;
@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,19 +128,12 @@ 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,
void ARMBaseInstrInfo::reMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg,
const MachineInstr *Orig) const {
@ -198,7 +182,7 @@ static unsigned getUnindexedOpcode(unsigned Opc) {
}
MachineInstr *
ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
MachineBasicBlock::iterator &MBBI,
LiveVariables *LV) const {
if (!EnableARM3Addr)
@ -349,7 +333,8 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
}
// Branch analysis.
bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
bool
ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const {
@ -424,7 +409,7 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
}
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;
@ -452,7 +437,7 @@ unsigned ARMInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
}
unsigned
ARMInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const {
// FIXME this should probably have a DebugLoc argument
@ -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)
@ -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;
@ -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,7 +701,8 @@ 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()) {
@ -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();

View File

@ -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,48 +175,6 @@ public:
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) 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,
int FrameIndex) const;
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
MachineInstr* LoadMI) const {
return 0;
}
virtual bool canFoldMemoryOperand(const MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops) const;
@ -259,6 +208,59 @@ public:
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,
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 MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
int FrameIndex) const;
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
MachineInstr* LoadMI) const {
return 0;
}
};
}
#endif

View File

@ -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>();

View File

@ -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

View File

@ -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,
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,13 +144,13 @@ const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
// Pass Pipeline Configuration
bool ARMTargetMachine::addInstSelector(PassManagerBase &PM,
bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
PM.add(createARMISelDag(*this));
return false;
}
bool ARMTargetMachine::addPreRegAlloc(PassManagerBase &PM,
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())
@ -156,7 +158,7 @@ bool ARMTargetMachine::addPreRegAlloc(PassManagerBase &PM,
return true;
}
bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
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())
@ -170,7 +172,7 @@ bool ARMTargetMachine::addPreEmitPass(PassManagerBase &PM,
return true;
}
bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
bool ARMBaseTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose,
raw_ostream &Out) {
@ -183,7 +185,7 @@ bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
}
bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm,
MachineCodeEmitter &MCE) {
@ -202,7 +204,7 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
return false;
}
bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm,
JITCodeEmitter &JCE) {
@ -221,7 +223,7 @@ bool ARMTargetMachine::addCodeEmitter(PassManagerBase &PM,
return false;
}
bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm,
MachineCodeEmitter &MCE) {
@ -236,7 +238,7 @@ bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
return false;
}
bool ARMTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm,
JITCodeEmitter &JCE) {

View File

@ -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,25 +42,17 @@ 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 {
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);
};

View File

@ -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;
}

View 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;
}

View 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