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
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);
// 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;
// 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;
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(),
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;
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;