Targets sometimes assign fixed stack object to spill certain callee-saved

registers based on dynamic conditions. For example, X86 EBP/RBP, when used as
frame register has to be spilled in the first fixed object. It should inform
PEI this so it doesn't get allocated another stack object. Also, it should not
be spilled as other callee-saved registers but rather its spilling and restoring
are being handled by emitPrologue and emitEpilogue. Avoid spilling it twice.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75116 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-07-09 06:53:48 +00:00
parent 1945b7b5c5
commit 910139f9ca
8 changed files with 52 additions and 18 deletions

View File

@ -567,18 +567,29 @@ public:
/// has variable sized allocas or if frame pointer elimination is disabled. /// has variable sized allocas or if frame pointer elimination is disabled.
virtual bool hasFP(const MachineFunction &MF) const = 0; virtual bool hasFP(const MachineFunction &MF) const = 0;
// hasReservedCallFrame - Under normal circumstances, when a frame pointer is /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
// not required, we reserve argument space for call sites in the function /// not required, we reserve argument space for call sites in the function
// immediately on entry to the current function. This eliminates the need for /// immediately on entry to the current function. This eliminates the need for
// add/sub sp brackets around call sites. Returns true if the call frame is /// add/sub sp brackets around call sites. Returns true if the call frame is
// included as part of the stack frame. /// included as part of the stack frame.
virtual bool hasReservedCallFrame(MachineFunction &MF) const { virtual bool hasReservedCallFrame(MachineFunction &MF) const {
return !hasFP(MF); return !hasFP(MF);
} }
// needsStackRealignment - true if storage within the function requires the /// hasReservedSpillSlot - Return true if target has reserved a spill slot in
// stack pointer to be aligned more than the normal calling convention calls /// the stack frame of the given function for the specified register. e.g. On
// for. /// x86, if the frame register is required, the first fixed stack object is
/// reserved as its spill slot. This tells PEI not to create a new stack frame
/// object for the given register. It should be called only after
/// processFunctionBeforeCalleeSavedScan().
virtual bool hasReservedSpillSlot(MachineFunction &MF, unsigned Reg,
int &FrameIdx) const {
return false;
}
/// needsStackRealignment - true if storage within the function requires the
/// stack pointer to be aligned more than the normal calling convention calls
/// for.
virtual bool needsStackRealignment(const MachineFunction &MF) const { virtual bool needsStackRealignment(const MachineFunction &MF) const {
return false; return false;
} }

View File

