diff options
author | Eric Christopher <echristo@apple.com> | 2010-11-18 19:40:05 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2010-11-18 19:40:05 +0000 |
commit | 8b3ca6216d62bf3f729c2e122dcfeb7c4d7500dc (patch) | |
tree | 262f781c67f1e51596bb314659ad97093d142d97 /lib/Target/ARM | |
parent | 9fe010ecf885b82ca16c3f1e3caf72b9823377f3 (diff) |
Rewrite stack callee saved spills and restores to use push/pop instructions.
Remove movePastCSLoadStoreOps and associated code for simple pointer
increments. Update routines that depended upon other opcodes for save/restore.
Adjust all testcases accordingly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119725 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 124 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.h | 15 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.h | 39 | ||||
-rw-r--r-- | lib/Target/ARM/ARMFrameInfo.cpp | 97 |
4 files changed, 189 insertions, 86 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 94147eb31e..cb9c11295b 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -197,26 +197,29 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, return NewMIs[0]; } -bool -ARMBaseInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - +void +ARMBaseInstrInfo::emitPushInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, unsigned Opc, + bool(*Func)(unsigned, bool)) const { + MachineFunction &MF = *MBB.getParent(); DebugLoc DL; if (MI != MBB.end()) DL = MI->getDebugLoc(); - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - bool isKill = true; - + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc)); + MIB.addReg(ARM::SP, getDefRegState(true)); + MIB.addReg(ARM::SP); + AddDefaultPred(MIB); + bool NumRegs = false; + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (!(Func)(Reg, Subtarget.isTargetDarwin())) continue; + // Add the callee-saved register as live-in unless it's LR and // @llvm.returnaddress is called. If LR is returned for @llvm.returnaddress // then it's already added to the function and entry block live-in sets. + bool isKill = true; if (Reg == ARM::LR) { - MachineFunction &MF = *MBB.getParent(); if (MF.getFrameInfo()->isReturnAddressTaken() && MF.getRegInfo().isLiveIn(Reg)) isKill = false; @@ -224,16 +227,99 @@ ARMBaseInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, if (isKill) MBB.addLiveIn(Reg); + + NumRegs = true; + MIB.addReg(Reg, getKillRegState(isKill)); + } + + // It's illegal to emit push instruction without operands. + if (NumRegs) + MBB.insert(MI, &*MIB); + else + MF.DeleteMachineInstr(MIB); +} + +bool +ARMBaseInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + DebugLoc DL = MI->getDebugLoc(); + + unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; + unsigned FltOpc = ARM::VSTMDDB_UPD; + emitPushInst(MBB, MI, CSI, PushOpc, &isARMArea1Register); + emitPushInst(MBB, MI, CSI, PushOpc, &isARMArea2Register); + emitPushInst(MBB, MI, CSI, FltOpc, &isARMArea3Register); + + return true; +} + +void +ARMBaseInstrInfo::emitPopInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, unsigned Opc, + bool isVarArg, bool(*Func)(unsigned, bool)) const { + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + DebugLoc DL = MI->getDebugLoc(); + + MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc)); + MIB.addReg(ARM::SP, getDefRegState(true)); + MIB.addReg(ARM::SP); + AddDefaultPred(MIB); + bool NumRegs = false; + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (!(Func)(Reg, Subtarget.isTargetDarwin())) continue; + + if (Reg == ARM::LR && !isVarArg) { + Reg = ARM::PC; + unsigned Opc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET; + (*MIB).setDesc(get(Opc)); + MI = MBB.erase(MI); + } - // 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); + MIB.addReg(Reg, RegState::Define); + NumRegs = true; } + + // It's illegal to emit pop instruction without operands. + if (NumRegs) + MBB.insert(MI, &*MIB); + else + MF.DeleteMachineInstr(MIB); +} + +bool +ARMBaseInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); + bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; + DebugLoc DL = MI->getDebugLoc(); + + unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; + unsigned FltOpc = ARM::VLDMDIA_UPD; + emitPopInst(MBB, MI, CSI, FltOpc, isVarArg, &isARMArea3Register); + emitPopInst(MBB, MI, CSI, PopOpc, isVarArg, &isARMArea2Register); + emitPopInst(MBB, MI, CSI, PopOpc, isVarArg, &isARMArea1Register); + return true; } + // Branch analysis. bool ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, @@ -2195,7 +2281,7 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, case ARM::VSTMQIA: case ARM::VSTMQDB: return 2; - } + } } bool ARMBaseInstrInfo:: diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index cbcc428b71..5e7156c9ce 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -211,6 +211,21 @@ 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; + +private: + void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, unsigned Opc, + bool isVarArg, bool(*Func)(unsigned, bool)) const; + void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, unsigned Opc, + bool(*Func)(unsigned, bool)) const; + + +public: // Branch analysis. virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 25792c70c3..5cb080804b 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -44,6 +44,45 @@ static inline bool isARMLowRegister(unsigned Reg) { } } +/// isARMArea1Register - Returns true if the register is a low register (r0-r7) +/// or a stack/pc register that we should push/pop. +static inline bool isARMArea1Register(unsigned Reg, bool isDarwin) { + 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; + case R8: case R9: case R10: case R11: + // For darwin we want r7 and lr to be next to each other. + return !isDarwin; + default: + return false; + } +} + +static inline bool isARMArea2Register(unsigned Reg, bool isDarwin) { + using namespace ARM; + switch (Reg) { + case R8: case R9: case R10: case R11: + // Darwin has this second area. + return isDarwin; + default: + return false; + } +} + +static inline bool isARMArea3Register(unsigned Reg, bool isDarwin) { + using namespace ARM; + switch (Reg) { + case D15: case D14: case D13: case D12: + case D11: case D10: case D9: case D8: + return true; + default: + return false; + } +} + class ARMBaseRegisterInfo : public ARMGenRegisterInfo { protected: const ARMBaseInstrInfo &TII; diff --git a/lib/Target/ARM/ARMFrameInfo.cpp b/lib/Target/ARM/ARMFrameInfo.cpp index 499111af06..3417ae2659 100644 --- a/lib/Target/ARM/ARMFrameInfo.cpp +++ b/lib/Target/ARM/ARMFrameInfo.cpp @@ -20,43 +20,6 @@ using namespace llvm; -/// Move iterator past the next bunch of callee save load / store ops for -/// the particular spill area (1: integer area 1, 2: integer area 2, -/// 3: fp area, 0: don't care). -static void movePastCSLoadStoreOps(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - 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) { - bool Done = false; - unsigned Category = 0; - switch (MBBI->getOperand(0).getReg()) { - case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7: - case ARM::LR: - Category = 1; - break; - case ARM::R8: case ARM::R9: case ARM::R10: case ARM::R11: - Category = STI.isTargetDarwin() ? 2 : 1; - break; - case ARM::D8: case ARM::D9: case ARM::D10: case ARM::D11: - case ARM::D12: case ARM::D13: case ARM::D14: case ARM::D15: - Category = 3; - break; - default: - Done = true; - break; - } - if (Done || Category != Area) - break; - } - - ++MBBI; - } -} - static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { for (unsigned i = 0; CSRegs[i]; ++i) if (Reg == CSRegs[i]) @@ -67,11 +30,21 @@ 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::LDMIA_RET || + MI->getOpcode() == ARM::t2LDMIA_RET || + MI->getOpcode() == ARM::LDMIA_UPD || + MI->getOpcode() == ARM::t2LDMIA_UPD || + MI->getOpcode() == ARM::VLDMDIA_UPD) { + // The first two operands are predicates. The last two are + // imp-def and imp-use of SP. Check everything in between. + for (int i = 5, e = MI->getNumOperands(); i != e; ++i) + if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs)) + return false; + return true; + } + + return false; } static void @@ -154,11 +127,10 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { DPRCSSize += 8; } } - - // 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); - + + // Move past area 1. + if (GPRCS1Size > 0) MBBI++; + // 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. // Otherwise, if this is not Darwin, all the callee-saved registers go @@ -172,14 +144,10 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { .addFrameIndex(FramePtrSpillFI).addImm(0); AddDefaultCC(AddDefaultPred(MIB)); } - - // Build the new SUBri to adjust SP for integer callee-save spill area 2. - 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); - emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize); - + + // Move past area 2. + if (GPRCS2Size > 0) MBBI++; + // Determine starting offsets of spill areas. unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; @@ -191,7 +159,9 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); - movePastCSLoadStoreOps(MBB, MBBI, ARM::VSTRD, 0, 3, STI); + // Move past area 3. + if (DPRCSSize > 0) MBBI++; + NumBytes = DPRCSOffset; if (NumBytes) { // Adjust SP after all the callee-save spills. @@ -325,17 +295,10 @@ void ARMFrameInfo::emitEpilogue(MachineFunction &MF, } else if (NumBytes) emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); - // Move SP to start of integer callee save spill area 2. - movePastCSLoadStoreOps(MBB, MBBI, ARM::VLDRD, 0, 3, STI); - 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); - 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()); + // Increment past our save areas. + if (AFI->getDPRCalleeSavedAreaSize()) MBBI++; + if (AFI->getGPRCalleeSavedArea2Size()) MBBI++; + if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; } if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND || |