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:
Evan Cheng 2007-03-06 10:03:56 +00:00
parent 87f8bf65dd
commit 140e33cfd1
2 changed files with 111 additions and 14 deletions

View File

@ -85,11 +85,6 @@ ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii,
: ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
TII(tii), STI(sti),
FramePtr(STI.useThumbBacktraces() ? ARM::R7 : ARM::R11) {
RS = (EnableScavenging) ? new RegScavenger() : NULL;
}
ARMRegisterInfo::~ARMRegisterInfo() {
delete RS;
}
bool ARMRegisterInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
@ -328,6 +323,25 @@ BitVector ARMRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
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
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
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
// out of 'Offset'.
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,
isSub ? -Offset : Offset, TII);
MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
}
}
void ARMRegisterInfo::
processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) {
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
// to take advantage the eliminateFrameIndex machinery. This also ensures it
// 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)) {
AFI->setHasStackFrame(true);
@ -1032,6 +1066,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const {
UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(),
UnspilledCS1GPRs.end(), (unsigned)ARM::LR));
ForceLRSpill = false;
ExtraCSSpill = true;
}
// 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();
MF.changePhyRegUsed(Reg, true);
AFI->setCSRegisterIsSpilled(Reg);
if (!isReservedReg(MF, Reg))
ExtraCSSpill = true;
} else if (!UnspilledCS2GPRs.empty()) {
unsigned Reg = UnspilledCS2GPRs.front();
MF.changePhyRegUsed(Reg, true);
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()));
}
}
}
}

View File

@ -27,17 +27,12 @@ struct ARMRegisterInfo : public ARMGenRegisterInfo {
const TargetInstrInfo &TII;
const ARMSubtarget &STI;
private:
/// RS - An instance of the register scavenger.
RegScavenger *RS;
/// FramePtr - ARM physical register used as frame ptr.
unsigned FramePtr;
public:
ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &STI);
~ARMRegisterInfo();
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// ARM::LR, return the number that it corresponds to (e.g. 14).
static unsigned getRegisterNumbering(unsigned RegEnum);
@ -74,6 +69,8 @@ public:
BitVector getReservedRegs(const MachineFunction &MF) const;
bool isReservedReg(const MachineFunction &MF, unsigned Reg) const;
bool requiresRegisterScavenging(const MachineFunction &MF) const;
bool hasFP(const MachineFunction &MF) const;
@ -85,7 +82,8 @@ public:
void eliminateFrameIndex(MachineBasicBlock::iterator II,
RegScavenger *RS = NULL) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;