In Thumb1, the register scavenger is not always able to use an emergency

spill slot. When frame references are via the frame pointer, they will be
negative, but Thumb1 load/store instructions only allow positive immediate
offsets. Instead, Thumb1 will spill to R12.

llvm-svn: 83336
This commit is contained in:
Jim Grosbach 2009-10-05 22:30:23 +00:00
parent 72c458d8a6
commit d6da133b85
5 changed files with 69 additions and 12 deletions

View File

@ -635,6 +635,24 @@ public:
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
}
/// saveScavengerRegister - Save the register so it can be used by the
/// register scavenger. Return true if the register was saved, false
/// otherwise. If this function does not save the register, the scavenger
/// will instead spill it to the emergency spill slot.
///
virtual bool saveScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const {return false;}
/// restoreScavengerRegister - Restore a register saved by
/// saveScavengerRegister().
///
virtual void restoreScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const {}
/// eliminateFrameIndex - This method must be overriden to eliminate abstract
/// frame indices from instructions which may use them. The instruction
/// referenced by the iterator contains an MO_FrameIndex operand which must be

View File

@ -268,9 +268,6 @@ unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator MI,
unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
MachineBasicBlock::iterator I,
int SPAdj) {
assert(ScavengingFrameIndex >= 0 &&
"Cannot scavenge a register without an emergency spill slot!");
// Mask off the registers which are not in the TargetRegisterClass.
BitVector Candidates(NumPhysRegs, false);
CreateRegClassMask(RC, Candidates);
@ -301,14 +298,23 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
// Avoid infinite regress
ScavengedReg = SReg;
// Spill the scavenged register before I.
TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC);
MachineBasicBlock::iterator II = prior(I);
TRI->eliminateFrameIndex(II, SPAdj, this);
// If the target knows how to save/restore the register, let it do so;
// otherwise, use the emergency stack spill slot.
if (!TRI->saveScavengerRegister(*MBB, I, RC, SReg)) {
// Spill the scavenged register before I.
assert(ScavengingFrameIndex >= 0 &&
"Cannot scavenging register without an emergency spill slot!");
TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC);
MachineBasicBlock::iterator II = prior(I);
TRI->eliminateFrameIndex(II, SPAdj, this);
// Restore the scavenged register before its use (or first terminator).
TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC);
} else
TRI->restoreScavengerRegister(*MBB, UseMI, RC, SReg);
// Restore the scavenged register before its use (or first terminator).
TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC);
ScavengeRestore = prior(UseMI);
// Doing this here leads to infinite regress.
// ScavengedReg = SReg;
ScavengedRC = RC;

View File

@ -660,8 +660,7 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
// off the frame pointer, the effective stack size is 4 bytes larger
// since the FP points to the stack slot of the previous FP.
if (estimateStackSize(MF, MFI) + (hasFP(MF) ? 4 : 0)
>= estimateRSStackSizeLimit(MF)
|| AFI->isThumb1OnlyFunction()) {
>= estimateRSStackSizeLimit(MF)) {
// 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;
@ -690,7 +689,8 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
MF.getRegInfo().setPhysRegUsed(Extras[i]);
AFI->setCSRegisterIsSpilled(Extras[i]);
}
} else {
} else if (!AFI->isThumb1OnlyFunction()) {
// note: Thumb1 functions spill to R12, not the stack.
// Reserve a slot closest to SP or frame pointer.
const TargetRegisterClass *RC = ARM::GPRRegisterClass;
RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),

View File

@ -402,6 +402,31 @@ rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
return 0;
}
/// saveScavengerRegister - Save the register so it can be used by the
/// register scavenger. Return true.
bool Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const {
// Thumb1 can't use the emergency spill slot on the stack because
// ldr/str immediate offsets must be positive, and if we're referencing
// off the frame pointer (if, for example, there are alloca() calls in
// the function, the offset will be negative. Use R12 instead since that's
// a call clobbered register that we know won't be used in Thumb1 mode.
TII.copyRegToReg(MBB, I, ARM::R12, Reg, ARM::GPRRegisterClass, RC);
return true;
}
/// restoreScavengerRegister - restore a registers saved by
// saveScavengerRegister().
void Thumb1RegisterInfo::restoreScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const {
TII.copyRegToReg(MBB, I, Reg, ARM::R12, RC, ARM::GPRRegisterClass);
}
void Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS) const{
unsigned i = 0;

View File

@ -54,6 +54,14 @@ public:
unsigned FrameReg, int Offset,
unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const;
bool saveScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const;
void restoreScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const TargetRegisterClass *RC,
unsigned Reg) const;
void eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS = NULL) const;