diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86FrameLowering.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 121 |
1 files changed, 78 insertions, 43 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index a15db03..50c56c9 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -223,6 +223,8 @@ flagsNeedToBePreservedBeforeTheTerminators(const MachineBasicBlock &MBB) { return false; } +constexpr int64_t MaxSPChunk = (1LL << 31) - 1; + /// emitSPUpdate - Emit a series of instructions to increment / decrement the /// stack pointer by a constant value. void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB, @@ -242,7 +244,7 @@ void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB, return; } - uint64_t Chunk = (1LL << 31) - 1; + uint64_t Chunk = MaxSPChunk; MachineFunction &MF = *MBB.getParent(); const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); @@ -391,12 +393,15 @@ MachineInstrBuilder X86FrameLowering::BuildStackAdjustment( return MI; } -int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - bool doMergeWithPrevious) const { +template <typename FoundT, typename CalcT> +int64_t X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + FoundT FoundStackAdjust, + CalcT CalcNewOffset, + bool doMergeWithPrevious) const { if ((doMergeWithPrevious && MBBI == MBB.begin()) || (!doMergeWithPrevious && MBBI == MBB.end())) - return 0; + return CalcNewOffset(0); MachineBasicBlock::iterator PI = doMergeWithPrevious ? std::prev(MBBI) : MBBI; @@ -415,27 +420,38 @@ int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, if (doMergeWithPrevious && PI != MBB.begin() && PI->isCFIInstruction()) PI = std::prev(PI); - unsigned Opc = PI->getOpcode(); - int Offset = 0; - - if ((Opc == X86::ADD64ri32 || Opc == X86::ADD32ri) && - PI->getOperand(0).getReg() == StackPtr) { - assert(PI->getOperand(1).getReg() == StackPtr); - Offset = PI->getOperand(2).getImm(); - } else if ((Opc == X86::LEA32r || Opc == X86::LEA64_32r) && - PI->getOperand(0).getReg() == StackPtr && - PI->getOperand(1).getReg() == StackPtr && - PI->getOperand(2).getImm() == 1 && - PI->getOperand(3).getReg() == X86::NoRegister && - PI->getOperand(5).getReg() == X86::NoRegister) { - // For LEAs we have: def = lea SP, FI, noreg, Offset, noreg. - Offset = PI->getOperand(4).getImm(); - } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB32ri) && - PI->getOperand(0).getReg() == StackPtr) { - assert(PI->getOperand(1).getReg() == StackPtr); - Offset = -PI->getOperand(2).getImm(); - } else - return 0; + int64_t Offset = 0; + for (;;) { + unsigned Opc = PI->getOpcode(); + + if ((Opc == X86::ADD64ri32 || Opc == X86::ADD32ri) && + PI->getOperand(0).getReg() == StackPtr) { + assert(PI->getOperand(1).getReg() == StackPtr); + Offset = PI->getOperand(2).getImm(); + } else if ((Opc == X86::LEA32r || Opc == X86::LEA64_32r) && + PI->getOperand(0).getReg() == StackPtr && + PI->getOperand(1).getReg() == StackPtr && + PI->getOperand(2).getImm() == 1 && + PI->getOperand(3).getReg() == X86::NoRegister && + PI->getOperand(5).getReg() == X86::NoRegister) { + // For LEAs we have: def = lea SP, FI, noreg, Offset, noreg. + Offset = PI->getOperand(4).getImm(); + } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB32ri) && + PI->getOperand(0).getReg() == StackPtr) { + assert(PI->getOperand(1).getReg() == StackPtr); + Offset = -PI->getOperand(2).getImm(); + } else + return CalcNewOffset(0); + + FoundStackAdjust(PI, Offset); + if (std::abs((int64_t)CalcNewOffset(Offset)) < MaxSPChunk) + break; + + if (doMergeWithPrevious ? (PI == MBB.begin()) : (PI == MBB.end())) + return CalcNewOffset(0); + + PI = doMergeWithPrevious ? std::prev(PI) : std::next(PI); + } PI = MBB.erase(PI); if (PI != MBB.end() && PI->isCFIInstruction()) { @@ -448,7 +464,16 @@ int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, if (!doMergeWithPrevious) MBBI = skipDebugInstructionsForward(PI, MBB.end()); - return Offset; + return CalcNewOffset(Offset); +} + +int64_t X86FrameLowering::mergeSPAdd(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + int64_t AddOffset, + bool doMergeWithPrevious) const { + return mergeSPUpdates( + MBB, MBBI, [AddOffset](int64_t Offset) { return AddOffset + Offset; }, + doMergeWithPrevious); } void X86FrameLowering::BuildCFI(MachineBasicBlock &MBB, @@ -1975,8 +2000,10 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // If there is an SUB32ri of ESP immediately before this instruction, merge // the two. This can be the case when tail call elimination is enabled and - // the callee has more arguments then the caller. - NumBytes -= mergeSPUpdates(MBB, MBBI, true); + // the callee has more arguments than the caller. + NumBytes = mergeSPUpdates( + MBB, MBBI, [NumBytes](int64_t Offset) { return NumBytes - Offset; }, + true); // Adjust stack pointer: ESP -= numbytes. @@ -2457,7 +2484,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (HasFP) { if (X86FI->hasSwiftAsyncContext()) { // Discard the context. - int Offset = 16 + mergeSPUpdates(MBB, MBBI, true); + int64_t Offset = mergeSPAdd(MBB, MBBI, 16, true); emitSPUpdate(MBB, MBBI, DL, Offset, /*InEpilogue*/ true); } // Pop EBP. @@ -2531,7 +2558,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // If there is an ADD32ri or SUB32ri of ESP immediately before this // instruction, merge the two instructions. if (NumBytes || MFI.hasVarSizedObjects()) - NumBytes += mergeSPUpdates(MBB, MBBI, true); + NumBytes = mergeSPAdd(MBB, MBBI, NumBytes, true); // If dynamic alloca is used, then reset esp to point to the last callee-saved // slot before popping them off! Same applies for the case, when stack was @@ -2612,11 +2639,11 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (Terminator == MBB.end() || !isTailCallOpcode(Terminator->getOpcode())) { // Add the return addr area delta back since we are not tail calling. - int Offset = -1 * X86FI->getTCReturnAddrDelta(); + int64_t Offset = -1 * X86FI->getTCReturnAddrDelta(); assert(Offset >= 0 && "TCDelta should never be positive"); if (Offset) { // Check for possible merge with preceding ADD instruction. - Offset += mergeSPUpdates(MBB, Terminator, true); + Offset = mergeSPAdd(MBB, Terminator, Offset, true); emitSPUpdate(MBB, Terminator, DL, Offset, /*InEpilogue=*/true); } } @@ -3814,13 +3841,24 @@ MachineBasicBlock::iterator X86FrameLowering::eliminateCallFramePseudoInstr( // Add Amount to SP to destroy a frame, or subtract to setup. int64_t StackAdjustment = isDestroy ? Amount : -Amount; + int64_t CfaAdjustment = StackAdjustment; if (StackAdjustment) { // Merge with any previous or following adjustment instruction. Note: the // instructions merged with here do not have CFI, so their stack - // adjustments do not feed into CfaAdjustment. - StackAdjustment += mergeSPUpdates(MBB, InsertPos, true); - StackAdjustment += mergeSPUpdates(MBB, InsertPos, false); + // adjustments do not feed into CfaAdjustment + + auto CalcCfaAdjust = [&CfaAdjustment](MachineBasicBlock::iterator PI, + int64_t Offset) { + CfaAdjustment += Offset; + }; + auto CalcNewOffset = [&StackAdjustment](int64_t Offset) { + return StackAdjustment + Offset; + }; + StackAdjustment = + mergeSPUpdates(MBB, InsertPos, CalcCfaAdjust, CalcNewOffset, true); + StackAdjustment = + mergeSPUpdates(MBB, InsertPos, CalcCfaAdjust, CalcNewOffset, false); if (StackAdjustment) { if (!(F.hasMinSize() && @@ -3830,7 +3868,7 @@ MachineBasicBlock::iterator X86FrameLowering::eliminateCallFramePseudoInstr( } } - if (DwarfCFI && !hasFP(MF)) { + if (DwarfCFI && !hasFP(MF) && CfaAdjustment) { // If we don't have FP, but need to generate unwind information, // we need to set the correct CFA offset after the stack adjustment. // How much we adjust the CFA offset depends on whether we're emitting @@ -3838,14 +3876,11 @@ MachineBasicBlock::iterator X86FrameLowering::eliminateCallFramePseudoInstr( // offset to be correct at each call site, while for debugging we want // it to be more precise. - int64_t CfaAdjustment = -StackAdjustment; // TODO: When not using precise CFA, we also need to adjust for the // InternalAmt here. - if (CfaAdjustment) { - BuildCFI( - MBB, InsertPos, DL, - MCCFIInstruction::createAdjustCfaOffset(nullptr, CfaAdjustment)); - } + BuildCFI( + MBB, InsertPos, DL, + MCCFIInstruction::createAdjustCfaOffset(nullptr, -CfaAdjustment)); } return I; |