Index: include/llvm/Target/TargetFrameLowering.h =================================================================== --- include/llvm/Target/TargetFrameLowering.h +++ include/llvm/Target/TargetFrameLowering.h @@ -250,11 +250,11 @@ /// RBP on x86. This is generally used for emitting statepoint or EH tables /// that use offsets from RSP. /// TODO: This should really be a parameterizable choice. - virtual int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, - unsigned &FrameReg) const { + virtual Optional getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { // default to calling normal version, we override this on x86 only llvm_unreachable("unimplemented for non-x86"); - return 0; + return Optional(); } /// This method determines which of the registers reported by Index: lib/CodeGen/AsmPrinter/WinException.cpp =================================================================== --- lib/CodeGen/AsmPrinter/WinException.cpp +++ lib/CodeGen/AsmPrinter/WinException.cpp @@ -301,8 +301,10 @@ const WinEHFuncInfo &FuncInfo) { const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering(); unsigned UnusedReg; - if (Asm->MAI->usesWindowsCFI()) - return TFI.getFrameIndexReferenceFromSP(*Asm->MF, FrameIndex, UnusedReg); + if (Asm->MAI->usesWindowsCFI()) { + return TFI.getFrameIndexReferenceFromSP(*Asm->MF, FrameIndex, + UnusedReg).getValue(); + } // 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: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -1094,9 +1094,20 @@ "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); + // if !hasReservedCallFrame the call site might have SP adjustement around it + // and we don't take them into account. So, even though the offset is statically + // known, fallback to another register. + if (!SPOffset.hasValue() || !TFI->hasReservedCallFrame(Fn)) { + refOffset = TFI->getFrameIndexReference(Fn, MI->getOperand(i).getIndex(), + Reg); + } else { + refOffset = SPOffset.getValue(); + } Offset.setImm(Offset.getImm() + refOffset); MI->getOperand(i).ChangeToRegister(Reg, false /*isDef*/); Index: lib/Target/X86/X86FrameLowering.h =================================================================== --- lib/Target/X86/X86FrameLowering.h +++ lib/Target/X86/X86FrameLowering.h @@ -100,8 +100,8 @@ int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override; - int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, - unsigned &FrameReg) const override; + Optional getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -1436,7 +1436,8 @@ // 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).getValue(); assert(Offset >= 0); return static_cast(Offset); } @@ -1722,58 +1723,54 @@ } // Simplified from getFrameIndexReference keeping only StackPointer cases -int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, - int FI, - unsigned &FrameReg) const { +Optional X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, + int FI, unsigned &FrameReg) 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()->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 Optional(); } + // We don't handle tail calls, and shouldn't be seeing them either. + int TailCallReturnAddrDelta = + MF.getInfo()->getTCReturnAddrDelta(); + assert(!(TailCallReturnAddrDelta < 0) && "we don't handle this case!"); + // Fill in FrameReg output argument. FrameReg = TRI->getStackRegister(); @@ -1805,8 +1802,7 @@ // Get the Offset from the StackPointer int Offset = MFI->getObjectOffset(FI) - getOffsetOfLocalArea(); - - return Offset + StackSize; + return Optional(Offset + StackSize); } bool X86FrameLowering::assignCalleeSavedSpillSlots( Index: test/CodeGen/X86/statepoint-nosp.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/statepoint-nosp.ll @@ -0,0 +1,15 @@ +; RUN: llc -debug-only=stackmaps < %s 2>&1 | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @f(i64 %n) { + %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 + ; CHECK: Loc 3: Direct 6 + call void @g(i64* %vl) [ "deopt"(i64* %s) ] + ret void +} + +declare void @g(i64* %vl)