aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2009-10-05 22:30:23 +0000
committerJim Grosbach <grosbach@apple.com>2009-10-05 22:30:23 +0000
commit540b05d227a79443b2a7b07d5152a35cb6392abf (patch)
treeb02075b715dc9df259f755e3f0558a53d3871675
parent303bf73ebdfe66b1538351b26aa3d84c4b2e35c8 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83336 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h18
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp24
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp6
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp25
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.h8
5 files changed, 69 insertions, 12 deletions
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 6043ec8f61..11347b0e39 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -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
diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp
index 9fc3da3b17..9e56039330 100644
--- a/lib/CodeGen/RegisterScavenging.cpp
+++ b/lib/CodeGen/RegisterScavenging.cpp
@@ -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;
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 4db4636600..4b7d32c8ff 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -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(),
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp
index 0cea27f74d..225468b36c 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.cpp
+++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp
@@ -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;
diff --git a/lib/Target/ARM/Thumb1RegisterInfo.h b/lib/Target/ARM/Thumb1RegisterInfo.h
index 6eae904c16..4b1c5776e4 100644
--- a/lib/Target/ARM/Thumb1RegisterInfo.h
+++ b/lib/Target/ARM/Thumb1RegisterInfo.h
@@ -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;