mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
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:
parent
055942529b
commit
cd775ceff0
@ -14,10 +14,13 @@
|
||||
#ifndef LLVM_TARGET_TARGETFRAMEINFO_H
|
||||
#define LLVM_TARGET_TARGETFRAMEINFO_H
|
||||
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
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<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
|
||||
/// frame pointer register. For most targets this is true only if the function
|
||||
/// has variable sized allocas or if frame pointer elimination is disabled.
|
||||
|
@ -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<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
|
||||
/// DBG_VALUE encoding the address of a frame index. Addresses would
|
||||
/// normally be lowered the same way as other addresses on the target,
|
||||
|
@ -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);
|
||||
|
@ -197,128 +197,6 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
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.
|
||||
bool
|
||||
|
@ -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<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
private:
|
||||
void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI, unsigned Opc,
|
||||
bool isVarArg, bool(*Func)(unsigned, bool)) const;
|
||||
void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI, unsigned Opc,
|
||||
bool(*Func)(unsigned, bool)) const;
|
||||
|
||||
|
||||
public:
|
||||
// Branch analysis.
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
|
@ -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<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;
|
||||
}
|
||||
|
@ -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<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 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<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
|
||||
|
@ -264,3 +264,82 @@ void Thumb1FrameInfo::emitEpilogue(MachineFunction &MF,
|
||||
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;
|
||||
}
|
||||
|
@ -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<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;
|
||||
};
|
||||
|
||||
|
@ -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<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;
|
||||
}
|
||||
|
@ -37,15 +37,6 @@ public:
|
||||
///
|
||||
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,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<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 hasReservedCallFrame(const MachineFunction &MF) const;
|
||||
};
|
||||
|
@ -101,48 +101,6 @@ void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||
.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 {
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
unsigned Count = 0;
|
||||
|
@ -66,15 +66,6 @@ public:
|
||||
const TargetRegisterClass *RC,
|
||||
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;
|
||||
|
||||
// Branch folding goodness
|
||||
|
@ -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<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;
|
||||
}
|
||||
|
@ -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<unsigned> 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<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 hasFP(const MachineFunction &MF) const;
|
||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||
|
@ -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<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::
|
||||
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
|
||||
assert(Cond.size() == 1 && "Invalid Xbranch condition!");
|
||||
|
@ -50,7 +50,6 @@ namespace SystemZII {
|
||||
class SystemZInstrInfo : public TargetInstrInfoImpl {
|
||||
const SystemZRegisterInfo RI;
|
||||
SystemZTargetMachine &TM;
|
||||
IndexedMap<unsigned> 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<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;
|
||||
virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const;
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
|
@ -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<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;
|
||||
}
|
||||
|
@ -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<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 hasReservedCallFrame(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -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<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*
|
||||
X86InstrInfo::emitFrameIndexDebugValue(MachineFunction &MF,
|
||||
int FrameIx, uint64_t Offset,
|
||||
|
@ -742,17 +742,6 @@ public:
|
||||
MachineInstr::mmo_iterator MMOBegin,
|
||||
MachineInstr::mmo_iterator MMOEnd,
|
||||
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
|
||||
MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF,
|
||||
int FrameIx, uint64_t Offset,
|
||||
|
@ -271,3 +271,68 @@ void XCoreFrameInfo::getInitialFrameState(std::vector<MachineMove> &Moves)
|
||||
MachineLocation Src(XCore::SP, 0);
|
||||
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;
|
||||
}
|
||||
|
@ -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<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;
|
||||
|
||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||
|
@ -384,74 +384,10 @@ void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
.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
|
||||
/// specified Branch instruction.
|
||||
bool XCoreInstrInfo::
|
||||
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
|
||||
{
|
||||
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
|
||||
assert((Cond.size() == 2) &&
|
||||
"Invalid XCore branch condition!");
|
||||
Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
|
||||
|
@ -75,15 +75,6 @@ public:
|
||||
const TargetRegisterClass *RC,
|
||||
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(
|
||||
SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
Loading…
Reference in New Issue
Block a user