From c87f68e32e1117b5c7b7bee4430e872cba696608 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Sat, 27 Nov 2010 23:05:03 +0000 Subject: [PATCH] Move callee-saved regs spills / reloads to TFI llvm-svn: 120228 --- include/llvm/Target/TargetFrameInfo.h | 25 ++++ include/llvm/Target/TargetInstrInfo.h | 23 ---- lib/CodeGen/PrologEpilogInserter.cpp | 5 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 122 ------------------- lib/Target/ARM/ARMBaseInstrInfo.h | 19 --- lib/Target/ARM/ARMFrameInfo.cpp | 132 +++++++++++++++++++- lib/Target/ARM/ARMFrameInfo.h | 17 +++ lib/Target/ARM/Thumb1FrameInfo.cpp | 79 ++++++++++++ lib/Target/ARM/Thumb1FrameInfo.h | 9 ++ lib/Target/ARM/Thumb1InstrInfo.cpp | 74 ------------ lib/Target/ARM/Thumb1InstrInfo.h | 9 -- lib/Target/MSP430/MSP430FrameInfo.cpp | 47 ++++++++ lib/Target/MSP430/MSP430FrameInfo.h | 9 ++ lib/Target/MSP430/MSP430InstrInfo.cpp | 42 ------- lib/Target/MSP430/MSP430InstrInfo.h | 9 -- lib/Target/SystemZ/SystemZFrameInfo.cpp | 154 ++++++++++++++++++++++++ lib/Target/SystemZ/SystemZFrameInfo.h | 15 ++- lib/Target/SystemZ/SystemZInstrInfo.cpp | 150 ----------------------- lib/Target/SystemZ/SystemZInstrInfo.h | 10 -- lib/Target/X86/X86FrameInfo.cpp | 71 +++++++++++ lib/Target/X86/X86FrameInfo.h | 10 ++ lib/Target/X86/X86InstrInfo.cpp | 70 ----------- lib/Target/X86/X86InstrInfo.h | 11 -- lib/Target/XCore/XCoreFrameInfo.cpp | 65 ++++++++++ lib/Target/XCore/XCoreFrameInfo.h | 9 ++ lib/Target/XCore/XCoreInstrInfo.cpp | 66 +--------- lib/Target/XCore/XCoreInstrInfo.h | 9 -- 27 files changed, 638 insertions(+), 623 deletions(-) diff --git a/include/llvm/Target/TargetFrameInfo.h b/include/llvm/Target/TargetFrameInfo.h index 7638c3db709..ebaf221aadd 100644 --- a/include/llvm/Target/TargetFrameInfo.h +++ b/include/llvm/Target/TargetFrameInfo.h @@ -14,10 +14,13 @@ #ifndef LLVM_TARGET_TARGETFRAMEINFO_H #define LLVM_TARGET_TARGETFRAMEINFO_H +#include "llvm/CodeGen/MachineBasicBlock.h" + #include #include namespace llvm { + class CalleeSavedInfo; class MachineFunction; class MachineBasicBlock; class MachineMove; @@ -108,6 +111,28 @@ public: virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of store instructions via + /// storeRegToStackSlot(). Returns false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + /// hasFP - Return true if the specified function should have a dedicated /// frame pointer register. For most targets this is true only if the function /// has variable sized allocas or if frame pointer elimination is disabled. diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 09400b3b837..21958bf3435 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -19,7 +19,6 @@ namespace llvm { -class CalleeSavedInfo; class InstrItineraryData; class LiveVariables; class MCAsmInfo; @@ -375,29 +374,7 @@ public: const TargetRegisterInfo *TRI) const { assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); } - - /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of store instructions via - /// storeRegToStackSlot(). Returns false otherwise. - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of load instructions via loadRegToStackSlot(). - /// Returns false otherwise. - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// emitFrameIndexDebugValue - Emit a target-dependent form of /// DBG_VALUE encoding the address of a frame index. Addresses would /// normally be lowered the same way as other addresses on the target, diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index f712a777c02..c461623192c 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -295,13 +295,14 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { return; const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); + const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo(); const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); MachineBasicBlock::iterator I; if (! ShrinkWrapThisFunction) { // Spill using target interface. I = EntryBlock->begin(); - if (!TII.spillCalleeSavedRegisters(*EntryBlock, I, CSI, TRI)) { + if (!TFI->spillCalleeSavedRegisters(*EntryBlock, I, CSI, TRI)) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { // Add the callee-saved register as live-in. // It's killed at the spill. @@ -333,7 +334,7 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { // Restore all registers immediately before the return and any // terminators that preceed it. - if (!TII.restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { + if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index cb9c11295bc..22fed76e927 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -197,128 +197,6 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, return NewMIs[0]; } -void -ARMBaseInstrInfo::emitPushInst(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, unsigned Opc, - bool(*Func)(unsigned, bool)) const { - MachineFunction &MF = *MBB.getParent(); - DebugLoc DL; - if (MI != MBB.end()) 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; - - // 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) { - if (MF.getFrameInfo()->isReturnAddressTaken() && - MF.getRegInfo().isLiveIn(Reg)) - isKill = false; - } - - 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 &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - MachineFunction &MF = *MBB.getParent(); - ARMFunctionInfo *AFI = MF.getInfo(); - 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 &CSI, unsigned Opc, - bool isVarArg, bool(*Func)(unsigned, bool)) const { - - MachineFunction &MF = *MBB.getParent(); - ARMFunctionInfo *AFI = MF.getInfo(); - 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); - } - - 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 &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - MachineFunction &MF = *MBB.getParent(); - ARMFunctionInfo *AFI = MF.getInfo(); - 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 diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 5e7156c9ce9..2b0da997616 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -206,25 +206,6 @@ public: virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0; const ARMSubtarget &getSubtarget() const { return Subtarget; } - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - - bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - -private: - void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector &CSI, unsigned Opc, - bool isVarArg, bool(*Func)(unsigned, bool)) const; - void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector &CSI, unsigned Opc, - bool(*Func)(unsigned, bool)) const; - - public: // Branch analysis. virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, diff --git a/lib/Target/ARM/ARMFrameInfo.cpp b/lib/Target/ARM/ARMFrameInfo.cpp index 62f3f986b27..d379bf0e9cb 100644 --- a/lib/Target/ARM/ARMFrameInfo.cpp +++ b/lib/Target/ARM/ARMFrameInfo.cpp @@ -174,10 +174,10 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { DPRCSSize += 8; } } - + // 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 @@ -191,10 +191,10 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { .addFrameIndex(FramePtrSpillFI).addImm(0); AddDefaultCC(AddDefaultPred(MIB)); } - + // Move past area 2. if (GPRCS2Size > 0) MBBI++; - + // Determine starting offsets of spill areas. unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; @@ -208,7 +208,7 @@ void ARMFrameInfo::emitPrologue(MachineFunction &MF) const { // Move past area 3. if (DPRCSSize > 0) MBBI++; - + NumBytes = DPRCSOffset; if (NumBytes) { // Adjust SP after all the callee-save spills. @@ -492,3 +492,125 @@ int ARMFrameInfo::getFrameIndexOffset(const MachineFunction &MF, int FI) const { unsigned FrameReg; return getFrameIndexReference(MF, FI, FrameReg); } + +void ARMFrameInfo::emitPushInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + unsigned Opc, + bool(*Func)(unsigned, bool)) const { + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineInstrBuilder MIB = BuildMI(MF, DL, TII.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, STI.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) { + if (MF.getFrameInfo()->isReturnAddressTaken() && + MF.getRegInfo().isLiveIn(Reg)) + isKill = false; + } + + 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 ARMFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + 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 ARMFrameInfo::emitPopInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + unsigned Opc, bool isVarArg, + bool(*Func)(unsigned, bool)) const { + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + DebugLoc DL = MI->getDebugLoc(); + + MachineInstrBuilder MIB = BuildMI(MF, DL, TII.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, STI.isTargetDarwin())) continue; + + if (Reg == ARM::LR && !isVarArg) { + Reg = ARM::PC; + unsigned Opc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET; + (*MIB).setDesc(TII.get(Opc)); + MI = MBB.erase(MI); + } + + 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 ARMFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + 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; +} diff --git a/lib/Target/ARM/ARMFrameInfo.h b/lib/Target/ARM/ARMFrameInfo.h index 9ee7f1f775b..7b34c1569db 100644 --- a/lib/Target/ARM/ARMFrameInfo.h +++ b/lib/Target/ARM/ARMFrameInfo.h @@ -35,6 +35,16 @@ public: void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasFP(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const; bool canSimplifyCallFramePseudos(const MachineFunction &MF) const; @@ -44,6 +54,13 @@ public: unsigned &FrameReg, int SPAdj) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + private: + void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, unsigned Opc, + bool isVarArg, bool(*Func)(unsigned, bool)) const; + void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, unsigned Opc, + bool(*Func)(unsigned, bool)) const; }; } // End llvm namespace diff --git a/lib/Target/ARM/Thumb1FrameInfo.cpp b/lib/Target/ARM/Thumb1FrameInfo.cpp index bb1faf576e5..d92d83c4e46 100644 --- a/lib/Target/ARM/Thumb1FrameInfo.cpp +++ b/lib/Target/ARM/Thumb1FrameInfo.cpp @@ -264,3 +264,82 @@ void Thumb1FrameInfo::emitEpilogue(MachineFunction &MF, MBB.erase(MBBI); } } + +bool Thumb1FrameInfo:: +spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.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 + // @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. + if (Reg == ARM::LR) { + MachineFunction &MF = *MBB.getParent(); + if (MF.getFrameInfo()->isReturnAddressTaken() && + MF.getRegInfo().isLiveIn(Reg)) + isKill = false; + } + + if (isKill) + MBB.addLiveIn(Reg); + + MIB.addReg(Reg, getKillRegState(isKill)); + } + return true; +} + +bool Thumb1FrameInfo:: +restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; + DebugLoc DL = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MF, DL, TII.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) { + // Special epilogue for vararg functions. See emitEpilogue + if (isVarArg) + continue; + Reg = ARM::PC; + (*MIB).setDesc(TII.get(ARM::tPOP_RET)); + MI = MBB.erase(MI); + } + 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; +} diff --git a/lib/Target/ARM/Thumb1FrameInfo.h b/lib/Target/ARM/Thumb1FrameInfo.h index f2ecaf1617a..c51edec5357 100644 --- a/lib/Target/ARM/Thumb1FrameInfo.h +++ b/lib/Target/ARM/Thumb1FrameInfo.h @@ -35,6 +35,15 @@ public: void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasReservedCallFrame(const MachineFunction &MF) const; }; diff --git a/lib/Target/ARM/Thumb1InstrInfo.cpp b/lib/Target/ARM/Thumb1InstrInfo.cpp index 7e20a0ff499..3fbb43340c3 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.cpp +++ b/lib/Target/ARM/Thumb1InstrInfo.cpp @@ -109,77 +109,3 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); } } - -bool Thumb1InstrInfo:: -spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - 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 - // @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. - if (Reg == ARM::LR) { - MachineFunction &MF = *MBB.getParent(); - if (MF.getFrameInfo()->isReturnAddressTaken() && - MF.getRegInfo().isLiveIn(Reg)) - isKill = false; - } - - if (isKill) - MBB.addLiveIn(Reg); - - MIB.addReg(Reg, getKillRegState(isKill)); - } - return true; -} - -bool Thumb1InstrInfo:: -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) { - // Special epilogue for vararg functions. See emitEpilogue - if (isVarArg) - continue; - Reg = ARM::PC; - (*MIB).setDesc(get(ARM::tPOP_RET)); - MI = MBB.erase(MI); - } - 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; -} diff --git a/lib/Target/ARM/Thumb1InstrInfo.h b/lib/Target/ARM/Thumb1InstrInfo.h index eff439bd94d..17ef2f758ef 100644 --- a/lib/Target/ARM/Thumb1InstrInfo.h +++ b/lib/Target/ARM/Thumb1InstrInfo.h @@ -37,15 +37,6 @@ public: /// const Thumb1RegisterInfo &getRegisterInfo() const { return RI; } - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, diff --git a/lib/Target/MSP430/MSP430FrameInfo.cpp b/lib/Target/MSP430/MSP430FrameInfo.cpp index 0a39a3629f5..7e7a0e41fd2 100644 --- a/lib/Target/MSP430/MSP430FrameInfo.cpp +++ b/lib/Target/MSP430/MSP430FrameInfo.cpp @@ -174,3 +174,50 @@ void MSP430FrameInfo::emitEpilogue(MachineFunction &MF, } } } + +// FIXME: Can we eleminate these in favour of generic code? +bool +MSP430FrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + MSP430MachineFunctionInfo *MFI = MF.getInfo(); + MFI->setCalleeSavedFrameSize(CSI.size() * 2); + + 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); + BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r)) + .addReg(Reg, RegState::Kill); + } + return true; +} + +bool +MSP430FrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) + BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg()); + + return true; +} diff --git a/lib/Target/MSP430/MSP430FrameInfo.h b/lib/Target/MSP430/MSP430FrameInfo.h index 00bf99d31ed..f80a3487a85 100644 --- a/lib/Target/MSP430/MSP430FrameInfo.h +++ b/lib/Target/MSP430/MSP430FrameInfo.h @@ -35,6 +35,15 @@ public: void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasFP(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const; }; diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index ab94adcca8d..424df136cc1 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -101,48 +101,6 @@ void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB, .addReg(SrcReg, getKillRegState(KillSrc)); } -bool -MSP430InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - MachineFunction &MF = *MBB.getParent(); - MSP430MachineFunctionInfo *MFI = MF.getInfo(); - MFI->setCalleeSavedFrameSize(CSI.size() * 2); - - 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); - BuildMI(MBB, MI, DL, get(MSP430::PUSH16r)) - .addReg(Reg, RegState::Kill); - } - return true; -} - -bool -MSP430InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - for (unsigned i = 0, e = CSI.size(); i != e; ++i) - BuildMI(MBB, MI, DL, get(MSP430::POP16r), CSI[i].getReg()); - - return true; -} - unsigned MSP430InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.end(); unsigned Count = 0; diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h index 49ccc032bf2..e885cd36a04 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.h +++ b/lib/Target/MSP430/MSP430InstrInfo.h @@ -66,15 +66,6 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - unsigned GetInstSizeInBytes(const MachineInstr *MI) const; // Branch folding goodness diff --git a/lib/Target/SystemZ/SystemZFrameInfo.cpp b/lib/Target/SystemZ/SystemZFrameInfo.cpp index 331b917415b..7fde9a0144f 100644 --- a/lib/Target/SystemZ/SystemZFrameInfo.cpp +++ b/lib/Target/SystemZ/SystemZFrameInfo.cpp @@ -27,6 +27,31 @@ using namespace llvm; +SystemZFrameInfo::SystemZFrameInfo(const SystemZSubtarget &sti) + : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160), STI(sti) { + // Fill the spill offsets map + static const unsigned SpillOffsTab[][2] = { + { SystemZ::R2D, 0x10 }, + { SystemZ::R3D, 0x18 }, + { SystemZ::R4D, 0x20 }, + { SystemZ::R5D, 0x28 }, + { SystemZ::R6D, 0x30 }, + { SystemZ::R7D, 0x38 }, + { SystemZ::R8D, 0x40 }, + { SystemZ::R9D, 0x48 }, + { SystemZ::R10D, 0x50 }, + { SystemZ::R11D, 0x58 }, + { SystemZ::R12D, 0x60 }, + { SystemZ::R13D, 0x68 }, + { SystemZ::R14D, 0x70 }, + { SystemZ::R15D, 0x78 } + }; + + RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); + + for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i) + RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1]; +} /// needsFP - Return true if the specified function should have a dedicated /// frame pointer register. This is true if the function has variable sized @@ -197,3 +222,132 @@ int SystemZFrameInfo::getFrameIndexOffset(const MachineFunction &MF, return Offset; } + +bool +SystemZFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + SystemZMachineFunctionInfo *MFI = MF.getInfo(); + unsigned CalleeFrameSize = 0; + + // Scan the callee-saved and find the bounds of register spill area. + unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (!SystemZ::FP64RegClass.contains(Reg)) { + unsigned Offset = RegSpillOffsets[Reg]; + CalleeFrameSize += 8; + if (StartOffset > Offset) { + LowReg = Reg; StartOffset = Offset; + } + if (EndOffset < Offset) { + HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; + } + } + } + + // Save information for epilogue inserter. + MFI->setCalleeSavedFrameSize(CalleeFrameSize); + MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); + + // Save GPRs + if (StartOffset) { + // Build a store instruction. Use STORE MULTIPLE instruction if there are many + // registers to store, otherwise - just STORE. + MachineInstrBuilder MIB = + BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ? + SystemZ::MOV64mr : SystemZ::MOV64mrm))); + + // Add store operands. + MIB.addReg(SystemZ::R15D).addImm(StartOffset); + if (LowReg == HighReg) + MIB.addReg(0); + MIB.addReg(LowReg, RegState::Kill); + if (LowReg != HighReg) + MIB.addReg(HighReg, RegState::Kill); + + // Do a second scan adding regs as being killed by instruction + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); + if (Reg != LowReg && Reg != HighReg) + MIB.addReg(Reg, RegState::ImplicitKill); + } + } + + // Save FPRs + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (SystemZ::FP64RegClass.contains(Reg)) { + MBB.addLiveIn(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), + &SystemZ::FP64RegClass, TRI); + } + } + + return true; +} + +bool +SystemZFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + SystemZMachineFunctionInfo *MFI = MF.getInfo(); + + // Restore FP registers + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (SystemZ::FP64RegClass.contains(Reg)) + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), + &SystemZ::FP64RegClass, TRI); + } + + // Restore GP registers + unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); + unsigned StartOffset = RegSpillOffsets[LowReg]; + + if (StartOffset) { + // Build a load instruction. Use LOAD MULTIPLE instruction if there are many + // registers to load, otherwise - just LOAD. + MachineInstrBuilder MIB = + BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ? + SystemZ::MOV64rm : SystemZ::MOV64rmm))); + // Add store operands. + MIB.addReg(LowReg, RegState::Define); + if (LowReg != HighReg) + MIB.addReg(HighReg, RegState::Define); + + MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D); + MIB.addImm(StartOffset); + if (LowReg == HighReg) + MIB.addReg(0); + + // Do a second scan adding regs as being defined by instruction + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (Reg != LowReg && Reg != HighReg) + MIB.addReg(Reg, RegState::ImplicitDefine); + } + } + + return true; +} diff --git a/lib/Target/SystemZ/SystemZFrameInfo.h b/lib/Target/SystemZ/SystemZFrameInfo.h index 85782f86f05..a977502d65b 100644 --- a/lib/Target/SystemZ/SystemZFrameInfo.h +++ b/lib/Target/SystemZ/SystemZFrameInfo.h @@ -17,24 +17,33 @@ #include "SystemZ.h" #include "SystemZSubtarget.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/ADT/IndexedMap.h" namespace llvm { class SystemZSubtarget; class SystemZFrameInfo : public TargetFrameInfo { + IndexedMap RegSpillOffsets; protected: const SystemZSubtarget &STI; public: - explicit SystemZFrameInfo(const SystemZSubtarget &sti) - : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160), STI(sti) { - } + explicit SystemZFrameInfo(const SystemZSubtarget &sti); /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasReservedCallFrame(const MachineFunction &MF) const { return true; } bool hasFP(const MachineFunction &MF) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index c145ce08458..be5280323c3 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -28,28 +28,6 @@ using namespace llvm; SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)), RI(tm, *this), TM(tm) { - // Fill the spill offsets map - static const unsigned SpillOffsTab[][2] = { - { SystemZ::R2D, 0x10 }, - { SystemZ::R3D, 0x18 }, - { SystemZ::R4D, 0x20 }, - { SystemZ::R5D, 0x28 }, - { SystemZ::R6D, 0x30 }, - { SystemZ::R7D, 0x38 }, - { SystemZ::R8D, 0x40 }, - { SystemZ::R9D, 0x48 }, - { SystemZ::R10D, 0x50 }, - { SystemZ::R11D, 0x58 }, - { SystemZ::R12D, 0x60 }, - { SystemZ::R13D, 0x68 }, - { SystemZ::R14D, 0x70 }, - { SystemZ::R15D, 0x78 } - }; - - RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); - - for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i) - RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1]; } /// isGVStub - Return true if the GV requires an extra load to get the @@ -211,134 +189,6 @@ unsigned SystemZInstrInfo::isStoreToStackSlot(const MachineInstr *MI, return 0; } -bool -SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - MachineFunction &MF = *MBB.getParent(); - SystemZMachineFunctionInfo *MFI = MF.getInfo(); - unsigned CalleeFrameSize = 0; - - // Scan the callee-saved and find the bounds of register spill area. - unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0; - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (!SystemZ::FP64RegClass.contains(Reg)) { - unsigned Offset = RegSpillOffsets[Reg]; - CalleeFrameSize += 8; - if (StartOffset > Offset) { - LowReg = Reg; StartOffset = Offset; - } - if (EndOffset < Offset) { - HighReg = Reg; EndOffset = RegSpillOffsets[Reg]; - } - } - } - - // Save information for epilogue inserter. - MFI->setCalleeSavedFrameSize(CalleeFrameSize); - MFI->setLowReg(LowReg); MFI->setHighReg(HighReg); - - // Save GPRs - if (StartOffset) { - // Build a store instruction. Use STORE MULTIPLE instruction if there are many - // registers to store, otherwise - just STORE. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, get((LowReg == HighReg ? - SystemZ::MOV64mr : SystemZ::MOV64mrm))); - - // Add store operands. - MIB.addReg(SystemZ::R15D).addImm(StartOffset); - if (LowReg == HighReg) - MIB.addReg(0); - MIB.addReg(LowReg, RegState::Kill); - if (LowReg != HighReg) - MIB.addReg(HighReg, RegState::Kill); - - // Do a second scan adding regs as being killed by instruction - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - // Add the callee-saved register as live-in. It's killed at the spill. - MBB.addLiveIn(Reg); - if (Reg != LowReg && Reg != HighReg) - MIB.addReg(Reg, RegState::ImplicitKill); - } - } - - // Save FPRs - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (SystemZ::FP64RegClass.contains(Reg)) { - MBB.addLiveIn(Reg); - storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), - &SystemZ::FP64RegClass, &RI); - } - } - - return true; -} - -bool -SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - MachineFunction &MF = *MBB.getParent(); - const TargetFrameInfo *TFI = MF.getTarget().getFrameInfo(); - SystemZMachineFunctionInfo *MFI = MF.getInfo(); - - // Restore FP registers - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (SystemZ::FP64RegClass.contains(Reg)) - loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), - &SystemZ::FP64RegClass, &RI); - } - - // Restore GP registers - unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); - unsigned StartOffset = RegSpillOffsets[LowReg]; - - if (StartOffset) { - // Build a load instruction. Use LOAD MULTIPLE instruction if there are many - // registers to load, otherwise - just LOAD. - MachineInstrBuilder MIB = - BuildMI(MBB, MI, DL, get((LowReg == HighReg ? - SystemZ::MOV64rm : SystemZ::MOV64rmm))); - // Add store operands. - MIB.addReg(LowReg, RegState::Define); - if (LowReg != HighReg) - MIB.addReg(HighReg, RegState::Define); - - MIB.addReg(TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D); - MIB.addImm(StartOffset); - if (LowReg == HighReg) - MIB.addReg(0); - - // Do a second scan adding regs as being defined by instruction - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (Reg != LowReg && Reg != HighReg) - MIB.addReg(Reg, RegState::ImplicitDefine); - } - } - - return true; -} - bool SystemZInstrInfo:: ReverseBranchCondition(SmallVectorImpl &Cond) const { assert(Cond.size() == 1 && "Invalid Xbranch condition!"); diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index c248f2489c4..6cb72001020 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -50,7 +50,6 @@ namespace SystemZII { class SystemZInstrInfo : public TargetInstrInfoImpl { const SystemZRegisterInfo RI; SystemZTargetMachine &TM; - IndexedMap RegSpillOffsets; public: explicit SystemZInstrInfo(SystemZTargetMachine &TM); @@ -80,15 +79,6 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - bool ReverseBranchCondition(SmallVectorImpl &Cond) const; virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; virtual bool AnalyzeBranch(MachineBasicBlock &MBB, diff --git a/lib/Target/X86/X86FrameInfo.cpp b/lib/Target/X86/X86FrameInfo.cpp index 420568ab774..192ed8ebe01 100644 --- a/lib/Target/X86/X86FrameInfo.cpp +++ b/lib/Target/X86/X86FrameInfo.cpp @@ -799,3 +799,74 @@ int X86FrameInfo::getFrameIndexOffset(const MachineFunction &MF, int FI) const { return Offset; } + +bool X86FrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL = MBB.findDebugLoc(MI); + + MachineFunction &MF = *MBB.getParent(); + + bool isWin64 = STI.isTargetWin64(); + unsigned SlotSize = STI.is64Bit() ? 8 : 4; + unsigned FPReg = TRI->getFrameRegister(MF); + unsigned CalleeFrameSize = 0; + + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + X86MachineFunctionInfo *X86FI = MF.getInfo(); + + unsigned Opc = STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r; + 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); + if (Reg == FPReg) + // X86RegisterInfo::emitPrologue will handle spilling of frame register. + continue; + if (!X86::VR128RegClass.contains(Reg) && !isWin64) { + CalleeFrameSize += SlotSize; + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill); + } else { + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), + RC, TRI); + } + } + + X86FI->setCalleeSavedFrameSize(CalleeFrameSize); + return true; +} + +bool X86FrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + DebugLoc DL = MBB.findDebugLoc(MI); + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + unsigned FPReg = TRI->getFrameRegister(MF); + bool isWin64 = STI.isTargetWin64(); + unsigned Opc = STI.is64Bit() ? X86::POP64r : X86::POP32r; + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + if (Reg == FPReg) + // X86RegisterInfo::emitEpilogue will handle restoring of frame register. + continue; + if (!X86::VR128RegClass.contains(Reg) && !isWin64) { + BuildMI(MBB, MI, DL, TII.get(Opc), Reg); + } else { + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), + RC, TRI); + } + } + return true; +} diff --git a/lib/Target/X86/X86FrameInfo.h b/lib/Target/X86/X86FrameInfo.h index b6d32508d1a..d265c610153 100644 --- a/lib/Target/X86/X86FrameInfo.h +++ b/lib/Target/X86/X86FrameInfo.h @@ -40,6 +40,16 @@ public: void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + +bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasFP(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 79d9872a1b2..06c35b48f89 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2151,76 +2151,6 @@ void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, NewMIs.push_back(MIB); } -bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL = MBB.findDebugLoc(MI); - - bool is64Bit = TM.getSubtarget().is64Bit(); - bool isWin64 = TM.getSubtarget().isTargetWin64(); - unsigned SlotSize = is64Bit ? 8 : 4; - - MachineFunction &MF = *MBB.getParent(); - unsigned FPReg = RI.getFrameRegister(MF); - X86MachineFunctionInfo *X86FI = MF.getInfo(); - unsigned CalleeFrameSize = 0; - - unsigned Opc = is64Bit ? X86::PUSH64r : X86::PUSH32r; - 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); - if (Reg == FPReg) - // X86RegisterInfo::emitPrologue will handle spilling of frame register. - continue; - if (!X86::VR128RegClass.contains(Reg) && !isWin64) { - CalleeFrameSize += SlotSize; - BuildMI(MBB, MI, DL, get(Opc)).addReg(Reg, RegState::Kill); - } else { - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), - RC, &RI); - } - } - - X86FI->setCalleeSavedFrameSize(CalleeFrameSize); - return true; -} - -bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) - return false; - - DebugLoc DL = MBB.findDebugLoc(MI); - - MachineFunction &MF = *MBB.getParent(); - unsigned FPReg = RI.getFrameRegister(MF); - bool is64Bit = TM.getSubtarget().is64Bit(); - bool isWin64 = TM.getSubtarget().isTargetWin64(); - unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r; - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (Reg == FPReg) - // X86RegisterInfo::emitEpilogue will handle restoring of frame register. - continue; - if (!X86::VR128RegClass.contains(Reg) && !isWin64) { - BuildMI(MBB, MI, DL, get(Opc), Reg); - } else { - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), - RC, &RI); - } - } - return true; -} - MachineInstr* X86InstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 46db68ed08e..1d442078727 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -742,17 +742,6 @@ public: MachineInstr::mmo_iterator MMOBegin, MachineInstr::mmo_iterator MMOEnd, SmallVectorImpl &NewMIs) const; - - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, diff --git a/lib/Target/XCore/XCoreFrameInfo.cpp b/lib/Target/XCore/XCoreFrameInfo.cpp index 5359abb98c9..cf957a7ed45 100644 --- a/lib/Target/XCore/XCoreFrameInfo.cpp +++ b/lib/Target/XCore/XCoreFrameInfo.cpp @@ -271,3 +271,68 @@ void XCoreFrameInfo::getInitialFrameState(std::vector &Moves) MachineLocation Src(XCore::SP, 0); Moves.push_back(MachineMove(0, Dst, Src)); } + +bool XCoreFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return true; + + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + + XCoreFunctionInfo *XFI = MF->getInfo(); + bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + for (std::vector::const_iterator it = CSI.begin(); + it != CSI.end(); ++it) { + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(it->getReg()); + + unsigned Reg = it->getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, true, + it->getFrameIdx(), RC, TRI); + if (emitFrameMoves) { + MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); + BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel); + XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); + } + } + return true; +} + +bool XCoreFrameInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const{ + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + + bool AtStart = MI == MBB.begin(); + MachineBasicBlock::iterator BeforeI = MI; + if (!AtStart) + --BeforeI; + for (std::vector::const_iterator it = CSI.begin(); + it != CSI.end(); ++it) { + unsigned Reg = it->getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(), + RC, TRI); + assert(MI != MBB.begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert multiple + // instructions. + if (AtStart) + MI = MBB.begin(); + else { + MI = BeforeI; + ++MI; + } + } + return true; +} diff --git a/lib/Target/XCore/XCoreFrameInfo.h b/lib/Target/XCore/XCoreFrameInfo.h index 86ca7919145..57983d179e8 100644 --- a/lib/Target/XCore/XCoreFrameInfo.h +++ b/lib/Target/XCore/XCoreFrameInfo.h @@ -31,6 +31,15 @@ namespace llvm { void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + bool hasFP(const MachineFunction &MF) const; void getInitialFrameState(std::vector &Moves) const; diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index ad00046af17..9cb6a7d17b5 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -384,74 +384,10 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, .addImm(0); } -bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const { - if (CSI.empty()) { - return true; - } - MachineFunction *MF = MBB.getParent(); - XCoreFunctionInfo *XFI = MF->getInfo(); - - bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF); - - DebugLoc DL; - if (MI != MBB.end()) DL = MI->getDebugLoc(); - - for (std::vector::const_iterator it = CSI.begin(); - it != CSI.end(); ++it) { - // Add the callee-saved register as live-in. It's killed at the spill. - MBB.addLiveIn(it->getReg()); - - unsigned Reg = it->getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - storeRegToStackSlot(MBB, MI, Reg, true, - it->getFrameIdx(), RC, &RI); - if (emitFrameMoves) { - MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol(); - BuildMI(MBB, MI, DL, get(XCore::PROLOG_LABEL)).addSym(SaveLabel); - XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it)); - } - } - return true; -} - -bool XCoreInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const -{ - bool AtStart = MI == MBB.begin(); - MachineBasicBlock::iterator BeforeI = MI; - if (!AtStart) - --BeforeI; - for (std::vector::const_iterator it = CSI.begin(); - it != CSI.end(); ++it) { - unsigned Reg = it->getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - loadRegFromStackSlot(MBB, MI, it->getReg(), - it->getFrameIdx(), - RC, &RI); - assert(MI != MBB.begin() && - "loadRegFromStackSlot didn't insert any code!"); - // Insert in reverse order. loadRegFromStackSlot can insert multiple - // instructions. - if (AtStart) - MI = MBB.begin(); - else { - MI = BeforeI; - ++MI; - } - } - return true; -} - /// ReverseBranchCondition - Return the inverse opcode of the /// specified Branch instruction. bool XCoreInstrInfo:: -ReverseBranchCondition(SmallVectorImpl &Cond) const -{ +ReverseBranchCondition(SmallVectorImpl &Cond) const { assert((Cond.size() == 2) && "Invalid XCore branch condition!"); Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm())); diff --git a/lib/Target/XCore/XCoreInstrInfo.h b/lib/Target/XCore/XCoreInstrInfo.h index d2b116eef0d..977fe8dd550 100644 --- a/lib/Target/XCore/XCoreInstrInfo.h +++ b/lib/Target/XCore/XCoreInstrInfo.h @@ -75,15 +75,6 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; - - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector &CSI, - const TargetRegisterInfo *TRI) const; virtual bool ReverseBranchCondition( SmallVectorImpl &Cond) const;