From 910139f9ca53fc20a680d51ae61bb1e072095141 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 9 Jul 2009 06:53:48 +0000 Subject: [PATCH] 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 --- include/llvm/Target/TargetRegisterInfo.h | 27 +++++++++++++------ lib/CodeGen/PrologEpilogInserter.cpp | 7 ++++- lib/Target/X86/X86InstrInfo.cpp | 13 ++++++--- lib/Target/X86/X86RegisterInfo.cpp | 13 ++++++--- lib/Target/X86/X86RegisterInfo.h | 4 ++- .../X86/2004-02-13-FrameReturnAddress.ll | 2 ++ test/CodeGen/X86/2008-08-31-EH_RETURN32.ll | 2 +- test/CodeGen/X86/2008-08-31-EH_RETURN64.ll | 2 +- 8 files changed, 52 insertions(+), 18 deletions(-) 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"