]> granicus.if.org Git - llvm/commitdiff
Don't force SP-relative addressing for statepoints
authorSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 15 Jun 2016 05:35:14 +0000 (05:35 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 15 Jun 2016 05:35:14 +0000 (05:35 +0000)
Summary:
...  when the offset is not statically known.

Prioritize addresses relative to the stack pointer in the stackmap, but
fallback gracefully to other modes of addressing if the offset to the
stack pointer is not a known constant.

Patch by Oscar Blumberg!

Reviewers: sanjoy

Subscribers: llvm-commits, majnemer, rnk, sanjoy, thanm

Differential Revision: http://reviews.llvm.org/D21259

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272756 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetFrameLowering.h
lib/CodeGen/AsmPrinter/WinException.cpp
lib/CodeGen/PrologEpilogInserter.cpp
lib/Target/X86/X86FrameLowering.cpp
lib/Target/X86/X86FrameLowering.h
test/CodeGen/X86/deopt-bundles.ll

index cdde1ffe9189f2d574a77e6148f4c16095eecee9..a71845e3e9a1343194310cbcee3f83b4ad408b29 100644 (file)
@@ -249,12 +249,16 @@ public:
   /// Same as above, except that the 'base register' will always be RSP, not
   /// RBP on x86. This is generally used for emitting statepoint or EH tables
   /// that use offsets from RSP.
+  /// If AllowSPAdjustment is true, the returned offset is only guaranteed
+  /// to be valid with respect to the value of SP at the end of the prologue.
   /// TODO: This should really be a parameterizable choice.
-  virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
-                                           unsigned &FrameReg) const {
+  virtual Optional<int>
+  getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
+                               unsigned &FrameReg,
+                               bool AllowSPAdjustment) const {
     // default to calling normal version, we override this on x86 only
     llvm_unreachable("unimplemented for non-x86");
-    return 0;
+    return None;
   }
 
   /// This method determines which of the registers reported by
index 478396556d2757bf65c514b23505ced5a307a801..083aacb3fc599097468d8587466f14d0388b6187 100644 (file)
@@ -302,7 +302,8 @@ int WinException::getFrameIndexOffset(int FrameIndex,
   const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering();
   unsigned UnusedReg;
   if (Asm->MAI->usesWindowsCFI())
-    return TFI.getFrameIndexReferenceFromSP(*Asm->MF, FrameIndex, UnusedReg);
+    return *TFI.getFrameIndexReferenceFromSP(*Asm->MF, FrameIndex, UnusedReg,
+                                             /*AllowSPAdjustment*/ true);
   // For 32-bit, offsets should be relative to the end of the EH registration
   // node. For 64-bit, it's relative to SP at the end of the prologue.
   assert(FuncInfo.EHRegNodeEndOffset != INT_MAX);
index bd7f34b485e3765e4d677801e323fe9f4a3daa5e..33935c421a342d71b5670b3e5738d5f8958c2472 100644 (file)
@@ -1094,9 +1094,16 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn,
                "DBG_VALUE machine instruction");
         unsigned Reg;
         MachineOperand &Offset = MI->getOperand(i + 1);
-        const unsigned refOffset =
-          TFI->getFrameIndexReferenceFromSP(Fn, MI->getOperand(i).getIndex(),
-                                            Reg);
+        int refOffset;
+        // First try to get an offset relative to SP. If that's not
+        // possible use whatever the target usually uses.
+        auto SPOffset = TFI->getFrameIndexReferenceFromSP(
+            Fn, MI->getOperand(i).getIndex(), Reg, /*AllowSPAdjustment*/ false);
+        if (SPOffset)
+          refOffset = *SPOffset;
+        else
+          refOffset = TFI->getFrameIndexReference(
+              Fn, MI->getOperand(i).getIndex(), Reg);
 
         Offset.setImm(Offset.getImm() + refOffset);
         MI->getOperand(i).ChangeToRegister(Reg, false /*isDef*/);
index 393dcb9d10428fe29cced553315116a6b5f385de..975eb0c4513171183a5256f6d200def28f4d560e 100644 (file)
@@ -1436,7 +1436,8 @@ X86FrameLowering::getPSPSlotOffsetFromSP(const MachineFunction &MF) const {
   // getFrameIndexReferenceFromSP has an out ref parameter for the stack
   // pointer register; pass a dummy that we ignore
   unsigned SPReg;
-  int Offset = getFrameIndexReferenceFromSP(MF, Info.PSPSymFrameIdx, SPReg);
+  int Offset = *getFrameIndexReferenceFromSP(MF, Info.PSPSymFrameIdx, SPReg,
+                                             /*AllowSPAdjustment*/ true);
   assert(Offset >= 0);
   return static_cast<unsigned>(Offset);
 }
@@ -1722,57 +1723,60 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
 }
 
 // Simplified from getFrameIndexReference keeping only StackPointer cases
