diff options
author | Jim Grosbach <grosbach@apple.com> | 2009-10-05 22:30:23 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2009-10-05 22:30:23 +0000 |
commit | adf4cf604eeca26d6a854945893fa6c264e02900 (patch) | |
tree | b02075b715dc9df259f755e3f0558a53d3871675 /lib | |
parent | 1567166b9fe417a0656f9fcb2a18b35d915c34c3 (diff) | |
download | external_llvm-adf4cf604eeca26d6a854945893fa6c264e02900.zip external_llvm-adf4cf604eeca26d6a854945893fa6c264e02900.tar.gz external_llvm-adf4cf604eeca26d6a854945893fa6c264e02900.tar.bz2 |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/RegisterScavenging.cpp | 24 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/Thumb1RegisterInfo.cpp | 25 | ||||
-rw-r--r-- | lib/Target/ARM/Thumb1RegisterInfo.h | 8 |
4 files changed, 51 insertions, 12 deletions
diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 9fc3da3..9e56039 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 4db4636..4b7d32c 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 0cea27f..225468b 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 6eae904..4b1c577 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; |