Change the prologue and epilogue to use push/pop for the low ARM registers.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118823 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher 2010-11-11 19:26:03 +00:00
parent f3b8c76599
commit 391f228e7e
4 changed files with 97 additions and 25 deletions

View File

@ -208,8 +208,10 @@ ARMBaseInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get(ARM::tPUSH));
AddDefaultPred(MIB);
for (unsigned i = CSI.size(); i != 0; --i) {
unsigned Reg = CSI[i-1].getReg();
bool isKill = true;
// Add the callee-saved register as live-in unless it's LR and
@ -225,15 +227,58 @@ ARMBaseInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
if (isKill)
MBB.addLiveIn(Reg);
// Insert the spill to the stack frame. The register is killed at the spill
//
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
storeRegToStackSlot(MBB, MI, Reg, isKill,
CSI[i].getFrameIdx(), RC, TRI);
if (!isARMPushRegister(Reg)) {
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
storeRegToStackSlot(MBB, MI, Reg, isKill,
CSI[i-1].getFrameIdx(), RC, TRI);
} else
MIB.addReg(Reg, getKillRegState(isKill));
}
return true;
}
bool
ARMBaseInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
MachineFunction &MF = *MBB.getParent();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
if (CSI.empty())
return false;
bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
DebugLoc DL = MI->getDebugLoc();
MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::tPOP));
AddDefaultPred(MIB);
bool NumRegs = false;
for (unsigned i = CSI.size(); i != 0; --i) {
unsigned Reg = CSI[i-1].getReg();
if (Reg == ARM::LR && !isVarArg) {
Reg = ARM::PC;
(*MIB).setDesc(get(ARM::tPOP_RET));
MI = MBB.erase(MI);
}
if (!isARMPushRegister(Reg)) {
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
loadRegFromStackSlot(MBB, MI, Reg, CSI[i-1].getFrameIdx(), RC, TRI);
} else
MIB.addReg(Reg, getDefRegState(true));
NumRegs = true;
}
// It's illegal to emit pop instruction without operands.
if (NumRegs)
MBB.insert(MI, &*MIB);
else
MF.DeleteMachineInstr(MIB);
return true;
}
// Branch analysis.
bool
ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
@ -2046,7 +2091,7 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
case ARM::VLDMQ:
case ARM::VSTMQ:
return 2;
}
}
}
bool ARMBaseInstrInfo::

View File

@ -211,6 +211,11 @@ public:
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
// Branch analysis.
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,

View File

@ -1667,9 +1667,9 @@ static void movePastCSLoadStoreOps(MachineBasicBlock &MBB,
int Opc1, int Opc2, unsigned Area,
const ARMSubtarget &STI) {
while (MBBI != MBB.end() &&
((MBBI->getOpcode() == Opc1) || (MBBI->getOpcode() == Opc2)) &&
MBBI->getOperand(1).isFI()) {
if (Area != 0) {
((MBBI->getOpcode() == Opc1) || (MBBI->getOpcode() == Opc2))) {
if (Area == 3) {
bool Done = false;
unsigned Category = 0;
switch (MBBI->getOperand(0).getReg()) {
@ -1759,9 +1759,7 @@ emitPrologue(MachineFunction &MF) const {
}
}
// Build the new SUBri to adjust SP for integer callee-save spill area 1.
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS1Size);
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 1, STI);
movePastCSLoadStoreOps(MBB, MBBI, ARM::tPUSH, 0, 1, STI);
// Set FP to point to the stack slot that contains the previous FP.
// For Darwin, FP is R7, which has now been stored in spill area 1.
@ -1781,7 +1779,7 @@ emitPrologue(MachineFunction &MF) const {
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS2Size);
// Build the new SUBri to adjust SP for FP callee-save spill area.
movePastCSLoadStoreOps(MBB, MBBI, ARM::STRi12, ARM::t2STRi12, 2, STI);
movePastCSLoadStoreOps(MBB, MBBI, ARM::tPUSH, 0, 2, STI);
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize);
// Determine starting offsets of spill areas.
@ -1875,11 +1873,25 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
static bool isCSRestore(MachineInstr *MI,
const ARMBaseInstrInfo &TII,
const unsigned *CSRegs) {
return ((MI->getOpcode() == (int)ARM::VLDRD ||
MI->getOpcode() == (int)ARM::LDRi12 ||
MI->getOpcode() == (int)ARM::t2LDRi12) &&
MI->getOperand(1).isFI() &&
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs));
// Integer spill area is handled with pop.
if (MI->getOpcode() == ARM::tRestore ||
MI->getOpcode() == ARM::tPOP) {
// The first two operands are predicates. The last two are
// imp-def and imp-use of SP. Check everything in between.
for (int i = 2, e = MI->getNumOperands() - 2; i != e; ++i)
if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs))
return false;
return true;
}
// Or if this is a fp reg spill.
if (MI->getOpcode() == (int)ARM::VLDRD &&
MI->getOperand(1).isFI() &&
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs))
return true;
return false;
}
void ARMBaseRegisterInfo::
@ -1945,12 +1957,8 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize());
// Move SP to start of integer callee save spill area 1.
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 2, STI);
movePastCSLoadStoreOps(MBB, MBBI, ARM::tPOP, 0, 2, STI);
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea2Size());
// Move SP to SP upon entry to the function.
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 1, STI);
emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size());
}
if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND ||

View File

@ -44,6 +44,20 @@ static inline bool isARMLowRegister(unsigned Reg) {
}
}
/// isARMPushRegister - Returns true if the register is a low register (r0-r7)
/// or a stack/pc register that we should push/pop.
static inline bool isARMPushRegister(unsigned Reg) {
using namespace ARM;
switch (Reg) {
case R0: case R1: case R2: case R3:
case R4: case R5: case R6: case R7:
case LR: case SP: case PC:
return true;
default:
return false;
}
}
class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
protected:
const ARMBaseInstrInfo &TII;