15f613dfdSUlrich Weigand //===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===// 25f613dfdSUlrich Weigand // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f613dfdSUlrich Weigand // 75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===// 85f613dfdSUlrich Weigand 95f613dfdSUlrich Weigand #include "SystemZFrameLowering.h" 105f613dfdSUlrich Weigand #include "SystemZCallingConv.h" 115f613dfdSUlrich Weigand #include "SystemZInstrBuilder.h" 12f1bd22dfSEric Christopher #include "SystemZInstrInfo.h" 135f613dfdSUlrich Weigand #include "SystemZMachineFunctionInfo.h" 14f1bd22dfSEric Christopher #include "SystemZRegisterInfo.h" 15d913448bSEric Christopher #include "SystemZSubtarget.h" 165f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineModuleInfo.h" 175f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h" 185dd52f8cSRichard Sandiford #include "llvm/CodeGen/RegisterScavenging.h" 195f613dfdSUlrich Weigand #include "llvm/IR/Function.h" 20fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h" 215f613dfdSUlrich Weigand 225f613dfdSUlrich Weigand using namespace llvm; 235f613dfdSUlrich Weigand 24db39b4a2SRichard Sandiford namespace { 25a7d3f693SJonas Paulsson // The ABI-defined register save slots, relative to the CFA (i.e. 26023b5c1eSYusra Syeda // incoming stack pointer + SystemZMC::ELFCallFrameSize). 270a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = { 2861f5ba5cSJonas Paulsson { SystemZ::R2D, 0x10 }, 2961f5ba5cSJonas Paulsson { SystemZ::R3D, 0x18 }, 3061f5ba5cSJonas Paulsson { SystemZ::R4D, 0x20 }, 3161f5ba5cSJonas Paulsson { SystemZ::R5D, 0x28 }, 3261f5ba5cSJonas Paulsson { SystemZ::R6D, 0x30 }, 3361f5ba5cSJonas Paulsson { SystemZ::R7D, 0x38 }, 3461f5ba5cSJonas Paulsson { SystemZ::R8D, 0x40 }, 3561f5ba5cSJonas Paulsson { SystemZ::R9D, 0x48 }, 3661f5ba5cSJonas Paulsson { SystemZ::R10D, 0x50 }, 3761f5ba5cSJonas Paulsson { SystemZ::R11D, 0x58 }, 3861f5ba5cSJonas Paulsson { SystemZ::R12D, 0x60 }, 3961f5ba5cSJonas Paulsson { SystemZ::R13D, 0x68 }, 4061f5ba5cSJonas Paulsson { SystemZ::R14D, 0x70 }, 4161f5ba5cSJonas Paulsson { SystemZ::R15D, 0x78 }, 4261f5ba5cSJonas Paulsson { SystemZ::F0D, 0x80 }, 4361f5ba5cSJonas Paulsson { SystemZ::F2D, 0x88 }, 4461f5ba5cSJonas Paulsson { SystemZ::F4D, 0x90 }, 4561f5ba5cSJonas Paulsson { SystemZ::F6D, 0x98 } 465f613dfdSUlrich Weigand }; 470a950a2eSKai Nacke 480a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = { 490a950a2eSKai Nacke {SystemZ::R4D, 0x00}, {SystemZ::R5D, 0x08}, {SystemZ::R6D, 0x10}, 500a950a2eSKai Nacke {SystemZ::R7D, 0x18}, {SystemZ::R8D, 0x20}, {SystemZ::R9D, 0x28}, 510a950a2eSKai Nacke {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40}, 520a950a2eSKai Nacke {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}}; 53c231269fSRichard Sandiford } // end anonymous namespace 545f613dfdSUlrich Weigand 550782e55cSNeumann Hon SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl, 560782e55cSNeumann Hon int LAO, Align TransAl, 570782e55cSNeumann Hon bool StackReal) 580782e55cSNeumann Hon : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {} 59a7d3f693SJonas Paulsson 600782e55cSNeumann Hon std::unique_ptr<SystemZFrameLowering> 610782e55cSNeumann Hon SystemZFrameLowering::create(const SystemZSubtarget &STI) { 620782e55cSNeumann Hon if (STI.isTargetXPLINK64()) 630782e55cSNeumann Hon return std::make_unique<SystemZXPLINKFrameLowering>(); 640782e55cSNeumann Hon return std::make_unique<SystemZELFFrameLowering>(); 65db39b4a2SRichard Sandiford } 66db39b4a2SRichard Sandiford 670782e55cSNeumann Hon MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr( 680782e55cSNeumann Hon MachineFunction &MF, MachineBasicBlock &MBB, 690782e55cSNeumann Hon MachineBasicBlock::iterator MI) const { 700782e55cSNeumann Hon switch (MI->getOpcode()) { 710782e55cSNeumann Hon case SystemZ::ADJCALLSTACKDOWN: 720782e55cSNeumann Hon case SystemZ::ADJCALLSTACKUP: 730782e55cSNeumann Hon assert(hasReservedCallFrame(MF) && 740782e55cSNeumann Hon "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); 750782e55cSNeumann Hon return MBB.erase(MI); 760782e55cSNeumann Hon break; 770782e55cSNeumann Hon 780782e55cSNeumann Hon default: 790782e55cSNeumann Hon llvm_unreachable("Unexpected call frame instruction"); 800782e55cSNeumann Hon } 810782e55cSNeumann Hon } 820782e55cSNeumann Hon 830782e55cSNeumann Hon bool SystemZFrameLowering::hasReservedCallFrame( 840782e55cSNeumann Hon const MachineFunction &MF) const { 850782e55cSNeumann Hon // The ELF ABI requires us to allocate 160 bytes of stack space for the 860782e55cSNeumann Hon // callee, with any outgoing stack arguments being placed above that. It 870782e55cSNeumann Hon // seems better to make that area a permanent feature of the frame even if 880782e55cSNeumann Hon // we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes 890782e55cSNeumann Hon // of stack space for the register save area. 900782e55cSNeumann Hon return true; 910782e55cSNeumann Hon } 920782e55cSNeumann Hon 930782e55cSNeumann Hon bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots( 940782e55cSNeumann Hon MachineFunction &MF, const TargetRegisterInfo *TRI, 9561f5ba5cSJonas Paulsson std::vector<CalleeSavedInfo> &CSI) const { 9661f5ba5cSJonas Paulsson SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 9761f5ba5cSJonas Paulsson MachineFrameInfo &MFFrame = MF.getFrameInfo(); 9861f5ba5cSJonas Paulsson bool IsVarArg = MF.getFunction().isVarArg(); 9961f5ba5cSJonas Paulsson if (CSI.empty()) 10061f5ba5cSJonas Paulsson return true; // Early exit if no callee saved registers are modified! 10161f5ba5cSJonas Paulsson 10261f5ba5cSJonas Paulsson unsigned LowGPR = 0; 10361f5ba5cSJonas Paulsson unsigned HighGPR = SystemZ::R15D; 104023b5c1eSYusra Syeda int StartSPOffset = SystemZMC::ELFCallFrameSize; 10561f5ba5cSJonas Paulsson for (auto &CS : CSI) { 106d6b07348SJim Lin Register Reg = CS.getReg(); 10782879c29SJonas Paulsson int Offset = getRegSpillOffset(MF, Reg); 10861f5ba5cSJonas Paulsson if (Offset) { 10961f5ba5cSJonas Paulsson if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) { 11061f5ba5cSJonas Paulsson LowGPR = Reg; 11161f5ba5cSJonas Paulsson StartSPOffset = Offset; 11261f5ba5cSJonas Paulsson } 113023b5c1eSYusra Syeda Offset -= SystemZMC::ELFCallFrameSize; 11461f5ba5cSJonas Paulsson int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset); 11561f5ba5cSJonas Paulsson CS.setFrameIdx(FrameIdx); 11661f5ba5cSJonas Paulsson } else 11761f5ba5cSJonas Paulsson CS.setFrameIdx(INT32_MAX); 11861f5ba5cSJonas Paulsson } 11961f5ba5cSJonas Paulsson 12061f5ba5cSJonas Paulsson // Save the range of call-saved registers, for use by the 12161f5ba5cSJonas Paulsson // prologue/epilogue inserters. 12261f5ba5cSJonas Paulsson ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset); 12361f5ba5cSJonas Paulsson if (IsVarArg) { 12461f5ba5cSJonas Paulsson // Also save the GPR varargs, if any. R6D is call-saved, so would 12561f5ba5cSJonas Paulsson // already be included, but we also need to handle the call-clobbered 12661f5ba5cSJonas Paulsson // argument registers. 127d6b07348SJim Lin Register FirstGPR = ZFI->getVarArgsFirstGPR(); 128023b5c1eSYusra Syeda if (FirstGPR < SystemZ::ELFNumArgGPRs) { 129023b5c1eSYusra Syeda unsigned Reg = SystemZ::ELFArgGPRs[FirstGPR]; 13082879c29SJonas Paulsson int Offset = getRegSpillOffset(MF, Reg); 13161f5ba5cSJonas Paulsson if (StartSPOffset > Offset) { 13261f5ba5cSJonas Paulsson LowGPR = Reg; StartSPOffset = Offset; 13361f5ba5cSJonas Paulsson } 13461f5ba5cSJonas Paulsson } 13561f5ba5cSJonas Paulsson } 13661f5ba5cSJonas Paulsson ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset); 13761f5ba5cSJonas Paulsson 13861f5ba5cSJonas Paulsson // Create fixed stack objects for the remaining registers. 139023b5c1eSYusra Syeda int CurrOffset = -SystemZMC::ELFCallFrameSize; 14082879c29SJonas Paulsson if (usePackedStack(MF)) 14182879c29SJonas Paulsson CurrOffset += StartSPOffset; 14282879c29SJonas Paulsson 14361f5ba5cSJonas Paulsson for (auto &CS : CSI) { 14461f5ba5cSJonas Paulsson if (CS.getFrameIdx() != INT32_MAX) 14561f5ba5cSJonas Paulsson continue; 146d6b07348SJim Lin Register Reg = CS.getReg(); 14761f5ba5cSJonas Paulsson const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 14861f5ba5cSJonas Paulsson unsigned Size = TRI->getSpillSize(*RC); 14961f5ba5cSJonas Paulsson CurrOffset -= Size; 15061f5ba5cSJonas Paulsson assert(CurrOffset % 8 == 0 && 15161f5ba5cSJonas Paulsson "8-byte alignment required for for all register save slots"); 15261f5ba5cSJonas Paulsson int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset); 15361f5ba5cSJonas Paulsson CS.setFrameIdx(FrameIdx); 15461f5ba5cSJonas Paulsson } 15561f5ba5cSJonas Paulsson 15661f5ba5cSJonas Paulsson return true; 1575f613dfdSUlrich Weigand } 1585f613dfdSUlrich Weigand 1590782e55cSNeumann Hon void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF, 16002564865SMatthias Braun BitVector &SavedRegs, 1615f613dfdSUlrich Weigand RegScavenger *RS) const { 16202564865SMatthias Braun TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 16302564865SMatthias Braun 164941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 165fc6de428SEric Christopher const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 1665f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 1675f613dfdSUlrich Weigand SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 168f1caa283SMatthias Braun bool IsVarArg = MF.getFunction().isVarArg(); 1695f613dfdSUlrich Weigand 1705f613dfdSUlrich Weigand // va_start stores incoming FPR varargs in the normal way, but delegates 1715f613dfdSUlrich Weigand // the saving of incoming GPR varargs to spillCalleeSavedRegisters(). 1725f613dfdSUlrich Weigand // Record these pending uses, which typically include the call-saved 1735f613dfdSUlrich Weigand // argument register R6D. 1745f613dfdSUlrich Weigand if (IsVarArg) 175023b5c1eSYusra Syeda for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I) 176023b5c1eSYusra Syeda SavedRegs.set(SystemZ::ELFArgGPRs[I]); 1775f613dfdSUlrich Weigand 178234e5a80SMarcin Koscielnicki // If there are any landing pads, entering them will modify r6/r7. 179d0ee66c2SMatthias Braun if (!MF.getLandingPads().empty()) { 180234e5a80SMarcin Koscielnicki SavedRegs.set(SystemZ::R6D); 181234e5a80SMarcin Koscielnicki SavedRegs.set(SystemZ::R7D); 182234e5a80SMarcin Koscielnicki } 183234e5a80SMarcin Koscielnicki 1845f613dfdSUlrich Weigand // If the function requires a frame pointer, record that the hard 1855f613dfdSUlrich Weigand // frame pointer will be clobbered. 1865f613dfdSUlrich Weigand if (HasFP) 18702564865SMatthias Braun SavedRegs.set(SystemZ::R11D); 1885f613dfdSUlrich Weigand 1895f613dfdSUlrich Weigand // If the function calls other functions, record that the return 1905f613dfdSUlrich Weigand // address register will be clobbered. 191941a705bSMatthias Braun if (MFFrame.hasCalls()) 19202564865SMatthias Braun SavedRegs.set(SystemZ::R14D); 1935f613dfdSUlrich Weigand 1945f613dfdSUlrich Weigand // If we are saving GPRs other than the stack pointer, we might as well 1955f613dfdSUlrich Weigand // save and restore the stack pointer at the same time, via STMG and LMG. 1965f613dfdSUlrich Weigand // This allows the deallocation to be done by the LMG, rather than needing 1975f613dfdSUlrich Weigand // a separate %r15 addition. 198840beec2SCraig Topper const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); 1995f613dfdSUlrich Weigand for (unsigned I = 0; CSRegs[I]; ++I) { 2005f613dfdSUlrich Weigand unsigned Reg = CSRegs[I]; 20102564865SMatthias Braun if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) { 20202564865SMatthias Braun SavedRegs.set(SystemZ::R15D); 2035f613dfdSUlrich Weigand break; 2045f613dfdSUlrich Weigand } 2055f613dfdSUlrich Weigand } 2065f613dfdSUlrich Weigand } 2075f613dfdSUlrich Weigand 2080782e55cSNeumann Hon SystemZELFFrameLowering::SystemZELFFrameLowering() 2090782e55cSNeumann Hon : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0, 2100a950a2eSKai Nacke Align(8), /* StackRealignable */ false), 2110782e55cSNeumann Hon RegSpillOffsets(0) { 2120a950a2eSKai Nacke 2130782e55cSNeumann Hon // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not 2140782e55cSNeumann Hon // equal to the incoming stack pointer, but to incoming stack pointer plus 2150782e55cSNeumann Hon // 160. Instead of using a Local Area Offset, the Register save area will 2160782e55cSNeumann Hon // be occupied by fixed frame objects, and all offsets are actually 2170782e55cSNeumann Hon // relative to CFA. 2180782e55cSNeumann Hon 2190782e55cSNeumann Hon // Create a mapping from register number to save slot offset. 2200782e55cSNeumann Hon // These offsets are relative to the start of the register save area. 2210782e55cSNeumann Hon RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); 222*f15014ffSBenjamin Kramer for (unsigned I = 0, E = array_lengthof(ELFSpillOffsetTable); I != E; ++I) 2230a950a2eSKai Nacke RegSpillOffsets[ELFSpillOffsetTable[I].Reg] = ELFSpillOffsetTable[I].Offset; 2240782e55cSNeumann Hon } 2250782e55cSNeumann Hon 2265f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic 2275f613dfdSUlrich Weigand // block MBB. IsImplicit says whether this is an explicit operand to the 2285f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start 2295f613dfdSUlrich Weigand // and end registers. 2305f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, 2315f613dfdSUlrich Weigand unsigned GPR64, bool IsImplicit) { 232d913448bSEric Christopher const TargetRegisterInfo *RI = 233fc6de428SEric Christopher MBB.getParent()->getSubtarget().getRegisterInfo(); 2340c476111SDaniel Sanders Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32); 2355f613dfdSUlrich Weigand bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32); 2365f613dfdSUlrich Weigand if (!IsLive || !IsImplicit) { 2375f613dfdSUlrich Weigand MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive)); 2385f613dfdSUlrich Weigand if (!IsLive) 2395f613dfdSUlrich Weigand MBB.addLiveIn(GPR64); 2405f613dfdSUlrich Weigand } 2415f613dfdSUlrich Weigand } 2425f613dfdSUlrich Weigand 2430782e55cSNeumann Hon bool SystemZELFFrameLowering::spillCalleeSavedRegisters( 244e4230a9fSBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 245e4230a9fSBenjamin Kramer ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 2465f613dfdSUlrich Weigand if (CSI.empty()) 2475f613dfdSUlrich Weigand return false; 2485f613dfdSUlrich Weigand 2495f613dfdSUlrich Weigand MachineFunction &MF = *MBB.getParent(); 250fc6de428SEric Christopher const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 2515f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 252f1caa283SMatthias Braun bool IsVarArg = MF.getFunction().isVarArg(); 253057c5a6bSOleg Ranevskyy DebugLoc DL; 2545f613dfdSUlrich Weigand 2555f613dfdSUlrich Weigand // Save GPRs 25661f5ba5cSJonas Paulsson SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs(); 25761f5ba5cSJonas Paulsson if (SpillGPRs.LowGPR) { 25861f5ba5cSJonas Paulsson assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR && 25961f5ba5cSJonas Paulsson "Should be saving %r15 and something else"); 2605f613dfdSUlrich Weigand 2615f613dfdSUlrich Weigand // Build an STMG instruction. 2625f613dfdSUlrich Weigand MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); 2635f613dfdSUlrich Weigand 2645f613dfdSUlrich Weigand // Add the explicit register operands. 26561f5ba5cSJonas Paulsson addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false); 26661f5ba5cSJonas Paulsson addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false); 2675f613dfdSUlrich Weigand 2685f613dfdSUlrich Weigand // Add the address. 26961f5ba5cSJonas Paulsson MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset); 2705f613dfdSUlrich Weigand 2715f613dfdSUlrich Weigand // Make sure all call-saved GPRs are included as operands and are 2725f613dfdSUlrich Weigand // marked as live on entry. 273ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 274d6b07348SJim Lin Register Reg = I.getReg(); 2755f613dfdSUlrich Weigand if (SystemZ::GR64BitRegClass.contains(Reg)) 276f1bd22dfSEric Christopher addSavedGPR(MBB, MIB, Reg, true); 2775f613dfdSUlrich Weigand } 2785f613dfdSUlrich Weigand 2795f613dfdSUlrich Weigand // ...likewise GPR varargs. 2805f613dfdSUlrich Weigand if (IsVarArg) 281023b5c1eSYusra Syeda for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I) 282023b5c1eSYusra Syeda addSavedGPR(MBB, MIB, SystemZ::ELFArgGPRs[I], true); 2835f613dfdSUlrich Weigand } 2845f613dfdSUlrich Weigand 2858b19be46SUlrich Weigand // Save FPRs/VRs in the normal TargetInstrInfo way. 286ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 287d6b07348SJim Lin Register Reg = I.getReg(); 2885f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) { 2895f613dfdSUlrich Weigand MBB.addLiveIn(Reg); 290ea5421bdSKazu Hirata TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(), 2915f613dfdSUlrich Weigand &SystemZ::FP64BitRegClass, TRI); 2925f613dfdSUlrich Weigand } 2938b19be46SUlrich Weigand if (SystemZ::VR128BitRegClass.contains(Reg)) { 2948b19be46SUlrich Weigand MBB.addLiveIn(Reg); 295ea5421bdSKazu Hirata TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(), 2968b19be46SUlrich Weigand &SystemZ::VR128BitRegClass, TRI); 2978b19be46SUlrich Weigand } 2985f613dfdSUlrich Weigand } 2995f613dfdSUlrich Weigand 3005f613dfdSUlrich Weigand return true; 3015f613dfdSUlrich Weigand } 3025f613dfdSUlrich Weigand 3030782e55cSNeumann Hon bool SystemZELFFrameLowering::restoreCalleeSavedRegisters( 304186dd631SBenjamin Kramer MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 305186dd631SBenjamin Kramer MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 3065f613dfdSUlrich Weigand if (CSI.empty()) 3075f613dfdSUlrich Weigand return false; 3085f613dfdSUlrich Weigand 3095f613dfdSUlrich Weigand MachineFunction &MF = *MBB.getParent(); 310fc6de428SEric Christopher const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 3115f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 3125f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 3135f613dfdSUlrich Weigand DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 3145f613dfdSUlrich Weigand 3158b19be46SUlrich Weigand // Restore FPRs/VRs in the normal TargetInstrInfo way. 316ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 317d6b07348SJim Lin Register Reg = I.getReg(); 3185f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) 319ea5421bdSKazu Hirata TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(), 3205f613dfdSUlrich Weigand &SystemZ::FP64BitRegClass, TRI); 3218b19be46SUlrich Weigand if (SystemZ::VR128BitRegClass.contains(Reg)) 322ea5421bdSKazu Hirata TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(), 3238b19be46SUlrich Weigand &SystemZ::VR128BitRegClass, TRI); 3245f613dfdSUlrich Weigand } 3255f613dfdSUlrich Weigand 3265f613dfdSUlrich Weigand // Restore call-saved GPRs (but not call-clobbered varargs, which at 3275f613dfdSUlrich Weigand // this point might hold return values). 32861f5ba5cSJonas Paulsson SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs(); 32961f5ba5cSJonas Paulsson if (RestoreGPRs.LowGPR) { 3305f613dfdSUlrich Weigand // If we saved any of %r2-%r5 as varargs, we should also be saving 3315f613dfdSUlrich Weigand // and restoring %r6. If we're saving %r6 or above, we should be 3325f613dfdSUlrich Weigand // restoring it too. 33361f5ba5cSJonas Paulsson assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR && 33461f5ba5cSJonas Paulsson "Should be loading %r15 and something else"); 3355f613dfdSUlrich Weigand 3365f613dfdSUlrich Weigand // Build an LMG instruction. 3375f613dfdSUlrich Weigand MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); 3385f613dfdSUlrich Weigand 3395f613dfdSUlrich Weigand // Add the explicit register operands. 34061f5ba5cSJonas Paulsson MIB.addReg(RestoreGPRs.LowGPR, RegState::Define); 34161f5ba5cSJonas Paulsson MIB.addReg(RestoreGPRs.HighGPR, RegState::Define); 3425f613dfdSUlrich Weigand 3435f613dfdSUlrich Weigand // Add the address. 3445f613dfdSUlrich Weigand MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D); 34561f5ba5cSJonas Paulsson MIB.addImm(RestoreGPRs.GPROffset); 3465f613dfdSUlrich Weigand 3475f613dfdSUlrich Weigand // Do a second scan adding regs as being defined by instruction 348ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 349d6b07348SJim Lin Register Reg = I.getReg(); 35061f5ba5cSJonas Paulsson if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR && 351f0344826SJonas Paulsson SystemZ::GR64BitRegClass.contains(Reg)) 3525f613dfdSUlrich Weigand MIB.addReg(Reg, RegState::ImplicitDefine); 3535f613dfdSUlrich Weigand } 3545f613dfdSUlrich Weigand } 3555f613dfdSUlrich Weigand 3565f613dfdSUlrich Weigand return true; 3575f613dfdSUlrich Weigand } 3585f613dfdSUlrich Weigand 3590782e55cSNeumann Hon void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized( 3600782e55cSNeumann Hon MachineFunction &MF, RegScavenger *RS) const { 361941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 3621606755dSJonas Paulsson SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 3631606755dSJonas Paulsson MachineRegisterInfo *MRI = &MF.getRegInfo(); 36423762575SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 36561f5ba5cSJonas Paulsson 36623762575SJonas Paulsson if (!usePackedStack(MF) || BackChain) 36723762575SJonas Paulsson // Create the incoming register save area. 36861f5ba5cSJonas Paulsson getOrCreateFramePointerSaveIndex(MF); 36961f5ba5cSJonas Paulsson 370af98b748SUlrich Weigand // Get the size of our stack frame to be allocated ... 371af98b748SUlrich Weigand uint64_t StackSize = (MFFrame.estimateStackSize(MF) + 372023b5c1eSYusra Syeda SystemZMC::ELFCallFrameSize); 373af98b748SUlrich Weigand // ... and the maximum offset we may need to reach into the 374af98b748SUlrich Weigand // caller's frame to access the save area or stack arguments. 37561f5ba5cSJonas Paulsson int64_t MaxArgOffset = 0; 376af98b748SUlrich Weigand for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) 377af98b748SUlrich Weigand if (MFFrame.getObjectOffset(I) >= 0) { 37861f5ba5cSJonas Paulsson int64_t ArgOffset = MFFrame.getObjectOffset(I) + 379af98b748SUlrich Weigand MFFrame.getObjectSize(I); 380af98b748SUlrich Weigand MaxArgOffset = std::max(MaxArgOffset, ArgOffset); 381af98b748SUlrich Weigand } 382af98b748SUlrich Weigand 383af98b748SUlrich Weigand uint64_t MaxReach = StackSize + MaxArgOffset; 38423943229SRichard Sandiford if (!isUInt<12>(MaxReach)) { 38523943229SRichard Sandiford // We may need register scavenging slots if some parts of the frame 3865dd52f8cSRichard Sandiford // are outside the reach of an unsigned 12-bit displacement. 38723943229SRichard Sandiford // Create 2 for the case where both addresses in an MVC are 38823943229SRichard Sandiford // out of range. 38928de229bSGuillaume Chatelet RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); 39028de229bSGuillaume Chatelet RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false)); 39123943229SRichard Sandiford } 3921606755dSJonas Paulsson 3931606755dSJonas Paulsson // If R6 is used as an argument register it is still callee saved. If it in 3941606755dSJonas Paulsson // this case is not clobbered (and restored) it should never be marked as 3951606755dSJonas Paulsson // killed. 3961606755dSJonas Paulsson if (MF.front().isLiveIn(SystemZ::R6D) && 3971606755dSJonas Paulsson ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D) 3981606755dSJonas Paulsson for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D)) 3991606755dSJonas Paulsson MO.setIsKill(false); 4005dd52f8cSRichard Sandiford } 4015dd52f8cSRichard Sandiford 4025f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg. 4035f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB, 4042481f26aSMatt Arsenault MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, 4052481f26aSMatt Arsenault Register Reg, int64_t NumBytes, 4065f613dfdSUlrich Weigand const TargetInstrInfo *TII) { 4075f613dfdSUlrich Weigand while (NumBytes) { 4085f613dfdSUlrich Weigand unsigned Opcode; 4095f613dfdSUlrich Weigand int64_t ThisVal = NumBytes; 4105f613dfdSUlrich Weigand if (isInt<16>(NumBytes)) 4115f613dfdSUlrich Weigand Opcode = SystemZ::AGHI; 4125f613dfdSUlrich Weigand else { 4135f613dfdSUlrich Weigand Opcode = SystemZ::AGFI; 4145f613dfdSUlrich Weigand // Make sure we maintain 8-byte stack alignment. 415fffd56ecSAlexey Samsonov int64_t MinVal = -uint64_t(1) << 31; 4165f613dfdSUlrich Weigand int64_t MaxVal = (int64_t(1) << 31) - 8; 4175f613dfdSUlrich Weigand if (ThisVal < MinVal) 4185f613dfdSUlrich Weigand ThisVal = MinVal; 4195f613dfdSUlrich Weigand else if (ThisVal > MaxVal) 4205f613dfdSUlrich Weigand ThisVal = MaxVal; 4215f613dfdSUlrich Weigand } 4225f613dfdSUlrich Weigand MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg) 4235f613dfdSUlrich Weigand .addReg(Reg).addImm(ThisVal); 42414a44495SRichard Sandiford // The CC implicit def is dead. 4255f613dfdSUlrich Weigand MI->getOperand(3).setIsDead(); 4265f613dfdSUlrich Weigand NumBytes -= ThisVal; 4275f613dfdSUlrich Weigand } 4285f613dfdSUlrich Weigand } 4295f613dfdSUlrich Weigand 430515bfc66SJonas Paulsson // Add CFI for the new CFA offset. 431515bfc66SJonas Paulsson static void buildCFAOffs(MachineBasicBlock &MBB, 432515bfc66SJonas Paulsson MachineBasicBlock::iterator MBBI, 433515bfc66SJonas Paulsson const DebugLoc &DL, int Offset, 434515bfc66SJonas Paulsson const SystemZInstrInfo *ZII) { 435515bfc66SJonas Paulsson unsigned CFIIndex = MBB.getParent()->addFrameInst( 436515bfc66SJonas Paulsson MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset)); 437515bfc66SJonas Paulsson BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 438515bfc66SJonas Paulsson .addCFIIndex(CFIIndex); 439515bfc66SJonas Paulsson } 440515bfc66SJonas Paulsson 441515bfc66SJonas Paulsson // Add CFI for the new frame location. 442515bfc66SJonas Paulsson static void buildDefCFAReg(MachineBasicBlock &MBB, 443515bfc66SJonas Paulsson MachineBasicBlock::iterator MBBI, 444515bfc66SJonas Paulsson const DebugLoc &DL, unsigned Reg, 445515bfc66SJonas Paulsson const SystemZInstrInfo *ZII) { 446515bfc66SJonas Paulsson MachineFunction &MF = *MBB.getParent(); 447515bfc66SJonas Paulsson MachineModuleInfo &MMI = MF.getMMI(); 448515bfc66SJonas Paulsson const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 449515bfc66SJonas Paulsson unsigned RegNum = MRI->getDwarfRegNum(Reg, true); 450515bfc66SJonas Paulsson unsigned CFIIndex = MF.addFrameInst( 451515bfc66SJonas Paulsson MCCFIInstruction::createDefCfaRegister(nullptr, RegNum)); 452515bfc66SJonas Paulsson BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 453515bfc66SJonas Paulsson .addCFIIndex(CFIIndex); 454515bfc66SJonas Paulsson } 455515bfc66SJonas Paulsson 4560782e55cSNeumann Hon void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF, 45761b305edSQuentin Colombet MachineBasicBlock &MBB) const { 45861b305edSQuentin Colombet assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 459515bfc66SJonas Paulsson const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>(); 460515bfc66SJonas Paulsson const SystemZTargetLowering &TLI = *STI.getTargetLowering(); 461941a705bSMatthias Braun MachineFrameInfo &MFFrame = MF.getFrameInfo(); 462515bfc66SJonas Paulsson auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo()); 4635f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 4645f613dfdSUlrich Weigand MachineBasicBlock::iterator MBBI = MBB.begin(); 4655f613dfdSUlrich Weigand MachineModuleInfo &MMI = MF.getMMI(); 466bc07a890SBill Wendling const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); 467941a705bSMatthias Braun const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 4685f613dfdSUlrich Weigand bool HasFP = hasFP(MF); 469057c5a6bSOleg Ranevskyy 47022f94291SUlrich Weigand // In GHC calling convention C stack space, including the ABI-defined 47122f94291SUlrich Weigand // 160-byte base area, is (de)allocated by GHC itself. This stack space may 47222f94291SUlrich Weigand // be used by LLVM as spill slots for the tail recursive GHC functions. Thus 47322f94291SUlrich Weigand // do not allocate stack space here, too. 47422f94291SUlrich Weigand if (MF.getFunction().getCallingConv() == CallingConv::GHC) { 47522f94291SUlrich Weigand if (MFFrame.getStackSize() > 2048 * sizeof(long)) { 47622f94291SUlrich Weigand report_fatal_error( 47722f94291SUlrich Weigand "Pre allocated stack space for GHC function is too small"); 47822f94291SUlrich Weigand } 47922f94291SUlrich Weigand if (HasFP) { 48022f94291SUlrich Weigand report_fatal_error( 48122f94291SUlrich Weigand "In GHC calling convention a frame pointer is not supported"); 48222f94291SUlrich Weigand } 483023b5c1eSYusra Syeda MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::ELFCallFrameSize); 48422f94291SUlrich Weigand return; 48522f94291SUlrich Weigand } 48622f94291SUlrich Weigand 487057c5a6bSOleg Ranevskyy // Debug location must be unknown since the first debug location is used 488057c5a6bSOleg Ranevskyy // to determine the end of the prologue. 489057c5a6bSOleg Ranevskyy DebugLoc DL; 4905f613dfdSUlrich Weigand 4915f613dfdSUlrich Weigand // The current offset of the stack pointer from the CFA. 492023b5c1eSYusra Syeda int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP; 4935f613dfdSUlrich Weigand 49461f5ba5cSJonas Paulsson if (ZFI->getSpillGPRRegs().LowGPR) { 4955f613dfdSUlrich Weigand // Skip over the GPR saves. 4965f613dfdSUlrich Weigand if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG) 4975f613dfdSUlrich Weigand ++MBBI; 4985f613dfdSUlrich Weigand else 4995f613dfdSUlrich Weigand llvm_unreachable("Couldn't skip over GPR saves"); 5005f613dfdSUlrich Weigand 5015f613dfdSUlrich Weigand // Add CFI for the GPR saves. 50228c111ecSRichard Sandiford for (auto &Save : CSI) { 503d6b07348SJim Lin Register Reg = Save.getReg(); 5045f613dfdSUlrich Weigand if (SystemZ::GR64BitRegClass.contains(Reg)) { 50561f5ba5cSJonas Paulsson int FI = Save.getFrameIdx(); 50661f5ba5cSJonas Paulsson int64_t Offset = MFFrame.getObjectOffset(FI); 507f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 508b1f25f1bSRafael Espindola nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); 509b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 510b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 5115f613dfdSUlrich Weigand } 5125f613dfdSUlrich Weigand } 5135f613dfdSUlrich Weigand } 5145f613dfdSUlrich Weigand 51532063888SUlrich Weigand uint64_t StackSize = MFFrame.getStackSize(); 51632063888SUlrich Weigand // We need to allocate the ABI-defined 160-byte base area whenever 51732063888SUlrich Weigand // we allocate stack space for our own use and whenever we call another 51832063888SUlrich Weigand // function. 51961f5ba5cSJonas Paulsson bool HasStackObject = false; 52061f5ba5cSJonas Paulsson for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i) 52161f5ba5cSJonas Paulsson if (!MFFrame.isDeadObjectIndex(i)) { 52261f5ba5cSJonas Paulsson HasStackObject = true; 52361f5ba5cSJonas Paulsson break; 52432063888SUlrich Weigand } 52561f5ba5cSJonas Paulsson if (HasStackObject || MFFrame.hasCalls()) 526023b5c1eSYusra Syeda StackSize += SystemZMC::ELFCallFrameSize; 52761f5ba5cSJonas Paulsson // Don't allocate the incoming reg save area. 528023b5c1eSYusra Syeda StackSize = StackSize > SystemZMC::ELFCallFrameSize 529023b5c1eSYusra Syeda ? StackSize - SystemZMC::ELFCallFrameSize 53061f5ba5cSJonas Paulsson : 0; 53161f5ba5cSJonas Paulsson MFFrame.setStackSize(StackSize); 53232063888SUlrich Weigand 5335f613dfdSUlrich Weigand if (StackSize) { 5345f613dfdSUlrich Weigand // Allocate StackSize bytes. 5355f613dfdSUlrich Weigand int64_t Delta = -int64_t(StackSize); 536515bfc66SJonas Paulsson const unsigned ProbeSize = TLI.getStackProbeSize(MF); 537515bfc66SJonas Paulsson bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset && 538515bfc66SJonas Paulsson (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize); 539515bfc66SJonas Paulsson if (!FreeProbe && 540515bfc66SJonas Paulsson MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) { 541515bfc66SJonas Paulsson // Stack probing may involve looping, but splitting the prologue block 542515bfc66SJonas Paulsson // is not possible at this point since it would invalidate the 543515bfc66SJonas Paulsson // SaveBlocks / RestoreBlocks sets of PEI in the single block function 544515bfc66SJonas Paulsson // case. Build a pseudo to be handled later by inlineStackProbe(). 545515bfc66SJonas Paulsson BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC)) 546515bfc66SJonas Paulsson .addImm(StackSize); 547515bfc66SJonas Paulsson } 548515bfc66SJonas Paulsson else { 54942f628c8SJonas Paulsson bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); 55042f628c8SJonas Paulsson // If we need backchain, save current stack pointer. R1 is free at 55142f628c8SJonas Paulsson // this point. 55242f628c8SJonas Paulsson if (StoreBackchain) 55342f628c8SJonas Paulsson BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR)) 55442f628c8SJonas Paulsson .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D); 5555f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); 556515bfc66SJonas Paulsson buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII); 557653b9769SJonas Paulsson if (StoreBackchain) 558ad1482c6SMarcin Koscielnicki BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG)) 55982879c29SJonas Paulsson .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D) 560653b9769SJonas Paulsson .addImm(getBackchainOffset(MF)).addReg(0); 5615f613dfdSUlrich Weigand } 56242f628c8SJonas Paulsson SPOffsetFromCFA += Delta; 56342f628c8SJonas Paulsson } 5645f613dfdSUlrich Weigand 5655f613dfdSUlrich Weigand if (HasFP) { 5665f613dfdSUlrich Weigand // Copy the base of the frame to R11. 5675f613dfdSUlrich Weigand BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D) 5685f613dfdSUlrich Weigand .addReg(SystemZ::R15D); 5695f613dfdSUlrich Weigand 5705f613dfdSUlrich Weigand // Add CFI for the new frame location. 571515bfc66SJonas Paulsson buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII); 5725f613dfdSUlrich Weigand 5735f613dfdSUlrich Weigand // Mark the FramePtr as live at the beginning of every block except 5745f613dfdSUlrich Weigand // the entry block. (We'll have marked R11 as live on entry when 5755f613dfdSUlrich Weigand // saving the GPRs.) 576cfc74024SKazu Hirata for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF)) 577cfc74024SKazu Hirata MBBJ.addLiveIn(SystemZ::R11D); 5785f613dfdSUlrich Weigand } 5795f613dfdSUlrich Weigand 5808b19be46SUlrich Weigand // Skip over the FPR/VR saves. 581b1f25f1bSRafael Espindola SmallVector<unsigned, 8> CFIIndexes; 58228c111ecSRichard Sandiford for (auto &Save : CSI) { 583d6b07348SJim Lin Register Reg = Save.getReg(); 5845f613dfdSUlrich Weigand if (SystemZ::FP64BitRegClass.contains(Reg)) { 5855f613dfdSUlrich Weigand if (MBBI != MBB.end() && 5865f613dfdSUlrich Weigand (MBBI->getOpcode() == SystemZ::STD || 5875f613dfdSUlrich Weigand MBBI->getOpcode() == SystemZ::STDY)) 5885f613dfdSUlrich Weigand ++MBBI; 5895f613dfdSUlrich Weigand else 5905f613dfdSUlrich Weigand llvm_unreachable("Couldn't skip over FPR save"); 5918b19be46SUlrich Weigand } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 5928b19be46SUlrich Weigand if (MBBI != MBB.end() && 5938b19be46SUlrich Weigand MBBI->getOpcode() == SystemZ::VST) 5948b19be46SUlrich Weigand ++MBBI; 5958b19be46SUlrich Weigand else 5968b19be46SUlrich Weigand llvm_unreachable("Couldn't skip over VR save"); 5978b19be46SUlrich Weigand } else 5988b19be46SUlrich Weigand continue; 5995f613dfdSUlrich Weigand 6005f613dfdSUlrich Weigand // Add CFI for the this save. 60128c111ecSRichard Sandiford unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); 6022481f26aSMatt Arsenault Register IgnoredFrameReg; 6035567bafeSJames Y Knight int64_t Offset = 604d57bba7cSSander de Smalen getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg) 605d57bba7cSSander de Smalen .getFixed(); 6065567bafeSJames Y Knight 607f23ef437SMatthias Braun unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 608b1f25f1bSRafael Espindola nullptr, DwarfReg, SPOffsetFromCFA + Offset)); 609b1f25f1bSRafael Espindola CFIIndexes.push_back(CFIIndex); 6105f613dfdSUlrich Weigand } 6118b19be46SUlrich Weigand // Complete the CFI for the FPR/VR saves, modelling them as taking effect 6125f613dfdSUlrich Weigand // after the last save. 613b1f25f1bSRafael Espindola for (auto CFIIndex : CFIIndexes) { 614b1f25f1bSRafael Espindola BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) 615b1f25f1bSRafael Espindola .addCFIIndex(CFIIndex); 616b1f25f1bSRafael Espindola } 6175f613dfdSUlrich Weigand } 6185f613dfdSUlrich Weigand 6190782e55cSNeumann Hon void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF, 6205f613dfdSUlrich Weigand MachineBasicBlock &MBB) const { 6215f613dfdSUlrich Weigand MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 622fc6de428SEric Christopher auto *ZII = 623fc6de428SEric Christopher static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 6245f613dfdSUlrich Weigand SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 62532063888SUlrich Weigand MachineFrameInfo &MFFrame = MF.getFrameInfo(); 6265f613dfdSUlrich Weigand 6270782e55cSNeumann Hon // See SystemZELFFrameLowering::emitPrologue 62822f94291SUlrich Weigand if (MF.getFunction().getCallingConv() == CallingConv::GHC) 62922f94291SUlrich Weigand return; 63022f94291SUlrich Weigand 6315f613dfdSUlrich Weigand // Skip the return instruction. 632709bda66SRichard Sandiford assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks"); 6335f613dfdSUlrich Weigand 63432063888SUlrich Weigand uint64_t StackSize = MFFrame.getStackSize(); 63561f5ba5cSJonas Paulsson if (ZFI->getRestoreGPRRegs().LowGPR) { 6365f613dfdSUlrich Weigand --MBBI; 6375f613dfdSUlrich Weigand unsigned Opcode = MBBI->getOpcode(); 6385f613dfdSUlrich Weigand if (Opcode != SystemZ::LMG) 6395f613dfdSUlrich Weigand llvm_unreachable("Expected to see callee-save register restore code"); 6405f613dfdSUlrich Weigand 6415f613dfdSUlrich Weigand unsigned AddrOpNo = 2; 6425f613dfdSUlrich Weigand DebugLoc DL = MBBI->getDebugLoc(); 6435f613dfdSUlrich Weigand uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm(); 6445f613dfdSUlrich Weigand unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 6455f613dfdSUlrich Weigand 6465f613dfdSUlrich Weigand // If the offset is too large, use the largest stack-aligned offset 6475f613dfdSUlrich Weigand // and add the rest to the base register (the stack or frame pointer). 6485f613dfdSUlrich Weigand if (!NewOpcode) { 6495f613dfdSUlrich Weigand uint64_t NumBytes = Offset - 0x7fff8; 6505f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(), 6515f613dfdSUlrich Weigand NumBytes, ZII); 6525f613dfdSUlrich Weigand Offset -= NumBytes; 6535f613dfdSUlrich Weigand NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset); 6545f613dfdSUlrich Weigand assert(NewOpcode && "No restore instruction available"); 6555f613dfdSUlrich Weigand } 6565f613dfdSUlrich Weigand 6575f613dfdSUlrich Weigand MBBI->setDesc(ZII->get(NewOpcode)); 6585f613dfdSUlrich Weigand MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset); 6595f613dfdSUlrich Weigand } else if (StackSize) { 6605f613dfdSUlrich Weigand DebugLoc DL = MBBI->getDebugLoc(); 6615f613dfdSUlrich Weigand emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII); 6625f613dfdSUlrich Weigand } 6635f613dfdSUlrich Weigand } 6645f613dfdSUlrich Weigand 6650782e55cSNeumann Hon void SystemZELFFrameLowering::inlineStackProbe( 6660782e55cSNeumann Hon MachineFunction &MF, MachineBasicBlock &PrologMBB) const { 667515bfc66SJonas Paulsson auto *ZII = 668515bfc66SJonas Paulsson static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo()); 669515bfc66SJonas Paulsson const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>(); 670515bfc66SJonas Paulsson const SystemZTargetLowering &TLI = *STI.getTargetLowering(); 671515bfc66SJonas Paulsson 672515bfc66SJonas Paulsson MachineInstr *StackAllocMI = nullptr; 673515bfc66SJonas Paulsson for (MachineInstr &MI : PrologMBB) 674515bfc66SJonas Paulsson if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) { 675515bfc66SJonas Paulsson StackAllocMI = &MI; 676515bfc66SJonas Paulsson break; 677515bfc66SJonas Paulsson } 678515bfc66SJonas Paulsson if (StackAllocMI == nullptr) 679515bfc66SJonas Paulsson return; 680515bfc66SJonas Paulsson uint64_t StackSize = StackAllocMI->getOperand(0).getImm(); 681515bfc66SJonas Paulsson const unsigned ProbeSize = TLI.getStackProbeSize(MF); 682515bfc66SJonas Paulsson uint64_t NumFullBlocks = StackSize / ProbeSize; 683515bfc66SJonas Paulsson uint64_t Residual = StackSize % ProbeSize; 684023b5c1eSYusra Syeda int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP; 685515bfc66SJonas Paulsson MachineBasicBlock *MBB = &PrologMBB; 686515bfc66SJonas Paulsson MachineBasicBlock::iterator MBBI = StackAllocMI; 687515bfc66SJonas Paulsson const DebugLoc DL = StackAllocMI->getDebugLoc(); 688515bfc66SJonas Paulsson 689515bfc66SJonas Paulsson // Allocate a block of Size bytes on the stack and probe it. 690515bfc66SJonas Paulsson auto allocateAndProbe = [&](MachineBasicBlock &InsMBB, 691515bfc66SJonas Paulsson MachineBasicBlock::iterator InsPt, unsigned Size, 692515bfc66SJonas Paulsson bool EmitCFI) -> void { 693515bfc66SJonas Paulsson emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII); 694515bfc66SJonas Paulsson if (EmitCFI) { 695515bfc66SJonas Paulsson SPOffsetFromCFA -= Size; 696515bfc66SJonas Paulsson buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII); 697515bfc66SJonas Paulsson } 698515bfc66SJonas Paulsson // Probe by means of a volatile compare. 699515bfc66SJonas Paulsson MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(), 700515bfc66SJonas Paulsson MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1)); 701515bfc66SJonas Paulsson BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG)) 702515bfc66SJonas Paulsson .addReg(SystemZ::R0D, RegState::Undef) 703515bfc66SJonas Paulsson .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0) 704515bfc66SJonas Paulsson .addMemOperand(MMO); 705515bfc66SJonas Paulsson }; 706515bfc66SJonas Paulsson 70742f628c8SJonas Paulsson bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); 70842f628c8SJonas Paulsson if (StoreBackchain) 70942f628c8SJonas Paulsson BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR)) 71042f628c8SJonas Paulsson .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D); 71142f628c8SJonas Paulsson 71242f628c8SJonas Paulsson MachineBasicBlock *DoneMBB = nullptr; 71342f628c8SJonas Paulsson MachineBasicBlock *LoopMBB = nullptr; 714515bfc66SJonas Paulsson if (NumFullBlocks < 3) { 715515bfc66SJonas Paulsson // Emit unrolled probe statements. 716515bfc66SJonas Paulsson for (unsigned int i = 0; i < NumFullBlocks; i++) 717515bfc66SJonas Paulsson allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/); 718515bfc66SJonas Paulsson } else { 719515bfc66SJonas Paulsson // Emit a loop probing the pages. 720515bfc66SJonas Paulsson uint64_t LoopAlloc = ProbeSize * NumFullBlocks; 721515bfc66SJonas Paulsson SPOffsetFromCFA -= LoopAlloc; 722515bfc66SJonas Paulsson 72342f628c8SJonas Paulsson // Use R0D to hold the exit value. 72442f628c8SJonas Paulsson BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D) 725515bfc66SJonas Paulsson .addReg(SystemZ::R15D); 72642f628c8SJonas Paulsson buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII); 72742f628c8SJonas Paulsson emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII); 728023b5c1eSYusra Syeda buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::ELFCallFrameSize + LoopAlloc), 729515bfc66SJonas Paulsson ZII); 730515bfc66SJonas Paulsson 73142f628c8SJonas Paulsson DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB); 73242f628c8SJonas Paulsson LoopMBB = SystemZ::emitBlockAfter(MBB); 733515bfc66SJonas Paulsson MBB->addSuccessor(LoopMBB); 734515bfc66SJonas Paulsson LoopMBB->addSuccessor(LoopMBB); 735515bfc66SJonas Paulsson LoopMBB->addSuccessor(DoneMBB); 736515bfc66SJonas Paulsson 737515bfc66SJonas Paulsson MBB = LoopMBB; 738515bfc66SJonas Paulsson allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/); 739515bfc66SJonas Paulsson BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR)) 74042f628c8SJonas Paulsson .addReg(SystemZ::R15D).addReg(SystemZ::R0D); 741515bfc66SJonas Paulsson BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC)) 742515bfc66SJonas Paulsson .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB); 743515bfc66SJonas Paulsson 744515bfc66SJonas Paulsson MBB = DoneMBB; 745515bfc66SJonas Paulsson MBBI = DoneMBB->begin(); 746515bfc66SJonas Paulsson buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII); 747515bfc66SJonas Paulsson } 748515bfc66SJonas Paulsson 749515bfc66SJonas Paulsson if (Residual) 750515bfc66SJonas Paulsson allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/); 751515bfc66SJonas Paulsson 752653b9769SJonas Paulsson if (StoreBackchain) 75342f628c8SJonas Paulsson BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG)) 75442f628c8SJonas Paulsson .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D) 755653b9769SJonas Paulsson .addImm(getBackchainOffset(MF)).addReg(0); 75642f628c8SJonas Paulsson 757515bfc66SJonas Paulsson StackAllocMI->eraseFromParent(); 75842f628c8SJonas Paulsson if (DoneMBB != nullptr) { 75942f628c8SJonas Paulsson // Compute the live-in lists for the new blocks. 76042f628c8SJonas Paulsson recomputeLiveIns(*DoneMBB); 76142f628c8SJonas Paulsson recomputeLiveIns(*LoopMBB); 76242f628c8SJonas Paulsson } 763515bfc66SJonas Paulsson } 764515bfc66SJonas Paulsson 7650782e55cSNeumann Hon bool SystemZELFFrameLowering::hasFP(const MachineFunction &MF) const { 7665f613dfdSUlrich Weigand return (MF.getTarget().Options.DisableFramePointerElim(MF) || 767792853cbSJonas Paulsson MF.getFrameInfo().hasVarSizedObjects()); 7685f613dfdSUlrich Weigand } 7695f613dfdSUlrich Weigand 7700782e55cSNeumann Hon StackOffset SystemZELFFrameLowering::getFrameIndexReference( 7710782e55cSNeumann Hon const MachineFunction &MF, int FI, Register &FrameReg) const { 772023b5c1eSYusra Syeda // Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so 77361f5ba5cSJonas Paulsson // add that difference here. 774d57bba7cSSander de Smalen StackOffset Offset = 77561f5ba5cSJonas Paulsson TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg); 776023b5c1eSYusra Syeda return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize); 77761f5ba5cSJonas Paulsson } 77861f5ba5cSJonas Paulsson 7790782e55cSNeumann Hon unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF, 7802481f26aSMatt Arsenault Register Reg) const { 78182879c29SJonas Paulsson bool IsVarArg = MF.getFunction().isVarArg(); 78282879c29SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 78382879c29SJonas Paulsson bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); 78482879c29SJonas Paulsson unsigned Offset = RegSpillOffsets[Reg]; 78582879c29SJonas Paulsson if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) { 78682879c29SJonas Paulsson if (SystemZ::GR64BitRegClass.contains(Reg)) 78782879c29SJonas Paulsson // Put all GPRs at the top of the Register save area with packed 78882879c29SJonas Paulsson // stack. Make room for the backchain if needed. 78982879c29SJonas Paulsson Offset += BackChain ? 24 : 32; 79082879c29SJonas Paulsson else 79182879c29SJonas Paulsson Offset = 0; 79282879c29SJonas Paulsson } 79382879c29SJonas Paulsson return Offset; 79482879c29SJonas Paulsson } 79582879c29SJonas Paulsson 7960782e55cSNeumann Hon int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex( 7970782e55cSNeumann Hon MachineFunction &MF) const { 79861f5ba5cSJonas Paulsson SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 79961f5ba5cSJonas Paulsson int FI = ZFI->getFramePointerSaveIndex(); 80061f5ba5cSJonas Paulsson if (!FI) { 80161f5ba5cSJonas Paulsson MachineFrameInfo &MFFrame = MF.getFrameInfo(); 802023b5c1eSYusra Syeda int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize; 80382879c29SJonas Paulsson FI = MFFrame.CreateFixedObject(8, Offset, false); 80461f5ba5cSJonas Paulsson ZFI->setFramePointerSaveIndex(FI); 80561f5ba5cSJonas Paulsson } 80661f5ba5cSJonas Paulsson return FI; 80761f5ba5cSJonas Paulsson } 80882879c29SJonas Paulsson 8090782e55cSNeumann Hon bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const { 81082879c29SJonas Paulsson bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); 81182879c29SJonas Paulsson bool BackChain = MF.getFunction().hasFnAttribute("backchain"); 81282879c29SJonas Paulsson bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat(); 81382879c29SJonas Paulsson if (HasPackedStackAttr && BackChain && !SoftFloat) 81482879c29SJonas Paulsson report_fatal_error("packed-stack + backchain + hard-float is unsupported."); 81582879c29SJonas Paulsson bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; 81682879c29SJonas Paulsson return HasPackedStackAttr && CallConv; 81782879c29SJonas Paulsson } 8180782e55cSNeumann Hon 8190782e55cSNeumann Hon SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering() 8209a358449SNeumann Hon : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0, 8210a950a2eSKai Nacke Align(32), /* StackRealignable */ false), 8220a950a2eSKai Nacke RegSpillOffsets(-1) { 8230a950a2eSKai Nacke 8240a950a2eSKai Nacke // Create a mapping from register number to save slot offset. 8250a950a2eSKai Nacke // These offsets are relative to the start of the local are area. 8260a950a2eSKai Nacke RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS); 827*f15014ffSBenjamin Kramer for (unsigned I = 0, E = array_lengthof(XPLINKSpillOffsetTable); I != E; ++I) 8280a950a2eSKai Nacke RegSpillOffsets[XPLINKSpillOffsetTable[I].Reg] = 8290a950a2eSKai Nacke XPLINKSpillOffsetTable[I].Offset; 8300a950a2eSKai Nacke } 8310a950a2eSKai Nacke 8320a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots( 8330a950a2eSKai Nacke MachineFunction &MF, const TargetRegisterInfo *TRI, 8340a950a2eSKai Nacke std::vector<CalleeSavedInfo> &CSI) const { 8350a950a2eSKai Nacke MachineFrameInfo &MFFrame = MF.getFrameInfo(); 8360a950a2eSKai Nacke SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); 8370a950a2eSKai Nacke const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 8380a950a2eSKai Nacke auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 8390a950a2eSKai Nacke 8400a950a2eSKai Nacke // Scan the call-saved GPRs and find the bounds of the register spill area. 8410a950a2eSKai Nacke unsigned LowGPR = 0; 8420a950a2eSKai Nacke int LowOffset = INT32_MAX; 8430a950a2eSKai Nacke unsigned HighGPR = LowGPR; 8440a950a2eSKai Nacke int HighOffset = -1; 8450a950a2eSKai Nacke 8460a950a2eSKai Nacke unsigned RegSP = Regs.getStackPointerRegister(); 8470a950a2eSKai Nacke auto &GRRegClass = SystemZ::GR64BitRegClass; 8480a950a2eSKai Nacke const unsigned RegSize = 8; 8490a950a2eSKai Nacke 8500a950a2eSKai Nacke auto ProcessCSI = [&](std::vector<CalleeSavedInfo> &CSIList) { 8510a950a2eSKai Nacke for (auto &CS : CSIList) { 852d6b07348SJim Lin Register Reg = CS.getReg(); 8530a950a2eSKai Nacke int Offset = RegSpillOffsets[Reg]; 8540a950a2eSKai Nacke if (Offset >= 0) { 8550a950a2eSKai Nacke if (GRRegClass.contains(Reg)) { 8560a950a2eSKai Nacke if (LowOffset > Offset) { 8570a950a2eSKai Nacke LowOffset = Offset; 8580a950a2eSKai Nacke LowGPR = Reg; 8590a950a2eSKai Nacke } 8600a950a2eSKai Nacke 8610a950a2eSKai Nacke if (Offset > HighOffset) { 8620a950a2eSKai Nacke HighOffset = Offset; 8630a950a2eSKai Nacke HighGPR = Reg; 8640a950a2eSKai Nacke } 8650a950a2eSKai Nacke } 8660a950a2eSKai Nacke int FrameIdx = MFFrame.CreateFixedSpillStackObject(RegSize, Offset); 8670a950a2eSKai Nacke CS.setFrameIdx(FrameIdx); 8680a950a2eSKai Nacke } else 8690a950a2eSKai Nacke CS.setFrameIdx(INT32_MAX); 8700a950a2eSKai Nacke } 8710a950a2eSKai Nacke }; 8720a950a2eSKai Nacke 8730a950a2eSKai Nacke std::vector<CalleeSavedInfo> Spills; 8740a950a2eSKai Nacke 8750a950a2eSKai Nacke // For non-leaf functions: 8760a950a2eSKai Nacke // - the address of callee (entry point) register R6 must be saved 8770a950a2eSKai Nacke Spills.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister())); 8780a950a2eSKai Nacke 8790a950a2eSKai Nacke // If the function needs a frame pointer, or if the backchain pointer should 8800a950a2eSKai Nacke // be stored, then save the stack pointer register R4. 8810a950a2eSKai Nacke if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain")) 8820a950a2eSKai Nacke Spills.push_back(CalleeSavedInfo(RegSP)); 8830a950a2eSKai Nacke 8840a950a2eSKai Nacke // Save the range of call-saved registers, for use by the 8850a950a2eSKai Nacke // prologue/epilogue inserters. 8860a950a2eSKai Nacke ProcessCSI(CSI); 8870a950a2eSKai Nacke MFI->setRestoreGPRRegs(LowGPR, HighGPR, LowOffset); 8880a950a2eSKai Nacke 8890a950a2eSKai Nacke // Save the range of call-saved registers, for use by the epilogue inserter. 8900a950a2eSKai Nacke ProcessCSI(Spills); 8910a950a2eSKai Nacke MFI->setSpillGPRRegs(LowGPR, HighGPR, LowOffset); 8920a950a2eSKai Nacke 8930a950a2eSKai Nacke // Create spill slots for the remaining registers. 8940a950a2eSKai Nacke for (auto &CS : CSI) { 8950a950a2eSKai Nacke if (CS.getFrameIdx() != INT32_MAX) 8960a950a2eSKai Nacke continue; 897d6b07348SJim Lin Register Reg = CS.getReg(); 8980a950a2eSKai Nacke const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); 8990a950a2eSKai Nacke Align Alignment = TRI->getSpillAlign(*RC); 9000a950a2eSKai Nacke unsigned Size = TRI->getSpillSize(*RC); 9010a950a2eSKai Nacke Alignment = std::min(Alignment, getStackAlign()); 9020a950a2eSKai Nacke int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true); 9030a950a2eSKai Nacke CS.setFrameIdx(FrameIdx); 9040a950a2eSKai Nacke } 9050a950a2eSKai Nacke 9060a950a2eSKai Nacke return true; 9070a950a2eSKai Nacke } 9080a950a2eSKai Nacke 9090a950a2eSKai Nacke void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF, 9100a950a2eSKai Nacke BitVector &SavedRegs, 9110a950a2eSKai Nacke RegScavenger *RS) const { 9120a950a2eSKai Nacke TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 9130a950a2eSKai Nacke 9140a950a2eSKai Nacke bool HasFP = hasFP(MF); 9150a950a2eSKai Nacke const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 9160a950a2eSKai Nacke auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 9170a950a2eSKai Nacke 9180a950a2eSKai Nacke // If the function requires a frame pointer, record that the hard 9190a950a2eSKai Nacke // frame pointer will be clobbered. 9200a950a2eSKai Nacke if (HasFP) 9210a950a2eSKai Nacke SavedRegs.set(Regs.getFramePointerRegister()); 9220a950a2eSKai Nacke 9230a950a2eSKai Nacke // If the function is not an XPLeaf function, we need to save the 9240a950a2eSKai Nacke // return address register. We also always use that register for 9250a950a2eSKai Nacke // the return instruction, so it needs to be restored in the 9260a950a2eSKai Nacke // epilogue even though that register is considered to be volatile. 9270a950a2eSKai Nacke // #TODO: Implement leaf detection. 9280a950a2eSKai Nacke SavedRegs.set(Regs.getReturnFunctionAddressRegister()); 9290a950a2eSKai Nacke } 9300a950a2eSKai Nacke 9310a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters( 9320a950a2eSKai Nacke MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 9330a950a2eSKai Nacke ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 9340a950a2eSKai Nacke if (CSI.empty()) 9350a950a2eSKai Nacke return true; 9360a950a2eSKai Nacke 9370a950a2eSKai Nacke MachineFunction &MF = *MBB.getParent(); 9380a950a2eSKai Nacke SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 9390a950a2eSKai Nacke const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 9400a950a2eSKai Nacke const TargetInstrInfo *TII = Subtarget.getInstrInfo(); 9410a950a2eSKai Nacke auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 9420a950a2eSKai Nacke SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs(); 9430a950a2eSKai Nacke DebugLoc DL; 9440a950a2eSKai Nacke 9450a950a2eSKai Nacke // Save GPRs 9460a950a2eSKai Nacke if (SpillGPRs.LowGPR) { 9470a950a2eSKai Nacke assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR && 9480a950a2eSKai Nacke "Should be saving multiple registers"); 9490a950a2eSKai Nacke 9500a950a2eSKai Nacke // Build an STM/STMG instruction. 9510a950a2eSKai Nacke MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG)); 9520a950a2eSKai Nacke 9530a950a2eSKai Nacke // Add the explicit register operands. 9540a950a2eSKai Nacke addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false); 9550a950a2eSKai Nacke addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false); 9560a950a2eSKai Nacke 9570a950a2eSKai Nacke // Add the address r4 9580a950a2eSKai Nacke MIB.addReg(Regs.getStackPointerRegister()); 9590a950a2eSKai Nacke 9600a950a2eSKai Nacke // Add the partial offset 9610a950a2eSKai Nacke // We cannot add the actual offset as, at the stack is not finalized 9620a950a2eSKai Nacke MIB.addImm(SpillGPRs.GPROffset); 9630a950a2eSKai Nacke 9640a950a2eSKai Nacke // Make sure all call-saved GPRs are included as operands and are 9650a950a2eSKai Nacke // marked as live on entry. 9660a950a2eSKai Nacke auto &GRRegClass = SystemZ::GR64BitRegClass; 967ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 968d6b07348SJim Lin Register Reg = I.getReg(); 9690a950a2eSKai Nacke if (GRRegClass.contains(Reg)) 9700a950a2eSKai Nacke addSavedGPR(MBB, MIB, Reg, true); 9710a950a2eSKai Nacke } 9720a950a2eSKai Nacke } 9730a950a2eSKai Nacke 9740a950a2eSKai Nacke // Spill FPRs to the stack in the normal TargetInstrInfo way 975ea5421bdSKazu Hirata for (const CalleeSavedInfo &I : CSI) { 976d6b07348SJim Lin Register Reg = I.getReg(); 9770a950a2eSKai Nacke if (SystemZ::FP64BitRegClass.contains(Reg)) { 9780a950a2eSKai Nacke MBB.addLiveIn(Reg); 979ea5421bdSKazu Hirata TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(), 9800a950a2eSKai Nacke &SystemZ::FP64BitRegClass, TRI); 9810a950a2eSKai Nacke } 9820a950a2eSKai Nacke if (SystemZ::VR128BitRegClass.contains(Reg)) { 9830a950a2eSKai Nacke MBB.addLiveIn(Reg); 984ea5421bdSKazu Hirata TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(), 9850a950a2eSKai Nacke &SystemZ::VR128BitRegClass, TRI); 9860a950a2eSKai Nacke } 9870a950a2eSKai Nacke } 9880a950a2eSKai Nacke 9890a950a2eSKai Nacke return true; 9900a950a2eSKai Nacke } 9910782e55cSNeumann Hon 9929a358449SNeumann Hon bool SystemZXPLINKFrameLowering::restoreCalleeSavedRegisters( 9939a358449SNeumann Hon MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 9949a358449SNeumann Hon MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 9959a358449SNeumann Hon 9969a358449SNeumann Hon if (CSI.empty()) 9979a358449SNeumann Hon return false; 9989a358449SNeumann Hon 9999a358449SNeumann Hon MachineFunction &MF = *MBB.getParent(); 10009a358449SNeumann Hon SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 10019a358449SNeumann Hon const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 10029a358449SNeumann Hon const TargetInstrInfo *TII = Subtarget.getInstrInfo(); 10039a358449SNeumann Hon auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 10049a358449SNeumann Hon 10059a358449SNeumann Hon DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 10069a358449SNeumann Hon 10079a358449SNeumann Hon // Restore FPRs in the normal TargetInstrInfo way. 10089a358449SNeumann Hon for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 1009d6b07348SJim Lin Register Reg = CSI[I].getReg(); 10109a358449SNeumann Hon if (SystemZ::FP64BitRegClass.contains(Reg)) 10119a358449SNeumann Hon TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 10129a358449SNeumann Hon &SystemZ::FP64BitRegClass, TRI); 10139a358449SNeumann Hon if (SystemZ::VR128BitRegClass.contains(Reg)) 10149a358449SNeumann Hon TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), 10159a358449SNeumann Hon &SystemZ::VR128BitRegClass, TRI); 10169a358449SNeumann Hon } 10179a358449SNeumann Hon 10189a358449SNeumann Hon // Restore call-saved GPRs (but not call-clobbered varargs, which at 10199a358449SNeumann Hon // this point might hold return values). 10209a358449SNeumann Hon SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs(); 10219a358449SNeumann Hon if (RestoreGPRs.LowGPR) { 10229a358449SNeumann Hon assert(isInt<20>(Regs.getStackPointerBias() + RestoreGPRs.GPROffset)); 10239a358449SNeumann Hon if (RestoreGPRs.LowGPR == RestoreGPRs.HighGPR) 10249a358449SNeumann Hon // Build an LG/L instruction. 10259a358449SNeumann Hon BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LG), RestoreGPRs.LowGPR) 10269a358449SNeumann Hon .addReg(Regs.getStackPointerRegister()) 10279a358449SNeumann Hon .addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset) 10289a358449SNeumann Hon .addReg(0); 10299a358449SNeumann Hon else { 10309a358449SNeumann Hon // Build an LMG/LM instruction. 10319a358449SNeumann Hon MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); 10329a358449SNeumann Hon 10339a358449SNeumann Hon // Add the explicit register operands. 10349a358449SNeumann Hon MIB.addReg(RestoreGPRs.LowGPR, RegState::Define); 10359a358449SNeumann Hon MIB.addReg(RestoreGPRs.HighGPR, RegState::Define); 10369a358449SNeumann Hon 10379a358449SNeumann Hon // Add the address. 10389a358449SNeumann Hon MIB.addReg(Regs.getStackPointerRegister()); 10399a358449SNeumann Hon MIB.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset); 10409a358449SNeumann Hon 10419a358449SNeumann Hon // Do a second scan adding regs as being defined by instruction 10429a358449SNeumann Hon for (unsigned I = 0, E = CSI.size(); I != E; ++I) { 1043d6b07348SJim Lin Register Reg = CSI[I].getReg(); 10449a358449SNeumann Hon if (Reg > RestoreGPRs.LowGPR && Reg < RestoreGPRs.HighGPR) 10459a358449SNeumann Hon MIB.addReg(Reg, RegState::ImplicitDefine); 10469a358449SNeumann Hon } 10479a358449SNeumann Hon } 10489a358449SNeumann Hon } 10499a358449SNeumann Hon 10509a358449SNeumann Hon return true; 10519a358449SNeumann Hon } 10529a358449SNeumann Hon 10530782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF, 10549a358449SNeumann Hon MachineBasicBlock &MBB) const { 10559a358449SNeumann Hon assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 10569a358449SNeumann Hon const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 10579a358449SNeumann Hon SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 10589a358449SNeumann Hon MachineBasicBlock::iterator MBBI = MBB.begin(); 10599a358449SNeumann Hon auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo()); 10609a358449SNeumann Hon auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 10619a358449SNeumann Hon MachineFrameInfo &MFFrame = MF.getFrameInfo(); 10629a358449SNeumann Hon MachineInstr *StoreInstr = nullptr; 10639a358449SNeumann Hon bool HasFP = hasFP(MF); 10649a358449SNeumann Hon // Debug location must be unknown since the first debug location is used 10659a358449SNeumann Hon // to determine the end of the prologue. 10669a358449SNeumann Hon DebugLoc DL; 10679a358449SNeumann Hon uint64_t Offset = 0; 10689a358449SNeumann Hon 10699a358449SNeumann Hon // TODO: Support leaf functions; only add size of save+reserved area when 10709a358449SNeumann Hon // function is non-leaf. 10719a358449SNeumann Hon MFFrame.setStackSize(MFFrame.getStackSize() + Regs.getCallFrameSize()); 10729a358449SNeumann Hon uint64_t StackSize = MFFrame.getStackSize(); 10739a358449SNeumann Hon 10749a358449SNeumann Hon // FIXME: Implement support for large stack sizes, when the stack extension 10759a358449SNeumann Hon // routine needs to be called. 10769a358449SNeumann Hon if (StackSize > 1024 * 1024) { 10779a358449SNeumann Hon llvm_unreachable("Huge Stack Frame not yet supported on z/OS"); 10789a358449SNeumann Hon } 10799a358449SNeumann Hon 10809a358449SNeumann Hon if (ZFI->getSpillGPRRegs().LowGPR) { 10819a358449SNeumann Hon // Skip over the GPR saves. 10829a358449SNeumann Hon if ((MBBI != MBB.end()) && ((MBBI->getOpcode() == SystemZ::STMG))) { 10839a358449SNeumann Hon const int Operand = 3; 10849a358449SNeumann Hon // Now we can set the offset for the operation, since now the Stack 10859a358449SNeumann Hon // has been finalized. 10869a358449SNeumann Hon Offset = Regs.getStackPointerBias() + MBBI->getOperand(Operand).getImm(); 10879a358449SNeumann Hon // Maximum displacement for STMG instruction. 10889a358449SNeumann Hon if (isInt<20>(Offset - StackSize)) 10899a358449SNeumann Hon Offset -= StackSize; 10909a358449SNeumann Hon else 10919a358449SNeumann Hon StoreInstr = &*MBBI; 10929a358449SNeumann Hon MBBI->getOperand(Operand).setImm(Offset); 10939a358449SNeumann Hon ++MBBI; 10949a358449SNeumann Hon } else 10959a358449SNeumann Hon llvm_unreachable("Couldn't skip over GPR saves"); 10969a358449SNeumann Hon } 10979a358449SNeumann Hon 10989a358449SNeumann Hon if (StackSize) { 10999a358449SNeumann Hon MachineBasicBlock::iterator InsertPt = StoreInstr ? StoreInstr : MBBI; 11009a358449SNeumann Hon // Allocate StackSize bytes. 11019a358449SNeumann Hon int64_t Delta = -int64_t(StackSize); 11029a358449SNeumann Hon 11039a358449SNeumann Hon // In case the STM(G) instruction also stores SP (R4), but the displacement 11049a358449SNeumann Hon // is too large, the SP register is manipulated first before storing, 11059a358449SNeumann Hon // resulting in the wrong value stored and retrieved later. In this case, we 11069a358449SNeumann Hon // need to temporarily save the value of SP, and store it later to memory. 11079a358449SNeumann Hon if (StoreInstr && HasFP) { 11089a358449SNeumann Hon // Insert LR r0,r4 before STMG instruction. 11099a358449SNeumann Hon BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::LGR)) 11109a358449SNeumann Hon .addReg(SystemZ::R0D, RegState::Define) 11119a358449SNeumann Hon .addReg(SystemZ::R4D); 11129a358449SNeumann Hon // Insert ST r0,xxx(,r4) after STMG instruction. 11139a358449SNeumann Hon BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG)) 11149a358449SNeumann Hon .addReg(SystemZ::R0D, RegState::Kill) 11159a358449SNeumann Hon .addReg(SystemZ::R4D) 11169a358449SNeumann Hon .addImm(Offset) 11179a358449SNeumann Hon .addReg(0); 11189a358449SNeumann Hon } 11199a358449SNeumann Hon 11209a358449SNeumann Hon emitIncrement(MBB, InsertPt, DL, Regs.getStackPointerRegister(), Delta, 11219a358449SNeumann Hon ZII); 11229a358449SNeumann Hon } 11239a358449SNeumann Hon 11249a358449SNeumann Hon if (HasFP) { 11259a358449SNeumann Hon // Copy the base of the frame to Frame Pointer Register. 11269a358449SNeumann Hon BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), 11279a358449SNeumann Hon Regs.getFramePointerRegister()) 11289a358449SNeumann Hon .addReg(Regs.getStackPointerRegister()); 11299a358449SNeumann Hon 11309a358449SNeumann Hon // Mark the FramePtr as live at the beginning of every block except 11319a358449SNeumann Hon // the entry block. (We'll have marked R8 as live on entry when 11329a358449SNeumann Hon // saving the GPRs.) 11339a358449SNeumann Hon for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) 11349a358449SNeumann Hon I->addLiveIn(Regs.getFramePointerRegister()); 11359a358449SNeumann Hon } 11369a358449SNeumann Hon } 11370782e55cSNeumann Hon 11380782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF, 11399a358449SNeumann Hon MachineBasicBlock &MBB) const { 11409a358449SNeumann Hon const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 11419a358449SNeumann Hon MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 11429a358449SNeumann Hon SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); 11439a358449SNeumann Hon MachineFrameInfo &MFFrame = MF.getFrameInfo(); 11449a358449SNeumann Hon auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo()); 11459a358449SNeumann Hon auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 11469a358449SNeumann Hon 11479a358449SNeumann Hon // Skip the return instruction. 11489a358449SNeumann Hon assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks"); 11499a358449SNeumann Hon 11509a358449SNeumann Hon uint64_t StackSize = MFFrame.getStackSize(); 11519a358449SNeumann Hon if (StackSize) { 11529a358449SNeumann Hon unsigned SPReg = Regs.getStackPointerRegister(); 11539a358449SNeumann Hon if (ZFI->getRestoreGPRRegs().LowGPR != SPReg) { 11549a358449SNeumann Hon DebugLoc DL = MBBI->getDebugLoc(); 11559a358449SNeumann Hon emitIncrement(MBB, MBBI, DL, SPReg, StackSize, ZII); 11569a358449SNeumann Hon } 11579a358449SNeumann Hon } 11589a358449SNeumann Hon } 11590782e55cSNeumann Hon 11600782e55cSNeumann Hon bool SystemZXPLINKFrameLowering::hasFP(const MachineFunction &MF) const { 11619a358449SNeumann Hon return (MF.getFrameInfo().hasVarSizedObjects()); 11629a358449SNeumann Hon } 11639a358449SNeumann Hon 11649a358449SNeumann Hon void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized( 11659a358449SNeumann Hon MachineFunction &MF, RegScavenger *RS) const { 11669a358449SNeumann Hon MachineFrameInfo &MFFrame = MF.getFrameInfo(); 11679a358449SNeumann Hon const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>(); 11689a358449SNeumann Hon auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>(); 11699a358449SNeumann Hon 11709a358449SNeumann Hon // Setup stack frame offset 11719a358449SNeumann Hon MFFrame.setOffsetAdjustment(Regs.getStackPointerBias()); 11720782e55cSNeumann Hon } 1173