mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Don't force SP-relative addressing for statepoints
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 llvm-svn: 272756
This commit is contained in:
parent
dd6dd22a91
commit
4e8fc79b92
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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*/);
|
||||
|
@ -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.
|
||||
// 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");
|
||||
if (MFI->isFixedObjectIndex(FI) && TRI->needsStackRealignment(MF) &&
|
||||
!STI.isTargetWin64())
|
||||
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!");
|
||||
#endif
|
||||
}
|
||||
// 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();
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user