Move callee-saved regs spills / reloads to TFI

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120228 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2010-11-27 23:05:03 +00:00
parent 055942529b
commit cd775ceff0
27 changed files with 638 additions and 623 deletions

View File

@ -14,10 +14,13 @@
#ifndef LLVM_TARGET_TARGETFRAMEINFO_H #ifndef LLVM_TARGET_TARGETFRAMEINFO_H
#define LLVM_TARGET_TARGETFRAMEINFO_H #define LLVM_TARGET_TARGETFRAMEINFO_H
#include "llvm/CodeGen/MachineBasicBlock.h"
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace llvm { namespace llvm {
class CalleeSavedInfo;
class MachineFunction; class MachineFunction;
class MachineBasicBlock; class MachineBasicBlock;
class MachineMove; class MachineMove;
@ -108,6 +111,28 @@ public:
virtual void emitEpilogue(MachineFunction &MF, virtual void emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const = 0; 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<CalleeSavedInfo> &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<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
return false;
}
/// hasFP - Return true if the specified function should have a dedicated /// hasFP - Return true if the specified function should have a dedicated
/// frame pointer register. For most targets this is true only if the function /// frame pointer register. For most targets this is true only if the function
/// has variable sized allocas or if frame pointer elimination is disabled. /// has variable sized allocas or if frame pointer elimination is disabled.

View File

@ -19,7 +19,6 @@
namespace llvm { namespace llvm {
class CalleeSavedInfo;
class InstrItineraryData; class InstrItineraryData;
class LiveVariables; class LiveVariables;
class MCAsmInfo; class MCAsmInfo;
@ -376,28 +375,6 @@ public:
assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); 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<CalleeSavedInfo> &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<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
return false;
}
/// emitFrameIndexDebugValue - Emit a target-dependent form of /// emitFrameIndexDebugValue - Emit a target-dependent form of
/// DBG_VALUE encoding the address of a frame index. Addresses would /// DBG_VALUE encoding the address of a frame index. Addresses would
/// normally be lowered the same way as other addresses on the target, /// normally be lowered the same way as other addresses on the target,

View File

@ -295,13 +295,14 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) {
return; return;
const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo();
MachineBasicBlock::iterator I; MachineBasicBlock::iterator I;
if (! ShrinkWrapThisFunction) { if (! ShrinkWrapThisFunction) {
// Spill using target interface. // Spill using target interface.
I = EntryBlock->begin(); 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) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
// Add the callee-saved register as live-in. // Add the callee-saved register as live-in.
// It's killed at the spill. // It's killed at the spill.
@ -333,7 +334,7 @@ void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) {
// Restore all registers immediately before the return and any // Restore all registers immediately before the return and any
// terminators that preceed it. // 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) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg(); unsigned Reg = CSI[i].getReg();
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);

View File

@ -197,128 +197,6 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
return NewMIs[0]; return NewMIs[0];
} }
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();
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<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);
}
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. // Branch analysis.
bool bool

View File

@ -206,25 +206,6 @@ public:
virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0; virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0;
const ARMSubtarget &getSubtarget() const { return Subtarget; } const ARMSubtarget &getSubtarget() const { return Subtarget; }
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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: public:
// Branch analysis. // Branch analysis.
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,

View File

@ -492,3 +492,125 @@ int ARMFrameInfo::getFrameIndexOffset(const MachineFunction &MF, int FI) const {
unsigned FrameReg; unsigned FrameReg;
return getFrameIndexReference(MF, FI, FrameReg); return getFrameIndexReference(MF, FI, FrameReg);
} }
void ARMFrameInfo::emitPushInst(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<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 ARMFrameInfo::emitPopInst(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
unsigned Opc, bool isVarArg,
bool(*Func)(unsigned, bool)) const {
MachineFunction &MF = *MBB.getParent();
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
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<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;
}

View File

@ -35,6 +35,16 @@ public:
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasFP(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;
bool hasReservedCallFrame(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const;
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const; bool canSimplifyCallFramePseudos(const MachineFunction &MF) const;
@ -44,6 +54,13 @@ public:
unsigned &FrameReg, int SPAdj) const; unsigned &FrameReg, int SPAdj) const;
int getFrameIndexOffset(const MachineFunction &MF, int FI) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) 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;
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -264,3 +264,82 @@ void Thumb1FrameInfo::emitEpilogue(MachineFunction &MF,
MBB.erase(MBBI); MBB.erase(MBBI);
} }
} }
bool Thumb1FrameInfo::
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return false;
MachineFunction &MF = *MBB.getParent();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
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;
}

