Index: llvm/trunk/include/llvm/Target/TargetFrameLowering.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetFrameLowering.h +++ llvm/trunk/include/llvm/Target/TargetFrameLowering.h @@ -249,12 +249,16 @@ /// 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 + 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: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp @@ -302,7 +302,8 @@ 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: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp +++ llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp @@ -1094,9 +1094,16 @@ "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: llvm/trunk/lib/Target/X86/X86FrameLowering.h =================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.h +++ llvm/trunk/lib/Target/X86/X86FrameLowering.h @@ -100,8 +100,10 @@ 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, + bool AllowSPAdjustment) const override; MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Index: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp +++ llvm/trunk/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, + /*AllowSPAdjustment*/ true); assert(Offset >= 0); return static_cast(Offset); } @@ -1722,57 +1723,60 @@ } // 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, + 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()->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()->getTCReturnAddrDelta(); + assert(!(TailCallReturnAddrDelta < 0) && "we don't handle this case!"); // Fill in FrameReg output argument. FrameReg = TRI->getStackRegister(); Index: llvm/trunk/test/CodeGen/X86/deopt-bundles.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/deopt-bundles.ll +++ llvm/trunk/test/CodeGen/X86/deopt-bundles.ll @@ -146,3 +146,16 @@ } 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)