-int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
-                                                   int FI,
-                                                   unsigned &FrameReg) const {
+Optional<int>
+X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
+                                               int FI, unsigned &FrameReg,
+                                               bool AllowSPAdjustment) const {
   const MachineFrameInfo *MFI = MF.getFrameInfo();
   // Does not include any dynamic realign.
   const uint64_t StackSize = MFI->getStackSize();
-  {
-#ifndef NDEBUG
-    // LLVM arranges the stack as follows:
-    //   ...
-    //   ARG2
-    //   ARG1
-    //   RETADDR
-    //   PUSH RBP   <-- RBP points here
-    //   PUSH CSRs
-    //   ~~~~~~~    <-- possible stack realignment (non-win64)
-    //   ...
-    //   STACK OBJECTS
-    //   ...        <-- RSP after prologue points here
-    //   ~~~~~~~    <-- possible stack realignment (win64)
-    //
-    // if (hasVarSizedObjects()):
-    //   ...        <-- "base pointer" (ESI/RBX) points here
-    //   DYNAMIC ALLOCAS
-    //   ...        <-- RSP points here
-    //
-    // Case 1: In the simple case of no stack realignment and no dynamic
-    // allocas, both "fixed" stack objects (arguments and CSRs) are addressable
-    // with fixed offsets from RSP.
-    //
-    // Case 2: In the case of stack realignment with no dynamic allocas, fixed
-    // stack objects are addressed with RBP and regular stack objects with RSP.
-    //
-    // Case 3: In the case of dynamic allocas and stack realignment, RSP is used
-    // to address stack arguments for outgoing calls and nothing else. The "base
-    // pointer" points to local variables, and RBP points to fixed objects.
-    //
-    // In cases 2 and 3, we can only answer for non-fixed stack objects, and the
-    // answer we give is relative to the SP after the prologue, and not the
-    // SP in the middle of the function.
-
-    assert((!MFI->isFixedObjectIndex(FI) || !TRI->needsStackRealignment(MF) ||
-            STI.isTargetWin64()) &&
-           "offset from fixed object to SP is not static");
-
-    // We don't handle tail calls, and shouldn't be seeing them either.
-    int TailCallReturnAddrDelta =
-        MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta();
-    assert(!(TailCallReturnAddrDelta < 0) && "we don't handle this case!");
-#endif
-  }
+  // LLVM arranges the stack as follows:
+  //   ...
+  //   ARG2
+  //   ARG1
+  //   RETADDR
+  //   PUSH RBP   <-- RBP points here
+  //   PUSH CSRs
+  //   ~~~~~~~    <-- possible stack realignment (non-win64)
+  //   ...
+  //   STACK OBJECTS
+  //   ...        <-- RSP after prologue points here
+  //   ~~~~~~~    <-- possible stack realignment (win64)
+  //
+  // if (hasVarSizedObjects()):
+  //   ...        <-- "base pointer" (ESI/RBX) points here
+  //   DYNAMIC ALLOCAS
+  //   ...        <-- RSP points here
+  //
+  // Case 1: In the simple case of no stack realignment and no dynamic
+  // allocas, both "fixed" stack objects (arguments and CSRs) are addressable
+  // with fixed offsets from RSP.
+  //
+  // Case 2: In the case of stack realignment with no dynamic allocas, fixed
+  // stack objects are addressed with RBP and regular stack objects with RSP.
+  //
+  // Case 3: In the case of dynamic allocas and stack realignment, RSP is used
+  // to address stack arguments for outgoing calls and nothing else. The "base
+  // pointer" points to local variables, and RBP points to fixed objects.
+  //
+  // In cases 2 and 3, we can only answer for non-fixed stack objects, and the
+  // answer we give is relative to the SP after the prologue, and not the
+  // SP in the middle of the function.
+
+  if (MFI->isFixedObjectIndex(FI) && TRI->needsStackRealignment(MF) &&
+      !STI.isTargetWin64())
+    return None;
+
+  // If !hasReservedCallFrame the function might have SP adjustement in the
+  // body.  So, even though the offset is statically known, it depends on where
+  // we are in the function.
+  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
+  if (!AllowSPAdjustment && !TFI->hasReservedCallFrame(MF))
+    return None;
+  // We don't handle tail calls, and shouldn't be seeing them either.
+  int TailCallReturnAddrDelta =
+      MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta();
+  assert(!(TailCallReturnAddrDelta < 0) && "we don't handle this case!");
 
   // Fill in FrameReg output argument.
   FrameReg = TRI->getStackRegister();
index 9ec3966af3343b060edde88393749d84be88bdd3..192ec0e8b5f2c5fbdf2b9b05f06b559b868ae0b2 100644 (file)
@@ -100,8 +100,10 @@ public:
   int getFrameIndexReference(const MachineFunction &MF, int FI,
                              unsigned &FrameReg) const override;
 
-  int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
-                                   unsigned &FrameReg) const override;
+  Optional<int>
+  getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI,
+                               unsigned &FrameReg,
+                               bool AllowSPAdjustment) const override;
 
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
index 4a9cf3b156decb81aedb6f776f6effae3faf3cf1..1fb73ea252ee08f5cc7b9d5199bb3c3fad8a53b3 100644 (file)
@@ -146,3 +146,16 @@ try.cont:
 }
 
 declare i32 @__CxxFrameHandler3(...)
+
+define void @f_0(i64 %n) {
+  ; CHECK-LABEL: _f_0
+  %s = alloca i64
+  %vl = alloca i64, i64 %n
+  ; Check that the stackmap does not reference %s through
+  ; SP since the offset is not static because of %vl.
+  ; STACKMAPS: Loc 3: Direct 6
+  call void @g_0(i64* %vl) [ "deopt"(i64* %s) ]
+  ret void
+}
+
+declare void @g_0(i64* %vl)