View File

@ -35,6 +35,15 @@ public:
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasReservedCallFrame(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const;
}; };

View File

@ -109,77 +109,3 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addFrameIndex(FI).addImm(0).addMemOperand(MMO)); .addFrameIndex(FI).addImm(0).addMemOperand(MMO));
} }
} }
bool Thumb1InstrInfo::
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<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) {
// 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;
}

View File

@ -37,15 +37,6 @@ public:
/// ///
const Thumb1RegisterInfo &getRegisterInfo() const { return RI; } const Thumb1RegisterInfo &getRegisterInfo() const { return RI; }
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
void copyPhysReg(MachineBasicBlock &MBB, void copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, DebugLoc DL, MachineBasicBlock::iterator I, DebugLoc DL,
unsigned DestReg, unsigned SrcReg, unsigned DestReg, unsigned SrcReg,

View File

@ -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<CalleeSavedInfo> &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<MSP430MachineFunctionInfo>();
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<CalleeSavedInfo> &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;
}

View File

@ -35,6 +35,15 @@ public:
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasFP(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;
bool hasReservedCallFrame(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const;
}; };

View File

@ -101,48 +101,6 @@ void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addReg(SrcReg, getKillRegState(KillSrc)); .addReg(SrcReg, getKillRegState(KillSrc));
} }
bool
MSP430InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<MSP430MachineFunctionInfo>();
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<CalleeSavedInfo> &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 { unsigned MSP430InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator I = MBB.end();
unsigned Count = 0; unsigned Count = 0;

View File

@ -66,15 +66,6 @@ public:
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const; const TargetRegisterInfo *TRI) const;
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
unsigned GetInstSizeInBytes(const MachineInstr *MI) const; unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
// Branch folding goodness // Branch folding goodness

View File

@ -27,6 +27,31 @@
using namespace llvm; 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 /// needsFP - Return true if the specified function should have a dedicated
/// frame pointer register. This is true if the function has variable sized /// frame pointer register. This is true if the function has variable sized
@ -197,3 +222,132 @@ int SystemZFrameInfo::getFrameIndexOffset(const MachineFunction &MF,
return Offset; return Offset;
} }
bool
SystemZFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<SystemZMachineFunctionInfo>();
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<CalleeSavedInfo> &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<SystemZMachineFunctionInfo>();
// 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;
}

View File

@ -17,24 +17,33 @@
#include "SystemZ.h" #include "SystemZ.h"
#include "SystemZSubtarget.h" #include "SystemZSubtarget.h"
#include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetFrameInfo.h"
#include "llvm/ADT/IndexedMap.h"
namespace llvm { namespace llvm {
class SystemZSubtarget; class SystemZSubtarget;
class SystemZFrameInfo : public TargetFrameInfo { class SystemZFrameInfo : public TargetFrameInfo {
IndexedMap<unsigned> RegSpillOffsets;
protected: protected:
const SystemZSubtarget &STI; const SystemZSubtarget &STI;
public: public:
explicit SystemZFrameInfo(const SystemZSubtarget &sti) explicit SystemZFrameInfo(const SystemZSubtarget &sti);
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160), STI(sti) {
}
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function. /// the function.
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasReservedCallFrame(const MachineFunction &MF) const { return true; } bool hasReservedCallFrame(const MachineFunction &MF) const { return true; }
bool hasFP(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;
int getFrameIndexOffset(const MachineFunction &MF, int FI) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const;

View File

@ -28,28 +28,6 @@ using namespace llvm;
SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm) SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
: TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)), : TargetInstrInfoImpl(SystemZInsts, array_lengthof(SystemZInsts)),
RI(tm, *this), TM(tm) { 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 /// 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; return 0;
} }
bool
SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<SystemZMachineFunctionInfo>();
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<CalleeSavedInfo> &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<SystemZMachineFunctionInfo>();
// 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:: bool SystemZInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
assert(Cond.size() == 1 && "Invalid Xbranch condition!"); assert(Cond.size() == 1 && "Invalid Xbranch condition!");

View File

