diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 91e8f80fd10..29f96e961ab 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -567,18 +567,29 @@ public: /// has variable sized allocas or if frame pointer elimination is disabled. virtual bool hasFP(const MachineFunction &MF) const = 0; - // hasReservedCallFrame - Under normal circumstances, when a frame pointer is - // not required, we reserve argument space for call sites in the function - // 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 - // included as part of the stack frame. + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is + /// not required, we reserve argument space for call sites in the function + /// 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 + /// included as part of the stack frame. virtual bool hasReservedCallFrame(MachineFunction &MF) const { return !hasFP(MF); } - // needsStackRealignment - true if storage within the function requires the - // stack pointer to be aligned more than the normal calling convention calls - // for. + /// hasReservedSpillSlot - Return true if target has reserved a spill slot in + /// the stack frame of the given function for the specified register. e.g. On + /// 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 { return false; } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 6582fd8c8da..2365316261b 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -210,6 +210,12 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { unsigned Reg = I->getReg(); 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 // on this target. const std::pair *FixedSlot = FixedSpillSlots; @@ -217,7 +223,6 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { FixedSlot->first != Reg) ++FixedSlot; - int FrameIdx; if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RC->getAlignment(); diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 5507e43b6df..c2cd04c896a 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2029,6 +2029,7 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, unsigned SlotSize = is64Bit ? 8 : 4; MachineFunction &MF = *MBB.getParent(); + unsigned FPReg = RI.getFrameRegister(MF); X86MachineFunctionInfo *X86FI = MF.getInfo(); unsigned CalleeFrameSize = 0; @@ -2038,10 +2039,12 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetRegisterClass *RegClass = CSI[i-1].getRegClass(); // Add the callee-saved register as live-in. It's killed at the spill. MBB.addLiveIn(Reg); + if (Reg == FPReg) + // X86RegisterInfo::emitPrologue will handle spilling of frame register. + continue; if (RegClass != &X86::VR128RegClass) { CalleeFrameSize += SlotSize; - BuildMI(MBB, MI, DL, get(Opc)) - .addReg(Reg, RegState::Kill); + BuildMI(MBB, MI, DL, get(Opc)).addReg(Reg, RegState::Kill); } else { storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), RegClass); } @@ -2060,11 +2063,15 @@ bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + unsigned FPReg = RI.getFrameRegister(MF); bool is64Bit = TM.getSubtarget().is64Bit(); - unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r; for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); + if (Reg == FPReg) + // X86RegisterInfo::emitEpilogue will handle restoring of frame register. + continue; const TargetRegisterClass *RegClass = CSI[i].getRegClass(); if (RegClass != &X86::VR128RegClass) { BuildMI(MBB, MI, DL, get(Opc), Reg); diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 5b43d21d8e1..be4764e2768 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -345,6 +345,16 @@ bool X86RegisterInfo::hasReservedCallFrame(MachineFunction &MF) const { 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 X86RegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const { int Offset = MF.getFrameInfo()->getObjectOffset(FI) + SlotSize; @@ -493,10 +503,7 @@ X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, calculateMaxStackAlignment(FFI)); FFI->setMaxAlignment(MaxAlign); -} -void -X86RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) const{ X86MachineFunctionInfo *X86FI = MF.getInfo(); int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); if (TailCallReturnAddrDelta < 0) { diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index e1a23cb4edb..eac8426a980 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -125,6 +125,9 @@ public: bool hasReservedCallFrame(MachineFunction &MF) const; + bool hasReservedSpillSlot(MachineFunction &MF, unsigned Reg, + int &FrameIdx) const; + void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; @@ -132,7 +135,6 @@ public: void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, RegScavenger *RS = NULL) const; - void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS = NULL) const; diff --git a/test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll b/test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll index f48b1d3adf0..ee3169af040 100644 --- a/test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll +++ b/test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll @@ -1,4 +1,6 @@ ; 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) diff --git a/test/CodeGen/X86/2008-08-31-EH_RETURN32.ll b/test/CodeGen/X86/2008-08-31-EH_RETURN32.ll index e22b647a13f..8aa330e7b1a 100644 --- a/test/CodeGen/X86/2008-08-31-EH_RETURN32.ll +++ b/test/CodeGen/X86/2008-08-31-EH_RETURN32.ll @@ -1,5 +1,5 @@ ; 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 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" diff --git a/test/CodeGen/X86/2008-08-31-EH_RETURN64.ll b/test/CodeGen/X86/2008-08-31-EH_RETURN64.ll index 7d01824400c..80eeba7e1ea 100644 --- a/test/CodeGen/X86/2008-08-31-EH_RETURN64.ll +++ b/test/CodeGen/X86/2008-08-31-EH_RETURN64.ll @@ -1,5 +1,5 @@ ; 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 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"