mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
Scavenge a register using the register scavenger when needed.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34966 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
87f8bf65dd
commit
140e33cfd1
@ -85,11 +85,6 @@ ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii,
|
|||||||
: ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
|
: ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
|
||||||
TII(tii), STI(sti),
|
TII(tii), STI(sti),
|
||||||
FramePtr(STI.useThumbBacktraces() ? ARM::R7 : ARM::R11) {
|
FramePtr(STI.useThumbBacktraces() ? ARM::R7 : ARM::R11) {
|
||||||
RS = (EnableScavenging) ? new RegScavenger() : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ARMRegisterInfo::~ARMRegisterInfo() {
|
|
||||||
delete RS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMRegisterInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
bool ARMRegisterInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||||
@ -328,6 +323,25 @@ BitVector ARMRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|||||||
return Reserved;
|
return Reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ARMRegisterInfo::isReservedReg(const MachineFunction &MF, unsigned Reg) const {
|
||||||
|
switch (Reg) {
|
||||||
|
default: break;
|
||||||
|
case ARM::SP:
|
||||||
|
case ARM::PC:
|
||||||
|
return true;
|
||||||
|
case ARM::R7:
|
||||||
|
case ARM::R11:
|
||||||
|
if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF)))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case ARM::R9:
|
||||||
|
return STI.isR9Reserved();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
|
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
|
||||||
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
@ -918,15 +932,34 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
// to form it with a series of ADDri's. Do this by taking 8-bit chunks
|
// to form it with a series of ADDri's. Do this by taking 8-bit chunks
|
||||||
// out of 'Offset'.
|
// out of 'Offset'.
|
||||||
unsigned ScratchReg = findScratchRegister(RS, &ARM::GPRRegClass, AFI);
|
unsigned ScratchReg = findScratchRegister(RS, &ARM::GPRRegClass, AFI);
|
||||||
assert(ScratchReg && "Unable to find a free register!");
|
if (ScratchReg == 0)
|
||||||
|
// No register is "free". Scavenge a register.
|
||||||
|
ScratchReg = RS->scavengeRegister(&ARM::GPRRegClass, II);
|
||||||
emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg,
|
emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg,
|
||||||
isSub ? -Offset : Offset, TII);
|
isSub ? -Offset : Offset, TII);
|
||||||
MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
|
MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMRegisterInfo::
|
static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) {
|
||||||
processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
|
const MachineFrameInfo *FFI = MF.getFrameInfo();
|
||||||
|
int Offset = 0;
|
||||||
|
for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
|
||||||
|
int FixedOff = -FFI->getObjectOffset(i);
|
||||||
|
if (FixedOff > Offset) Offset = FixedOff;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
|
||||||
|
Offset += FFI->getObjectSize(i);
|
||||||
|
unsigned Align = FFI->getObjectAlignment(i);
|
||||||
|
// Adjust to alignment boundary
|
||||||
|
Offset = (Offset+Align-1)/Align*Align;
|
||||||
|
}
|
||||||
|
return (unsigned)Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ARMRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS) const {
|
||||||
// This tells PEI to spill the FP as if it is any other callee-save register
|
// This tells PEI to spill the FP as if it is any other callee-save register
|
||||||
// to take advantage the eliminateFrameIndex machinery. This also ensures it
|
// to take advantage the eliminateFrameIndex machinery. This also ensures it
|
||||||
// is spilled in the order specified by getCalleeSavedRegs() to make it easier
|
// is spilled in the order specified by getCalleeSavedRegs() to make it easier
|
||||||
@ -1020,6 +1053,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExtraCSSpill = false;
|
||||||
if (!CanEliminateFrame || hasFP(MF)) {
|
if (!CanEliminateFrame || hasFP(MF)) {
|
||||||
AFI->setHasStackFrame(true);
|
AFI->setHasStackFrame(true);
|
||||||
|
|
||||||
@ -1032,6 +1066,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
|
|||||||
UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
|
UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
|
||||||
UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
|
UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
|
||||||
ForceLRSpill = false;
|
ForceLRSpill = false;
|
||||||
|
ExtraCSSpill = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Darwin ABI requires FP to point to the stack slot that contains the
|
// Darwin ABI requires FP to point to the stack slot that contains the
|
||||||
@ -1050,10 +1085,74 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
|
|||||||
unsigned Reg = UnspilledCS1GPRs.front();
|
unsigned Reg = UnspilledCS1GPRs.front();
|
||||||
MF.changePhyRegUsed(Reg, true);
|
MF.changePhyRegUsed(Reg, true);
|
||||||
AFI->setCSRegisterIsSpilled(Reg);
|
AFI->setCSRegisterIsSpilled(Reg);
|
||||||
|
if (!isReservedReg(MF, Reg))
|
||||||
|
ExtraCSSpill = true;
|
||||||
} else if (!UnspilledCS2GPRs.empty()) {
|
} else if (!UnspilledCS2GPRs.empty()) {
|
||||||
unsigned Reg = UnspilledCS2GPRs.front();
|
unsigned Reg = UnspilledCS2GPRs.front();
|
||||||
MF.changePhyRegUsed(Reg, true);
|
MF.changePhyRegUsed(Reg, true);
|
||||||
AFI->setCSRegisterIsSpilled(Reg);
|
AFI->setCSRegisterIsSpilled(Reg);
|
||||||
|
if (!isReservedReg(MF, Reg))
|
||||||
|
ExtraCSSpill = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estimate if we might need to scavenge a register at some point in order
|
||||||
|
// to materialize a stack offset. If so, either spill one additiona
|
||||||
|
// callee-saved register or reserve a special spill slot to facilitate
|
||||||
|
// register scavenging.
|
||||||
|
if (RS && !ExtraCSSpill && !AFI->isThumbFunction()) {
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
unsigned Size = estimateStackSize(MF, MFI);
|
||||||
|
unsigned Limit = (1 << 12) - 1;
|
||||||
|
for (MachineFunction::iterator BB = MF.begin(),E = MF.end();BB != E; ++BB)
|
||||||
|
for (MachineBasicBlock::iterator I= BB->begin(); I != BB->end(); ++I) {
|
||||||
|
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
|
||||||
|
if (I->getOperand(i).isFrameIndex()) {
|
||||||
|
unsigned Opcode = I->getOpcode();
|
||||||
|
const TargetInstrDescriptor &Desc = TII.get(Opcode);
|
||||||
|
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
||||||
|
if (AddrMode == ARMII::AddrMode3) {
|
||||||
|
Limit = (1 << 8) - 1;
|
||||||
|
goto DoneEstimating;
|
||||||
|
} else if (AddrMode == ARMII::AddrMode5) {
|
||||||
|
Limit = ((1 << 8) - 1) * 4;
|
||||||
|
goto DoneEstimating;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DoneEstimating:
|
||||||
|
if (Size >= Limit) {
|
||||||
|
// If any non-reserved CS register isn't spilled, just spill one or two
|
||||||
|
// extra. That should take care of it!
|
||||||
|
unsigned NumExtras = TargetAlign / 4;
|
||||||
|
SmallVector<unsigned, 2> Extras;
|
||||||
|
while (NumExtras && !UnspilledCS1GPRs.empty()) {
|
||||||
|
unsigned Reg = UnspilledCS1GPRs.back();
|
||||||
|
UnspilledCS1GPRs.pop_back();
|
||||||
|
if (!isReservedReg(MF, Reg)) {
|
||||||
|
Extras.push_back(Reg);
|
||||||
|
NumExtras--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (NumExtras && !UnspilledCS2GPRs.empty()) {
|
||||||
|
unsigned Reg = UnspilledCS2GPRs.back();
|
||||||
|
UnspilledCS2GPRs.pop_back();
|
||||||
|
if (!isReservedReg(MF, Reg)) {
|
||||||
|
Extras.push_back(Reg);
|
||||||
|
NumExtras--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Extras.size() && NumExtras == 0) {
|
||||||
|
for (unsigned i = 0, e = Extras.size(); i != e; ++i) {
|
||||||
|
MF.changePhyRegUsed(Extras[i], true);
|
||||||
|
AFI->setCSRegisterIsSpilled(Extras[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Reserve a slot closest to SP or frame pointer.
|
||||||
|
const TargetRegisterClass *RC = &ARM::GPRRegClass;
|
||||||
|
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
|
||||||
|
RC->getAlignment()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,17 +27,12 @@ struct ARMRegisterInfo : public ARMGenRegisterInfo {
|
|||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
const ARMSubtarget &STI;
|
const ARMSubtarget &STI;
|
||||||
private:
|
private:
|
||||||
/// RS - An instance of the register scavenger.
|
|
||||||
RegScavenger *RS;
|
|
||||||
|
|
||||||
/// FramePtr - ARM physical register used as frame ptr.
|
/// FramePtr - ARM physical register used as frame ptr.
|
||||||
unsigned FramePtr;
|
unsigned FramePtr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &STI);
|
ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &STI);
|
||||||
|
|
||||||
~ARMRegisterInfo();
|
|
||||||
|
|
||||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||||
/// ARM::LR, return the number that it corresponds to (e.g. 14).
|
/// ARM::LR, return the number that it corresponds to (e.g. 14).
|
||||||
static unsigned getRegisterNumbering(unsigned RegEnum);
|
static unsigned getRegisterNumbering(unsigned RegEnum);
|
||||||
@ -74,6 +69,8 @@ public:
|
|||||||
|
|
||||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
bool isReservedReg(const MachineFunction &MF, unsigned Reg) const;
|
||||||
|
|
||||||
bool requiresRegisterScavenging(const MachineFunction &MF) const;
|
bool requiresRegisterScavenging(const MachineFunction &MF) const;
|
||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
@ -85,7 +82,8 @@ public:
|
|||||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||||
RegScavenger *RS = NULL) const;
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const;
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
RegScavenger *RS = NULL) const;
|
||||||
|
|
||||||
void emitPrologue(MachineFunction &MF) const;
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user