Index: include/llvm/Target/TargetFrameLowering.h =================================================================== --- include/llvm/Target/TargetFrameLowering.h +++ include/llvm/Target/TargetFrameLowering.h @@ -273,14 +273,13 @@ report_fatal_error("WinEH not implemented for this target"); } - /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog - /// code insertion to eliminate call frame setup and destroy pseudo - /// instructions (but only if the Target is using them). It is responsible - /// for eliminating these instructions, replacing them with concrete - /// instructions. This method need only be implemented if using call frame - /// setup/destroy pseudo instructions. - /// - virtual void + /// This method is called during prolog/epilog code insertion to eliminate + /// call frame setup and destroy pseudo instructions (but only if the Target + /// is using them). It is responsible for eliminating these instructions, + /// replacing them with concrete instructions. This method need only be + /// implemented if using call frame setup/destroy pseudo instructions. + /// Returns an iterator pointing to the instruction after the replaced one. + virtual MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -891,15 +891,7 @@ InsideCallSequence = (I->getOpcode() == FrameSetupOpcode); SPAdj += TII.getSPAdjust(I); - MachineBasicBlock::iterator PrevI = BB->end(); - if (I != BB->begin()) PrevI = std::prev(I); - TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); - - // Visit the instructions created by eliminateCallFramePseudoInstr(). - if (PrevI == BB->end()) - I = BB->begin(); // The replaced instr was the first in the block. - else - I = std::next(PrevI); + I = TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); continue; } Index: lib/Target/AArch64/AArch64FrameLowering.h =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.h +++ lib/Target/AArch64/AArch64FrameLowering.h @@ -27,9 +27,9 @@ void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -153,7 +153,7 @@ return !MF.getFrameInfo()->hasVarSizedObjects(); } -void AArch64FrameLowering::eliminateCallFramePseudoInstr( +MachineBasicBlock::iterator AArch64FrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const AArch64InstrInfo *TII = @@ -196,7 +196,7 @@ emitFrameOffset(MBB, I, DL, AArch64::SP, AArch64::SP, -CalleePopAmount, TII); } - MBB.erase(I); + return MBB.erase(I); } void AArch64FrameLowering::emitCalleeSavedFrameMoves( Index: lib/Target/ARM/ARMFrameLowering.h =================================================================== --- lib/Target/ARM/ARMFrameLowering.h +++ lib/Target/ARM/ARMFrameLowering.h @@ -74,7 +74,7 @@ bool(*Func)(unsigned, bool), unsigned NumAlignedDPRCS2Regs) const; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override; Index: lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- lib/Target/ARM/ARMFrameLowering.cpp +++ lib/Target/ARM/ARMFrameLowering.cpp @@ -1726,10 +1726,9 @@ } } - -void ARMFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { +MachineBasicBlock::iterator ARMFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { const ARMBaseInstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); if (!hasReservedCallFrame(MF)) { @@ -1769,7 +1768,7 @@ } } } - MBB.erase(I); + return MBB.erase(I); } /// Get the minimum constant for ARM that is greater than or equal to the Index: lib/Target/ARM/Thumb1FrameLowering.h =================================================================== --- lib/Target/ARM/Thumb1FrameLowering.h +++ lib/Target/ARM/Thumb1FrameLowering.h @@ -41,7 +41,7 @@ bool hasReservedCallFrame(const MachineFunction &MF) const override; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override; Index: lib/Target/ARM/Thumb1FrameLowering.cpp =================================================================== --- lib/Target/ARM/Thumb1FrameLowering.cpp +++ lib/Target/ARM/Thumb1FrameLowering.cpp @@ -49,7 +49,7 @@ } -void Thumb1FrameLowering:: +MachineBasicBlock::iterator Thumb1FrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const Thumb1InstrInfo &TII = @@ -80,7 +80,7 @@ } } } - MBB.erase(I); + return MBB.erase(I); } void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, Index: lib/Target/BPF/BPFFrameLowering.h =================================================================== --- lib/Target/BPF/BPFFrameLowering.h +++ lib/Target/BPF/BPFFrameLowering.h @@ -31,10 +31,10 @@ void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override { - MBB.erase(MI); + return MBB.erase(MI); } }; } Index: lib/Target/Hexagon/HexagonFrameLowering.h =================================================================== --- lib/Target/Hexagon/HexagonFrameLowering.h +++ lib/Target/Hexagon/HexagonFrameLowering.h @@ -42,8 +42,9 @@ return true; } - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS = nullptr) const override; void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, Index: lib/Target/Hexagon/HexagonFrameLowering.cpp =================================================================== --- lib/Target/Hexagon/HexagonFrameLowering.cpp +++ lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -1060,15 +1060,15 @@ return true; } - -void HexagonFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { +MachineBasicBlock::iterator HexagonFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { MachineInstr &MI = *I; unsigned Opc = MI.getOpcode(); (void)Opc; // Silence compiler warning. assert((Opc == Hexagon::ADJCALLSTACKDOWN || Opc == Hexagon::ADJCALLSTACKUP) && "Cannot handle this call frame pseudo instruction"); - MBB.erase(I); + return MBB.erase(I); } Index: lib/Target/Lanai/LanaiFrameLowering.h =================================================================== --- lib/Target/Lanai/LanaiFrameLowering.h +++ lib/Target/Lanai/LanaiFrameLowering.h @@ -42,7 +42,7 @@ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; Index: lib/Target/Lanai/LanaiFrameLowering.cpp =================================================================== --- lib/Target/Lanai/LanaiFrameLowering.cpp +++ lib/Target/Lanai/LanaiFrameLowering.cpp @@ -139,11 +139,11 @@ replaceAdjDynAllocPseudo(MF); } -void LanaiFrameLowering::eliminateCallFramePseudoInstr( +MachineBasicBlock::iterator LanaiFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { // Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. - MBB.erase(I); + return MBB.erase(I); } // The function epilogue should not depend on the current stack pointer! Index: lib/Target/MSP430/MSP430FrameLowering.h =================================================================== --- lib/Target/MSP430/MSP430FrameLowering.h +++ lib/Target/MSP430/MSP430FrameLowering.h @@ -30,9 +30,9 @@ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Index: lib/Target/MSP430/MSP430FrameLowering.cpp =================================================================== --- lib/Target/MSP430/MSP430FrameLowering.cpp +++ lib/Target/MSP430/MSP430FrameLowering.cpp @@ -224,9 +224,9 @@ return true; } -void MSP430FrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { +MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { const MSP430InstrInfo &TII = *static_cast(MF.getSubtarget().getInstrInfo()); unsigned StackAlign = getStackAlignment(); @@ -283,7 +283,7 @@ } } - MBB.erase(I); + return MBB.erase(I); } void Index: lib/Target/Mips/MipsFrameLowering.h =================================================================== --- lib/Target/Mips/MipsFrameLowering.h +++ lib/Target/Mips/MipsFrameLowering.h @@ -36,7 +36,7 @@ bool isFPCloseToIncomingSP() const override { return false; } - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; Index: lib/Target/Mips/MipsFrameLowering.cpp =================================================================== --- lib/Target/Mips/MipsFrameLowering.cpp +++ lib/Target/Mips/MipsFrameLowering.cpp @@ -143,7 +143,7 @@ } // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -void MipsFrameLowering:: +MachineBasicBlock::iterator MipsFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { unsigned SP = STI.getABI().IsN64() ? Mips::SP_64 : Mips::SP; @@ -156,5 +156,5 @@ STI.getInstrInfo()->adjustStackPtr(SP, Amount, MBB, I); } - MBB.erase(I); + return MBB.erase(I); } Index: lib/Target/NVPTX/NVPTXFrameLowering.h =================================================================== --- lib/Target/NVPTX/NVPTXFrameLowering.h +++ lib/Target/NVPTX/NVPTXFrameLowering.h @@ -26,7 +26,7 @@ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; }; Index: lib/Target/NVPTX/NVPTXFrameLowering.cpp =================================================================== --- lib/Target/NVPTX/NVPTXFrameLowering.cpp +++ lib/Target/NVPTX/NVPTXFrameLowering.cpp @@ -70,10 +70,10 @@ // This function eliminates ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions -void NVPTXFrameLowering::eliminateCallFramePseudoInstr( +MachineBasicBlock::iterator NVPTXFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { // Simply discard ADJCALLSTACKDOWN, // ADJCALLSTACKUP instructions. - MBB.erase(I); + return MBB.erase(I); } Index: lib/Target/PowerPC/PPCFrameLowering.h =================================================================== --- lib/Target/PowerPC/PPCFrameLowering.h +++ lib/Target/PowerPC/PPCFrameLowering.h @@ -93,9 +93,9 @@ const std::vector &CSI, const TargetRegisterInfo *TRI) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Index: lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCFrameLowering.cpp +++ lib/Target/PowerPC/PPCFrameLowering.cpp @@ -1770,7 +1770,7 @@ .addReg(MoveReg, getKillRegState(true))); } -void PPCFrameLowering:: +MachineBasicBlock::iterator PPCFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); @@ -1807,7 +1807,7 @@ } } // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. - MBB.erase(I); + return MBB.erase(I); } bool Index: lib/Target/Sparc/SparcFrameLowering.h =================================================================== --- lib/Target/Sparc/SparcFrameLowering.h +++ lib/Target/Sparc/SparcFrameLowering.h @@ -29,7 +29,7 @@ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; Index: lib/Target/Sparc/SparcFrameLowering.cpp =================================================================== --- lib/Target/Sparc/SparcFrameLowering.cpp +++ lib/Target/Sparc/SparcFrameLowering.cpp @@ -183,7 +183,7 @@ } } -void SparcFrameLowering:: +MachineBasicBlock::iterator SparcFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { if (!hasReservedCallFrame(MF)) { @@ -195,7 +195,7 @@ if (Size) emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); } - MBB.erase(I); + return MBB.erase(I); } Index: lib/Target/SystemZ/SystemZFrameLowering.h =================================================================== --- lib/Target/SystemZ/SystemZFrameLowering.h +++ lib/Target/SystemZ/SystemZFrameLowering.h @@ -46,10 +46,9 @@ int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const - override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override; // Return the number of bytes in the callee-allocated part of the frame. uint64_t getAllocatedStackSize(const MachineFunction &MF) const; Index: lib/Target/SystemZ/SystemZFrameLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZFrameLowering.cpp +++ lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -511,7 +511,7 @@ return true; } -void SystemZFrameLowering:: +MachineBasicBlock::iterator SystemZFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { @@ -520,7 +520,7 @@ case SystemZ::ADJCALLSTACKUP: assert(hasReservedCallFrame(MF) && "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); - MBB.erase(MI); + return MBB.erase(MI); break; default: Index: lib/Target/WebAssembly/WebAssemblyFrameLowering.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyFrameLowering.h +++ lib/Target/WebAssembly/WebAssemblyFrameLowering.h @@ -34,7 +34,7 @@ /*TransientStackAlignment=*/16, /*StackRealignable=*/true) {} - void eliminateCallFramePseudoInstr( + MachineBasicBlock::iterator eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; Index: lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -100,7 +100,8 @@ MF.getInfo()->stackifyVReg(SPAddr); } -void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( +MachineBasicBlock::iterator +WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { assert(!I->getOperand(0).getImm() && hasFP(MF) && @@ -111,7 +112,7 @@ DebugLoc DL = I->getDebugLoc(); writeSPToMemory(WebAssembly::SP32, MF, MBB, I, I, DL); } - MBB.erase(I); + return MBB.erase(I); } void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, Index: lib/Target/WebAssembly/WebAssemblyPEI.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyPEI.cpp +++ lib/Target/WebAssembly/WebAssemblyPEI.cpp @@ -877,16 +877,7 @@ I->getOpcode() == FrameDestroyOpcode) { InsideCallSequence = (I->getOpcode() == FrameSetupOpcode); SPAdj += TII.getSPAdjust(I); - - MachineBasicBlock::iterator PrevI = BB->end(); - if (I != BB->begin()) PrevI = std::prev(I); - TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); - - // Visit the instructions created by eliminateCallFramePseudoInstr(). - if (PrevI == BB->end()) - I = BB->begin(); // The replaced instr was the first in the block. - else - I = std::next(PrevI); + I = TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); continue; } Index: lib/Target/X86/X86FrameLowering.h =================================================================== --- lib/Target/X86/X86FrameLowering.h +++ lib/Target/X86/X86FrameLowering.h @@ -103,9 +103,9 @@ int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, unsigned &FrameReg) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const override; + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override; unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -2477,7 +2477,7 @@ return true; } -void X86FrameLowering:: +MachineBasicBlock::iterator X86FrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { bool reserveCallFrame = hasReservedCallFrame(MF); @@ -2521,7 +2521,7 @@ MCCFIInstruction::createGnuArgsSize(nullptr, Amount)); if (Amount == 0) - return; + return I; // Factor out the amount that gets handled inside the sequence // (Pushes of argument for frame setup, callee pops for frame destroy) @@ -2534,13 +2534,22 @@ BuildCFI(MBB, I, DL, MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt)); - if (Amount) { - // Add Amount to SP to destroy a frame, and subtract to setup. - int Offset = isDestroy ? Amount : -Amount; + // Add Amount to SP to destroy a frame, or subtract to setup. + int64_t StackAdjustment = isDestroy ? Amount : -Amount; - if (!(Fn->optForMinSize() && - adjustStackWithPops(MBB, I, DL, Offset))) - BuildStackAdjustment(MBB, I, DL, Offset, /*InEpilogue=*/false); + if (StackAdjustment) { + // Merge with any previous or following adjustment instruction. + StackAdjustment += mergeSPUpdates(MBB, I, true); + StackAdjustment += mergeSPUpdates(MBB, I, false); + + if (!StackAdjustment) { + // This and the merged instruction canceled out each other. + return I; + } + + if (!(Fn->optForMinSize() && + adjustStackWithPops(MBB, I, DL, StackAdjustment))) + BuildStackAdjustment(MBB, I, DL, StackAdjustment, /*InEpilogue=*/false); } if (DwarfCFI && !hasFP(MF)) { @@ -2550,18 +2559,16 @@ // CFI only for EH purposes or for debugging. EH only requires the CFA // offset to be correct at each call site, while for debugging we want // it to be more precise. - int CFAOffset = Amount; + // TODO: When not using precise CFA, we also need to adjust for the // InternalAmt here. - - if (CFAOffset) { - CFAOffset = isDestroy ? -CFAOffset : CFAOffset; - BuildCFI(MBB, I, DL, - MCCFIInstruction::createAdjustCfaOffset(nullptr, CFAOffset)); + if (StackAdjustment) { + BuildCFI(MBB, I, DL, MCCFIInstruction::createAdjustCfaOffset( + nullptr, -StackAdjustment)); } } - return; + return I; } if (isDestroy && InternalAmt) { @@ -2571,11 +2578,14 @@ // We are not tracking the stack pointer adjustment by the callee, so make // sure we restore the stack pointer immediately after the call, there may // be spill code inserted between the CALL and ADJCALLSTACKUP instructions. + MachineBasicBlock::iterator CI = I; MachineBasicBlock::iterator B = MBB.begin(); - while (I != B && !std::prev(I)->isCall()) + while (CI != B && !std::prev(I)->isCall()) --I; - BuildStackAdjustment(MBB, I, DL, -InternalAmt, /*InEpilogue=*/false); + BuildStackAdjustment(MBB, CI, DL, -InternalAmt, /*InEpilogue=*/false); } + + return I; } bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { Index: lib/Target/XCore/XCoreFrameLowering.h =================================================================== --- lib/Target/XCore/XCoreFrameLowering.h +++ lib/Target/XCore/XCoreFrameLowering.h @@ -41,8 +41,8 @@ const std::vector &CSI, const TargetRegisterInfo *TRI) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; bool hasFP(const MachineFunction &MF) const override; Index: lib/Target/XCore/XCoreFrameLowering.cpp =================================================================== --- lib/Target/XCore/XCoreFrameLowering.cpp +++ lib/Target/XCore/XCoreFrameLowering.cpp @@ -482,9 +482,9 @@ // This function eliminates ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions -void XCoreFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { +MachineBasicBlock::iterator XCoreFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { const XCoreInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); if (!hasReservedCallFrame(MF)) { // Turn the adjcallstackdown instruction into 'extsp ' and the @@ -528,7 +528,7 @@ } } - MBB.erase(I); + return MBB.erase(I); } void XCoreFrameLowering::determineCalleeSaves(MachineFunction &MF, Index: test/CodeGen/X86/2006-05-02-InstrSched1.ll =================================================================== --- test/CodeGen/X86/2006-05-02-InstrSched1.ll +++ test/CodeGen/X86/2006-05-02-InstrSched1.ll @@ -1,6 +1,6 @@ ; REQUIRES: asserts ; RUN: llc < %s -mtriple=i686-unknown-linux -relocation-model=static -stats 2>&1 | \ -; RUN: grep asm-printer | grep 15 +; RUN: grep asm-printer | grep 14 ; ; It's possible to schedule this in 14 instructions by avoiding ; callee-save registers, but the scheduler isn't currently that Index: test/CodeGen/X86/fold-push.ll =================================================================== --- test/CodeGen/X86/fold-push.ll +++ test/CodeGen/X86/fold-push.ll @@ -14,7 +14,7 @@ ; SLM: movl (%esp), [[RELOAD:%e..]] ; SLM-NEXT: pushl [[RELOAD]] ; CHECK: calll -; CHECK-NEXT: addl $4, %esp +; CHECK-NEXT: addl $8, %esp %c = add i32 %a, %b call void @foo(i32 %c) call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"() Index: test/CodeGen/X86/force-align-stack-alloca.ll =================================================================== --- test/CodeGen/X86/force-align-stack-alloca.ll +++ test/CodeGen/X86/force-align-stack-alloca.ll @@ -32,15 +32,21 @@ ; CHECK: movl %{{...}}, %esp ; CHECK-NOT: {{[^ ,]*}}, %esp ; -; Next we set up the memset call, and then undo it. +; Next we set up the memset call. ; CHECK: subl $20, %esp ; CHECK-NOT: {{[^ ,]*}}, %esp +; CHECK: pushl +; CHECK: pushl +; CHECK: pushl ; CHECK: calll memset -; CHECK-NEXT: addl $32, %esp +; +; Deallocating 32 bytes of outgoing call frame for memset and +; allocating 28 bytes for calling f yields a 4-byte adjustment: +; CHECK-NEXT: addl $4, %esp ; CHECK-NOT: {{[^ ,]*}}, %esp ; -; Next we set up the call to 'f'. -; CHECK: subl $28, %esp +; And move on to call 'f', and then restore the stack. +; CHECK: pushl ; CHECK-NOT: {{[^ ,]*}}, %esp ; CHECK: calll f ; CHECK-NEXT: addl $32, %esp Index: test/CodeGen/X86/localescape.ll =================================================================== --- test/CodeGen/X86/localescape.ll +++ test/CodeGen/X86/localescape.ll @@ -137,6 +137,5 @@ ; X86: movl $13, (%esp) ; X86: pushl $0 ; X86: calll _print_framealloc_from_fp -; X86: addl $4, %esp -; X86: addl $8, %esp +; X86: addl $12, %esp ; X86: retl Index: test/CodeGen/X86/memset-2.ll =================================================================== --- test/CodeGen/X86/memset-2.ll +++ test/CodeGen/X86/memset-2.ll @@ -5,7 +5,7 @@ define fastcc void @t1() nounwind { ; CHECK-LABEL: t1: -; CHECK: subl $12, %esp +; CHECK: subl $16, %esp ; CHECK: pushl $188 ; CHECK-NEXT: pushl $0 ; CHECK-NEXT: pushl $0 Index: test/CodeGen/X86/movtopush.ll =================================================================== --- test/CodeGen/X86/movtopush.ll +++ test/CodeGen/X86/movtopush.ll @@ -2,6 +2,7 @@ ; RUN: llc < %s -mtriple=i686-windows -no-x86-call-frame-opt | FileCheck %s -check-prefix=NOPUSH ; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64 ; RUN: llc < %s -mtriple=i686-windows -stackrealign -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED +; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX %class.Class = type { i32 } %struct.s = type { i64 } @@ -223,8 +224,7 @@ ; NORMAL-NEXT: pushl $2 ; NORMAL-NEXT: pushl $1 ; NORMAL-NEXT: call -; NORMAL-NEXT: addl $16, %esp -; NORMAL-NEXT: subl $20, %esp +; NORMAL-NEXT: subl $4, %esp ; NORMAL-NEXT: movl 20(%esp), [[E1:%e..]] ; NORMAL-NEXT: movl 24(%esp), [[E2:%e..]] ; NORMAL-NEXT: movl [[E2]], 4(%esp) @@ -261,7 +261,7 @@ ; NORMAL-NEXT: pushl $2 ; NORMAL-NEXT: pushl $1 ; NORMAL-NEXT: calll *16(%esp) -; NORMAL-NEXT: addl $16, %esp +; NORMAL-NEXT: addl $24, %esp define void @test10() optsize { %stack_fptr = alloca void (i32, i32, i32, i32)* store void (i32, i32, i32, i32)* @good, void (i32, i32, i32, i32)** %stack_fptr @@ -314,8 +314,7 @@ ; NORMAL-NEXT: pushl $2 ; NORMAL-NEXT: pushl $1 ; NORMAL-NEXT: calll _good -; NORMAL-NEXT: addl $16, %esp -; NORMAL-NEXT: subl $20, %esp +; NORMAL-NEXT: subl $4, %esp ; NORMAL: movl $8, 16(%esp) ; NORMAL-NEXT: movl $7, 12(%esp) ; NORMAL-NEXT: movl $6, 8(%esp) @@ -358,3 +357,27 @@ call void @good(i32 %val1, i32 %val2, i32 %val3, i32 %add) ret i32* %ptr3 } + +; Make sure to fold adjacent stack adjustments. +; LINUX-LABEL: pr27140: +; LINUX: subl $12, %esp +; LINUX: .cfi_def_cfa_offset 16 +; LINUX-NOT: sub +; LINUX: pushl $4 +; LINUX: .cfi_adjust_cfa_offset 4 +; LINUX: pushl $3 +; LINUX: .cfi_adjust_cfa_offset 4 +; LINUX: pushl $2 +; LINUX: .cfi_adjust_cfa_offset 4 +; LINUX: pushl $1 +; LINUX: .cfi_adjust_cfa_offset 4 +; LINUX: calll good +; LINUX: addl $28, %esp +; LINUX: .cfi_adjust_cfa_offset -28 +; LINUX-NOT: add +; LINUX: retl +define void @pr27140() optsize { +entry: + tail call void @good(i32 1, i32 2, i32 3, i32 4) + ret void +} Index: test/CodeGen/X86/push-cfi-debug.ll =================================================================== --- test/CodeGen/X86/push-cfi-debug.ll +++ test/CodeGen/X86/push-cfi-debug.ll @@ -23,8 +23,8 @@ ; CHECK: .cfi_adjust_cfa_offset 4 ; CHECK: calll stdfoo ; CHECK: .cfi_adjust_cfa_offset -8 -; CHECK: addl $8, %esp -; CHECK: .cfi_adjust_cfa_offset -8 +; CHECK: addl $20, %esp +; CHECK: .cfi_adjust_cfa_offset -20 define void @test1() #0 !dbg !4 { entry: tail call void @foo(i32 1, i32 2) #1, !dbg !10 Index: test/CodeGen/X86/push-cfi.ll =================================================================== --- test/CodeGen/X86/push-cfi.ll +++ test/CodeGen/X86/push-cfi.ll @@ -82,8 +82,8 @@ ; LINUX-NEXT: Ltmp{{[0-9]+}}: ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 ; LINUX-NEXT: call -; LINUX-NEXT: addl $16, %esp -; LINUX: .cfi_adjust_cfa_offset -16 +; LINUX-NEXT: addl $28, %esp +; LINUX: .cfi_adjust_cfa_offset -28 ; DARWIN-NOT: .cfi_escape ; DARWIN-NOT: pushl define void @test2_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {