From 391f228e7e00f62b79ad483b801f5f58f046b7ea Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 11 Nov 2010 19:26:03 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMBaseInstrInfo.cpp | 61 ++++++++++++++++++++++---- lib/Target/ARM/ARMBaseInstrInfo.h | 5 +++ lib/Target/ARM/ARMBaseRegisterInfo.cpp | 42 +++++++++++------- lib/Target/ARM/ARMBaseRegisterInfo.h | 14 ++++++ 4 files changed, 97 insertions(+), 25 deletions(-) diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index b023379e7ba..36d8a079708 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -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 &CSI, + const TargetRegisterInfo *TRI) const { + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + 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:: diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index c11f02ccb10..065e04af5e0 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -211,6 +211,11 @@ public: const std::vector &CSI, const TargetRegisterInfo *TRI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + // Branch analysis. virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index f72713325ad..9969de94e54 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -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 || diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 4907f01f448..2bf7a91c910 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -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;