@ -210,6 +210,12 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
unsigned Reg = I->getReg(); unsigned Reg = I->getReg();
const TargetRegisterClass *RC = I->getRegClass(); const TargetRegisterClass *RC = I->getRegClass();
int FrameIdx;
if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) {
I->setFrameIdx(FrameIdx);
continue;
}
// Check to see if this physreg must be spilled to a particular stack slot // Check to see if this physreg must be spilled to a particular stack slot
// on this target. // on this target.
const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots; const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
@ -217,7 +223,6 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
FixedSlot->first != Reg) FixedSlot->first != Reg)
++FixedSlot; ++FixedSlot;
int FrameIdx;
if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {
// Nope, just spill it anywhere convenient. // Nope, just spill it anywhere convenient.
unsigned Align = RC->getAlignment(); unsigned Align = RC->getAlignment();

View File

@ -2029,6 +2029,7 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
unsigned SlotSize = is64Bit ? 8 : 4; unsigned SlotSize = is64Bit ? 8 : 4;
MachineFunction &MF = *MBB.getParent(); MachineFunction &MF = *MBB.getParent();
unsigned FPReg = RI.getFrameRegister(MF);
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
unsigned CalleeFrameSize = 0; unsigned CalleeFrameSize = 0;
@ -2038,10 +2039,12 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
const TargetRegisterClass *RegClass = CSI[i-1].getRegClass(); const TargetRegisterClass *RegClass = CSI[i-1].getRegClass();
// Add the callee-saved register as live-in. It's killed at the spill. // Add the callee-saved register as live-in. It's killed at the spill.
MBB.addLiveIn(Reg); MBB.addLiveIn(Reg);
if (Reg == FPReg)
// X86RegisterInfo::emitPrologue will handle spilling of frame register.
continue;
if (RegClass != &X86::VR128RegClass) { if (RegClass != &X86::VR128RegClass) {
CalleeFrameSize += SlotSize; CalleeFrameSize += SlotSize;
BuildMI(MBB, MI, DL, get(Opc)) BuildMI(MBB, MI, DL, get(Opc)).addReg(Reg, RegState::Kill);
.addReg(Reg, RegState::Kill);
} else { } else {
storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), RegClass); storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), RegClass);
} }
@ -2060,11 +2063,15 @@ bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
DebugLoc DL = DebugLoc::getUnknownLoc(); DebugLoc DL = DebugLoc::getUnknownLoc();
if (MI != MBB.end()) DL = MI->getDebugLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc();
MachineFunction &MF = *MBB.getParent();
unsigned FPReg = RI.getFrameRegister(MF);
bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit(); bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r; unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r;
for (unsigned i = 0, e = CSI.size(); i != e; ++i) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg(); unsigned Reg = CSI[i].getReg();
if (Reg == FPReg)
// X86RegisterInfo::emitEpilogue will handle restoring of frame register.
continue;
const TargetRegisterClass *RegClass = CSI[i].getRegClass(); const TargetRegisterClass *RegClass = CSI[i].getRegClass();
if (RegClass != &X86::VR128RegClass) { if (RegClass != &X86::VR128RegClass) {
BuildMI(MBB, MI, DL, get(Opc), Reg); BuildMI(MBB, MI, DL, get(Opc), Reg);

View File

@ -345,6 +345,16 @@ bool X86RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const {
return !MF.getFrameInfo()->hasVarSizedObjects(); return !MF.getFrameInfo()->hasVarSizedObjects();
} }
bool X86RegisterInfo::hasReservedSpillSlot(MachineFunction &MF, unsigned Reg,
int &FrameIdx) const {
if (Reg == FramePtr && hasFP(MF)) {
FrameIdx = MF.getFrameInfo()->getObjectIndexBegin();
return true;
}
return false;
}
int int
X86RegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { X86RegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const {
int Offset = MF.getFrameInfo()->getObjectOffset(FI) + SlotSize; int Offset = MF.getFrameInfo()->getObjectOffset(FI) + SlotSize;
@ -493,10 +503,7 @@ X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
calculateMaxStackAlignment(FFI)); calculateMaxStackAlignment(FFI));
FFI->setMaxAlignment(MaxAlign); FFI->setMaxAlignment(MaxAlign);
}
void
X86RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) const{
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
if (TailCallReturnAddrDelta < 0) { if (TailCallReturnAddrDelta < 0) {

View File

@ -125,6 +125,9 @@ public:
bool hasReservedCallFrame(MachineFunction &MF) const; bool hasReservedCallFrame(MachineFunction &MF) const;
bool hasReservedSpillSlot(MachineFunction &MF, unsigned Reg,
int &FrameIdx) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF, void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const; MachineBasicBlock::iterator MI) const;
@ -132,7 +135,6 @@ public:
void eliminateFrameIndex(MachineBasicBlock::iterator MI, void eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, RegScavenger *RS = NULL) const; int SPAdj, RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const; RegScavenger *RS = NULL) const;

View File

@ -1,4 +1,6 @@
; RUN: llvm-as < %s | llc -march=x86 | grep {(%esp} ; RUN: llvm-as < %s | llc -march=x86 | grep {(%esp}
; RUN: llvm-as < %s | llc -march=x86 | grep {pushl %ebp} | count 1
; RUN: llvm-as < %s | llc -march=x86 | grep {popl %ebp} | count 1
declare i8* @llvm.returnaddress(i32) declare i8* @llvm.returnaddress(i32)

View File

@ -1,5 +1,5 @@
; Check that eh_return & unwind_init were properly lowered ; Check that eh_return & unwind_init were properly lowered
; RUN: llvm-as < %s | llc | grep %ebp | count 9 ; RUN: llvm-as < %s | llc | grep %ebp | count 7
; RUN: llvm-as < %s | llc | grep %ecx | count 5 ; RUN: llvm-as < %s | llc | grep %ecx | count 5
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"

View File

@ -1,5 +1,5 @@
; Check that eh_return & unwind_init were properly lowered ; Check that eh_return & unwind_init were properly lowered
; RUN: llvm-as < %s | llc | grep %rbp | count 7 ; RUN: llvm-as < %s | llc | grep %rbp | count 5
; RUN: llvm-as < %s | llc | grep %rcx | count 3 ; RUN: llvm-as < %s | llc | grep %rcx | count 3
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"