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

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,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:

View File

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

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,
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) {

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

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