Targets sometimes assign fixed stack object to spill certain callee-saved
authorEvan Cheng <evan.cheng@apple.com>
Thu, 9 Jul 2009 06:53:48 +0000 (06:53 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 9 Jul 2009 06:53:48 +0000 (06:53 +0000)
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
lib/CodeGen/PrologEpilogInserter.cpp
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86RegisterInfo.cpp
lib/Target/X86/X86RegisterInfo.h
test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll
test/CodeGen/X86/2008-08-31-EH_RETURN32.ll
test/CodeGen/X86/2008-08-31-EH_RETURN64.ll

index 91e8f80fd108dd8ddc098526a8c1b3cc3e02bd3c..29f96e961abcc5ce51842dc3b63508b7359487fb 100644 (file)
@@ -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;
   }
index 6582fd8c8da54cbf67f4607fb46663cd1de3cf6d..2365316261b8f2949a7ef53a3457b72aec700477 100644 (file)
@@ -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<unsigned,int> *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();
index 5507e43b6df3f129cb506561c9e39f0d3e8de2f9..c2cd04c896a159648bc4df1d52e4d1690c733125 100644 (file)
@@ -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<X86MachineFunctionInfo>();
   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<X86Subtarget>().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);
index 5b43d21d8e1a3258d00d9a288452bf1dda3a1357..be4764e276828d27731c9d1dc14f8095381ed80b 100644 (file)
@@ -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<X86MachineFunctionInfo>();
   int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
   if (TailCallReturnAddrDelta < 0) {
index e1a23cb4edbfc2cce6b2fe75cf1535a2b292e59b..eac8426a980ea0628069962694176c31c0f2fa24 100644 (file)
@@ -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;
 
index f48b1d3adf0159f308d5166b2bd6e2c25a939b1f..ee3169af04038ebe2a043ac9a8c98436a79b6e84 100644 (file)
@@ -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)
 
index e22b647a13f0a5cfd74747201799c0f624a58e85..8aa330e7b1aefe4cfbe7683892f4128f7a46f52c 100644 (file)
@@ -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"
index 7d01824400c8ed00ec3945157771433dd47a635a..80eeba7e1eaa47229fcc39784d4e88f14048cee8 100644 (file)
@@ -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"