mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +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
|
#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.
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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!");
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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()));
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user