@ -50,7 +50,6 @@ namespace SystemZII {
class SystemZInstrInfo : public TargetInstrInfoImpl { class SystemZInstrInfo : public TargetInstrInfoImpl {
const SystemZRegisterInfo RI; const SystemZRegisterInfo RI;
SystemZTargetMachine &TM; SystemZTargetMachine &TM;
IndexedMap<unsigned> RegSpillOffsets;
public: public:
explicit SystemZInstrInfo(SystemZTargetMachine &TM); explicit SystemZInstrInfo(SystemZTargetMachine &TM);
@ -80,15 +79,6 @@ public:
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const; const TargetRegisterInfo *TRI) const;
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const;
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, virtual bool AnalyzeBranch(MachineBasicBlock &MBB,

View File

@ -799,3 +799,74 @@ int X86FrameInfo::getFrameIndexOffset(const MachineFunction &MF, int FI) const {
return Offset; return Offset;
} }
bool X86FrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &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<X86MachineFunctionInfo>();
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<CalleeSavedInfo> &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;
}

View File

@ -40,6 +40,16 @@ public:
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasFP(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;
bool hasReservedCallFrame(const MachineFunction &MF) const; bool hasReservedCallFrame(const MachineFunction &MF) const;

View File

@ -2151,76 +2151,6 @@ void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
NewMIs.push_back(MIB); NewMIs.push_back(MIB);
} }
bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return false;
DebugLoc DL = MBB.findDebugLoc(MI);
bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
bool isWin64 = TM.getSubtarget<X86Subtarget>().isTargetWin64();
unsigned SlotSize = is64Bit ? 8 : 4;
MachineFunction &MF = *MBB.getParent();
unsigned FPReg = RI.getFrameRegister(MF);
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
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<CalleeSavedInfo> &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<X86Subtarget>().is64Bit();
bool isWin64 = TM.getSubtarget<X86Subtarget>().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* MachineInstr*
X86InstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, X86InstrInfo::emitFrameIndexDebugValue(MachineFunction &MF,
int FrameIx, uint64_t Offset, int FrameIx, uint64_t Offset,

View File

@ -742,17 +742,6 @@ public:
MachineInstr::mmo_iterator MMOBegin, MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd, MachineInstr::mmo_iterator MMOEnd,
SmallVectorImpl<MachineInstr*> &NewMIs) const; SmallVectorImpl<MachineInstr*> &NewMIs) const;
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual virtual
MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF,
int FrameIx, uint64_t Offset, int FrameIx, uint64_t Offset,

View File

@ -271,3 +271,68 @@ void XCoreFrameInfo::getInitialFrameState(std::vector<MachineMove> &Moves)
MachineLocation Src(XCore::SP, 0); MachineLocation Src(XCore::SP, 0);
Moves.push_back(MachineMove(0, Dst, Src)); Moves.push_back(MachineMove(0, Dst, Src));
} }
bool XCoreFrameInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return true;
MachineFunction *MF = MBB.getParent();
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
for (std::vector<CalleeSavedInfo>::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<CalleeSavedInfo> &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<CalleeSavedInfo>::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;
}

View File

@ -31,6 +31,15 @@ namespace llvm {
void emitPrologue(MachineFunction &MF) const; void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
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;
bool hasFP(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;
void getInitialFrameState(std::vector<MachineMove> &Moves) const; void getInitialFrameState(std::vector<MachineMove> &Moves) const;

View File

@ -384,74 +384,10 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
.addImm(0); .addImm(0);
} }
bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
if (CSI.empty()) {
return true;
}
MachineFunction *MF = MBB.getParent();
XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
for (std::vector<CalleeSavedInfo>::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<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const
{
bool AtStart = MI == MBB.begin();
MachineBasicBlock::iterator BeforeI = MI;
if (!AtStart)
--BeforeI;
for (std::vector<CalleeSavedInfo>::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 /// ReverseBranchCondition - Return the inverse opcode of the
/// specified Branch instruction. /// specified Branch instruction.
bool XCoreInstrInfo:: bool XCoreInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
{
assert((Cond.size() == 2) && assert((Cond.size() == 2) &&
"Invalid XCore branch condition!"); "Invalid XCore branch condition!");
Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm())); Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));

View File

@ -75,15 +75,6 @@ public:
const TargetRegisterClass *RC, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const; const TargetRegisterInfo *TRI) const;
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const;
virtual bool ReverseBranchCondition( virtual bool ReverseBranchCondition(
SmallVectorImpl<MachineOperand> &Cond) const; SmallVectorImpl<MachineOperand> &Cond) const;