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.
26a7d3f693SJonas Paulsson // incoming stack pointer + SystemZMC::CallFrameSize).
27db39b4a2SRichard Sandiford static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = {
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 };
47c231269fSRichard Sandiford } // end anonymous namespace
485f613dfdSUlrich Weigand 
49f1bd22dfSEric Christopher SystemZFrameLowering::SystemZFrameLowering()
50882c43d7SGuillaume Chatelet     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8),
5161f5ba5cSJonas Paulsson                           0, Align(8), false /* StackRealignable */),
5261f5ba5cSJonas Paulsson       RegSpillOffsets(0) {
53a7d3f693SJonas Paulsson   // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not
54a7d3f693SJonas Paulsson   // equal to the incoming stack pointer, but to incoming stack pointer plus
5561f5ba5cSJonas Paulsson   // 160.  Instead of using a Local Area Offset, the Register save area will
5661f5ba5cSJonas Paulsson   // be occupied by fixed frame objects, and all offsets are actually
5761f5ba5cSJonas Paulsson   // relative to CFA.
58a7d3f693SJonas Paulsson 
595f613dfdSUlrich Weigand   // Create a mapping from register number to save slot offset.
60a7d3f693SJonas Paulsson   // These offsets are relative to the start of the register save area.
615f613dfdSUlrich Weigand   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
625f613dfdSUlrich Weigand   for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I)
6361f5ba5cSJonas Paulsson     RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset;
64db39b4a2SRichard Sandiford }
65db39b4a2SRichard Sandiford 
6661f5ba5cSJonas Paulsson bool SystemZFrameLowering::
6761f5ba5cSJonas Paulsson assignCalleeSavedSpillSlots(MachineFunction &MF,
6861f5ba5cSJonas Paulsson                             const TargetRegisterInfo *TRI,
6961f5ba5cSJonas Paulsson                             std::vector<CalleeSavedInfo> &CSI) const {
7061f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
7161f5ba5cSJonas Paulsson   MachineFrameInfo &MFFrame = MF.getFrameInfo();
7261f5ba5cSJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
7361f5ba5cSJonas Paulsson   if (CSI.empty())
7461f5ba5cSJonas Paulsson     return true; // Early exit if no callee saved registers are modified!
7561f5ba5cSJonas Paulsson 
7661f5ba5cSJonas Paulsson   unsigned LowGPR = 0;
7761f5ba5cSJonas Paulsson   unsigned HighGPR = SystemZ::R15D;
7861f5ba5cSJonas Paulsson   int StartSPOffset = SystemZMC::CallFrameSize;
7961f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
8061f5ba5cSJonas Paulsson     unsigned Reg = CS.getReg();
8182879c29SJonas Paulsson     int Offset = getRegSpillOffset(MF, Reg);
8261f5ba5cSJonas Paulsson     if (Offset) {
8361f5ba5cSJonas Paulsson       if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {
8461f5ba5cSJonas Paulsson         LowGPR = Reg;
8561f5ba5cSJonas Paulsson         StartSPOffset = Offset;
8661f5ba5cSJonas Paulsson       }
8761f5ba5cSJonas Paulsson       Offset -= SystemZMC::CallFrameSize;
8861f5ba5cSJonas Paulsson       int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
8961f5ba5cSJonas Paulsson       CS.setFrameIdx(FrameIdx);
9061f5ba5cSJonas Paulsson     } else
9161f5ba5cSJonas Paulsson       CS.setFrameIdx(INT32_MAX);
9261f5ba5cSJonas Paulsson   }
9361f5ba5cSJonas Paulsson 
9461f5ba5cSJonas Paulsson   // Save the range of call-saved registers, for use by the
9561f5ba5cSJonas Paulsson   // prologue/epilogue inserters.
9661f5ba5cSJonas Paulsson   ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
9761f5ba5cSJonas Paulsson   if (IsVarArg) {
9861f5ba5cSJonas Paulsson     // Also save the GPR varargs, if any.  R6D is call-saved, so would
9961f5ba5cSJonas Paulsson     // already be included, but we also need to handle the call-clobbered
10061f5ba5cSJonas Paulsson     // argument registers.
10161f5ba5cSJonas Paulsson     unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
10261f5ba5cSJonas Paulsson     if (FirstGPR < SystemZ::NumArgGPRs) {
10361f5ba5cSJonas Paulsson       unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
10482879c29SJonas Paulsson       int Offset = getRegSpillOffset(MF, Reg);
10561f5ba5cSJonas Paulsson       if (StartSPOffset > Offset) {
10661f5ba5cSJonas Paulsson         LowGPR = Reg; StartSPOffset = Offset;
10761f5ba5cSJonas Paulsson       }
10861f5ba5cSJonas Paulsson     }
10961f5ba5cSJonas Paulsson   }
11061f5ba5cSJonas Paulsson   ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
11161f5ba5cSJonas Paulsson 
11261f5ba5cSJonas Paulsson   // Create fixed stack objects for the remaining registers.
11382879c29SJonas Paulsson   int CurrOffset = -SystemZMC::CallFrameSize;
11482879c29SJonas Paulsson   if (usePackedStack(MF))
11582879c29SJonas Paulsson     CurrOffset += StartSPOffset;
11682879c29SJonas Paulsson 
11761f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
11861f5ba5cSJonas Paulsson     if (CS.getFrameIdx() != INT32_MAX)
11961f5ba5cSJonas Paulsson       continue;
12061f5ba5cSJonas Paulsson     unsigned Reg = CS.getReg();
12161f5ba5cSJonas Paulsson     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
12261f5ba5cSJonas Paulsson     unsigned Size = TRI->getSpillSize(*RC);
12361f5ba5cSJonas Paulsson     CurrOffset -= Size;
12461f5ba5cSJonas Paulsson     assert(CurrOffset % 8 == 0 &&
12561f5ba5cSJonas Paulsson            "8-byte alignment required for for all register save slots");
12661f5ba5cSJonas Paulsson     int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);
12761f5ba5cSJonas Paulsson     CS.setFrameIdx(FrameIdx);
12861f5ba5cSJonas Paulsson   }
12961f5ba5cSJonas Paulsson 
13061f5ba5cSJonas Paulsson   return true;
1315f613dfdSUlrich Weigand }
1325f613dfdSUlrich Weigand 
13302564865SMatthias Braun void SystemZFrameLowering::determineCalleeSaves(MachineFunction &MF,
13402564865SMatthias Braun                                                 BitVector &SavedRegs,
1355f613dfdSUlrich Weigand                                                 RegScavenger *RS) const {
13602564865SMatthias Braun   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
13702564865SMatthias Braun 
138941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
139fc6de428SEric Christopher   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1405f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
1415f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
142f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
1435f613dfdSUlrich Weigand 
1445f613dfdSUlrich Weigand   // va_start stores incoming FPR varargs in the normal way, but delegates
1455f613dfdSUlrich Weigand   // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
1465f613dfdSUlrich Weigand   // Record these pending uses, which typically include the call-saved
1475f613dfdSUlrich Weigand   // argument register R6D.
1485f613dfdSUlrich Weigand   if (IsVarArg)
1495f613dfdSUlrich Weigand     for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
15002564865SMatthias Braun       SavedRegs.set(SystemZ::ArgGPRs[I]);
1515f613dfdSUlrich Weigand 
152234e5a80SMarcin Koscielnicki   // If there are any landing pads, entering them will modify r6/r7.
153d0ee66c2SMatthias Braun   if (!MF.getLandingPads().empty()) {
154234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R6D);
155234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R7D);
156234e5a80SMarcin Koscielnicki   }
157234e5a80SMarcin Koscielnicki 
1585f613dfdSUlrich Weigand   // If the function requires a frame pointer, record that the hard
1595f613dfdSUlrich Weigand   // frame pointer will be clobbered.
1605f613dfdSUlrich Weigand   if (HasFP)
16102564865SMatthias Braun     SavedRegs.set(SystemZ::R11D);
1625f613dfdSUlrich Weigand 
1635f613dfdSUlrich Weigand   // If the function calls other functions, record that the return
1645f613dfdSUlrich Weigand   // address register will be clobbered.
165941a705bSMatthias Braun   if (MFFrame.hasCalls())
16602564865SMatthias Braun     SavedRegs.set(SystemZ::R14D);
1675f613dfdSUlrich Weigand 
1685f613dfdSUlrich Weigand   // If we are saving GPRs other than the stack pointer, we might as well
1695f613dfdSUlrich Weigand   // save and restore the stack pointer at the same time, via STMG and LMG.
1705f613dfdSUlrich Weigand   // This allows the deallocation to be done by the LMG, rather than needing
1715f613dfdSUlrich Weigand   // a separate %r15 addition.
172840beec2SCraig Topper   const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
1735f613dfdSUlrich Weigand   for (unsigned I = 0; CSRegs[I]; ++I) {
1745f613dfdSUlrich Weigand     unsigned Reg = CSRegs[I];
17502564865SMatthias Braun     if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {
17602564865SMatthias Braun       SavedRegs.set(SystemZ::R15D);
1775f613dfdSUlrich Weigand       break;
1785f613dfdSUlrich Weigand     }
1795f613dfdSUlrich Weigand   }
1805f613dfdSUlrich Weigand }
1815f613dfdSUlrich Weigand 
1825f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic
1835f613dfdSUlrich Weigand // block MBB.  IsImplicit says whether this is an explicit operand to the
1845f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start
1855f613dfdSUlrich Weigand // and end registers.
1865f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,
1875f613dfdSUlrich Weigand                         unsigned GPR64, bool IsImplicit) {
188d913448bSEric Christopher   const TargetRegisterInfo *RI =
189fc6de428SEric Christopher       MBB.getParent()->getSubtarget().getRegisterInfo();
1900c476111SDaniel Sanders   Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);
1915f613dfdSUlrich Weigand   bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);
1925f613dfdSUlrich Weigand   if (!IsLive || !IsImplicit) {
1935f613dfdSUlrich Weigand     MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));
1945f613dfdSUlrich Weigand     if (!IsLive)
1955f613dfdSUlrich Weigand       MBB.addLiveIn(GPR64);
1965f613dfdSUlrich Weigand   }
1975f613dfdSUlrich Weigand }
1985f613dfdSUlrich Weigand 
199e4230a9fSBenjamin Kramer bool SystemZFrameLowering::spillCalleeSavedRegisters(
200e4230a9fSBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
201e4230a9fSBenjamin Kramer     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
2025f613dfdSUlrich Weigand   if (CSI.empty())
2035f613dfdSUlrich Weigand     return false;
2045f613dfdSUlrich Weigand 
2055f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
206fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
2075f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
208f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
209057c5a6bSOleg Ranevskyy   DebugLoc DL;
2105f613dfdSUlrich Weigand 
2115f613dfdSUlrich Weigand   // Save GPRs
21261f5ba5cSJonas Paulsson   SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();
21361f5ba5cSJonas Paulsson   if (SpillGPRs.LowGPR) {
21461f5ba5cSJonas Paulsson     assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&
21561f5ba5cSJonas Paulsson            "Should be saving %r15 and something else");
2165f613dfdSUlrich Weigand 
2175f613dfdSUlrich Weigand     // Build an STMG instruction.
2185f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
2195f613dfdSUlrich Weigand 
2205f613dfdSUlrich Weigand     // Add the explicit register operands.
22161f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);
22261f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);
2235f613dfdSUlrich Weigand 
2245f613dfdSUlrich Weigand     // Add the address.
22561f5ba5cSJonas Paulsson     MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset);
2265f613dfdSUlrich Weigand 
2275f613dfdSUlrich Weigand     // Make sure all call-saved GPRs are included as operands and are
2285f613dfdSUlrich Weigand     // marked as live on entry.
2295f613dfdSUlrich Weigand     for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
2305f613dfdSUlrich Weigand       unsigned Reg = CSI[I].getReg();
2315f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg))
232f1bd22dfSEric Christopher         addSavedGPR(MBB, MIB, Reg, true);
2335f613dfdSUlrich Weigand     }
2345f613dfdSUlrich Weigand 
2355f613dfdSUlrich Weigand     // ...likewise GPR varargs.
2365f613dfdSUlrich Weigand     if (IsVarArg)
2375f613dfdSUlrich Weigand       for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::NumArgGPRs; ++I)
238f1bd22dfSEric Christopher         addSavedGPR(MBB, MIB, SystemZ::ArgGPRs[I], true);
2395f613dfdSUlrich Weigand   }
2405f613dfdSUlrich Weigand 
2418b19be46SUlrich Weigand   // Save FPRs/VRs in the normal TargetInstrInfo way.
2425f613dfdSUlrich Weigand   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
2435f613dfdSUlrich Weigand     unsigned Reg = CSI[I].getReg();
2445f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
2455f613dfdSUlrich Weigand       MBB.addLiveIn(Reg);
2465f613dfdSUlrich Weigand       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
2475f613dfdSUlrich Weigand                                &SystemZ::FP64BitRegClass, TRI);
2485f613dfdSUlrich Weigand     }
2498b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg)) {
2508b19be46SUlrich Weigand       MBB.addLiveIn(Reg);
2518b19be46SUlrich Weigand       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, CSI[I].getFrameIdx(),
2528b19be46SUlrich Weigand                                &SystemZ::VR128BitRegClass, TRI);
2538b19be46SUlrich Weigand     }
2545f613dfdSUlrich Weigand   }
2555f613dfdSUlrich Weigand 
2565f613dfdSUlrich Weigand   return true;
2575f613dfdSUlrich Weigand }
2585f613dfdSUlrich Weigand 
259186dd631SBenjamin Kramer bool SystemZFrameLowering::restoreCalleeSavedRegisters(
260186dd631SBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
261186dd631SBenjamin Kramer     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
2625f613dfdSUlrich Weigand   if (CSI.empty())
2635f613dfdSUlrich Weigand     return false;
2645f613dfdSUlrich Weigand 
2655f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
266fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
2675f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
2685f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
2695f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
2705f613dfdSUlrich Weigand 
2718b19be46SUlrich Weigand   // Restore FPRs/VRs in the normal TargetInstrInfo way.
2725f613dfdSUlrich Weigand   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
2735f613dfdSUlrich Weigand     unsigned Reg = CSI[I].getReg();
2745f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg))
2755f613dfdSUlrich Weigand       TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
2765f613dfdSUlrich Weigand                                 &SystemZ::FP64BitRegClass, TRI);
2778b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg))
2788b19be46SUlrich Weigand       TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
2798b19be46SUlrich Weigand                                 &SystemZ::VR128BitRegClass, TRI);
2805f613dfdSUlrich Weigand   }
2815f613dfdSUlrich Weigand 
2825f613dfdSUlrich Weigand   // Restore call-saved GPRs (but not call-clobbered varargs, which at
2835f613dfdSUlrich Weigand   // this point might hold return values).
28461f5ba5cSJonas Paulsson   SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();
28561f5ba5cSJonas Paulsson   if (RestoreGPRs.LowGPR) {
2865f613dfdSUlrich Weigand     // If we saved any of %r2-%r5 as varargs, we should also be saving
2875f613dfdSUlrich Weigand     // and restoring %r6.  If we're saving %r6 or above, we should be
2885f613dfdSUlrich Weigand     // restoring it too.
28961f5ba5cSJonas Paulsson     assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR &&
29061f5ba5cSJonas Paulsson            "Should be loading %r15 and something else");
2915f613dfdSUlrich Weigand 
2925f613dfdSUlrich Weigand     // Build an LMG instruction.
2935f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
2945f613dfdSUlrich Weigand 
2955f613dfdSUlrich Weigand     // Add the explicit register operands.
29661f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);
29761f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);
2985f613dfdSUlrich Weigand 
2995f613dfdSUlrich Weigand     // Add the address.
3005f613dfdSUlrich Weigand     MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);
30161f5ba5cSJonas Paulsson     MIB.addImm(RestoreGPRs.GPROffset);
3025f613dfdSUlrich Weigand 
3035f613dfdSUlrich Weigand     // Do a second scan adding regs as being defined by instruction
3045f613dfdSUlrich Weigand     for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
3055f613dfdSUlrich Weigand       unsigned Reg = CSI[I].getReg();
30661f5ba5cSJonas Paulsson       if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&
307f0344826SJonas Paulsson           SystemZ::GR64BitRegClass.contains(Reg))
3085f613dfdSUlrich Weigand         MIB.addReg(Reg, RegState::ImplicitDefine);
3095f613dfdSUlrich Weigand     }
3105f613dfdSUlrich Weigand   }
3115f613dfdSUlrich Weigand 
3125f613dfdSUlrich Weigand   return true;
3135f613dfdSUlrich Weigand }
3145f613dfdSUlrich Weigand 
3155dd52f8cSRichard Sandiford void SystemZFrameLowering::
3165dd52f8cSRichard Sandiford processFunctionBeforeFrameFinalized(MachineFunction &MF,
3175dd52f8cSRichard Sandiford                                     RegScavenger *RS) const {
318941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
31923762575SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
32061f5ba5cSJonas Paulsson 
32123762575SJonas Paulsson   if (!usePackedStack(MF) || BackChain)
32223762575SJonas Paulsson     // Create the incoming register save area.
32361f5ba5cSJonas Paulsson     getOrCreateFramePointerSaveIndex(MF);
32461f5ba5cSJonas Paulsson 
325af98b748SUlrich Weigand   // Get the size of our stack frame to be allocated ...
326af98b748SUlrich Weigand   uint64_t StackSize = (MFFrame.estimateStackSize(MF) +
327af98b748SUlrich Weigand                         SystemZMC::CallFrameSize);
328af98b748SUlrich Weigand   // ... and the maximum offset we may need to reach into the
329af98b748SUlrich Weigand   // caller's frame to access the save area or stack arguments.
33061f5ba5cSJonas Paulsson   int64_t MaxArgOffset = 0;
331af98b748SUlrich Weigand   for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)
332af98b748SUlrich Weigand     if (MFFrame.getObjectOffset(I) >= 0) {
33361f5ba5cSJonas Paulsson       int64_t ArgOffset = MFFrame.getObjectOffset(I) +
334af98b748SUlrich Weigand                           MFFrame.getObjectSize(I);
335af98b748SUlrich Weigand       MaxArgOffset = std::max(MaxArgOffset, ArgOffset);
336af98b748SUlrich Weigand     }
337af98b748SUlrich Weigand 
338af98b748SUlrich Weigand   uint64_t MaxReach = StackSize + MaxArgOffset;
33923943229SRichard Sandiford   if (!isUInt<12>(MaxReach)) {
34023943229SRichard Sandiford     // We may need register scavenging slots if some parts of the frame
3415dd52f8cSRichard Sandiford     // are outside the reach of an unsigned 12-bit displacement.
34223943229SRichard Sandiford     // Create 2 for the case where both addresses in an MVC are
34323943229SRichard Sandiford     // out of range.
344*28de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
345*28de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
34623943229SRichard Sandiford   }
3475dd52f8cSRichard Sandiford }
3485dd52f8cSRichard Sandiford 
3495f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
3505f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB,
3512481f26aSMatt Arsenault                           MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,
3522481f26aSMatt Arsenault                           Register Reg, int64_t NumBytes,
3535f613dfdSUlrich Weigand                           const TargetInstrInfo *TII) {
3545f613dfdSUlrich Weigand   while (NumBytes) {
3555f613dfdSUlrich Weigand     unsigned Opcode;
3565f613dfdSUlrich Weigand     int64_t ThisVal = NumBytes;
3575f613dfdSUlrich Weigand     if (isInt<16>(NumBytes))
3585f613dfdSUlrich Weigand       Opcode = SystemZ::AGHI;
3595f613dfdSUlrich Weigand     else {
3605f613dfdSUlrich Weigand       Opcode = SystemZ::AGFI;
3615f613dfdSUlrich Weigand       // Make sure we maintain 8-byte stack alignment.
362fffd56ecSAlexey Samsonov       int64_t MinVal = -uint64_t(1) << 31;
3635f613dfdSUlrich Weigand       int64_t MaxVal = (int64_t(1) << 31) - 8;
3645f613dfdSUlrich Weigand       if (ThisVal < MinVal)
3655f613dfdSUlrich Weigand         ThisVal = MinVal;
3665f613dfdSUlrich Weigand       else if (ThisVal > MaxVal)
3675f613dfdSUlrich Weigand         ThisVal = MaxVal;
3685f613dfdSUlrich Weigand     }
3695f613dfdSUlrich Weigand     MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
3705f613dfdSUlrich Weigand       .addReg(Reg).addImm(ThisVal);
37114a44495SRichard Sandiford     // The CC implicit def is dead.
3725f613dfdSUlrich Weigand     MI->getOperand(3).setIsDead();
3735f613dfdSUlrich Weigand     NumBytes -= ThisVal;
3745f613dfdSUlrich Weigand   }
3755f613dfdSUlrich Weigand }
3765f613dfdSUlrich Weigand 
377515bfc66SJonas Paulsson // Add CFI for the new CFA offset.
378515bfc66SJonas Paulsson static void buildCFAOffs(MachineBasicBlock &MBB,
379515bfc66SJonas Paulsson                          MachineBasicBlock::iterator MBBI,
380515bfc66SJonas Paulsson                          const DebugLoc &DL, int Offset,
381515bfc66SJonas Paulsson                          const SystemZInstrInfo *ZII) {
382515bfc66SJonas Paulsson   unsigned CFIIndex = MBB.getParent()->addFrameInst(
383515bfc66SJonas Paulsson     MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));
384515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
385515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
386515bfc66SJonas Paulsson }
387515bfc66SJonas Paulsson 
388515bfc66SJonas Paulsson // Add CFI for the new frame location.
389515bfc66SJonas Paulsson static void buildDefCFAReg(MachineBasicBlock &MBB,
390515bfc66SJonas Paulsson                            MachineBasicBlock::iterator MBBI,
391515bfc66SJonas Paulsson                            const DebugLoc &DL, unsigned Reg,
392515bfc66SJonas Paulsson                            const SystemZInstrInfo *ZII) {
393515bfc66SJonas Paulsson   MachineFunction &MF = *MBB.getParent();
394515bfc66SJonas Paulsson   MachineModuleInfo &MMI = MF.getMMI();
395515bfc66SJonas Paulsson   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
396515bfc66SJonas Paulsson   unsigned RegNum = MRI->getDwarfRegNum(Reg, true);
397515bfc66SJonas Paulsson   unsigned CFIIndex = MF.addFrameInst(
398515bfc66SJonas Paulsson                         MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));
399515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
400515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
401515bfc66SJonas Paulsson }
402515bfc66SJonas Paulsson 
40361b305edSQuentin Colombet void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
40461b305edSQuentin Colombet                                         MachineBasicBlock &MBB) const {
40561b305edSQuentin Colombet   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
406515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
407515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
408941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
409515bfc66SJonas Paulsson   auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo());
4105f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
4115f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.begin();
4125f613dfdSUlrich Weigand   MachineModuleInfo &MMI = MF.getMMI();
413bc07a890SBill Wendling   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
414941a705bSMatthias Braun   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
4155f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
416057c5a6bSOleg Ranevskyy 
41722f94291SUlrich Weigand   // In GHC calling convention C stack space, including the ABI-defined
41822f94291SUlrich Weigand   // 160-byte base area, is (de)allocated by GHC itself.  This stack space may
41922f94291SUlrich Weigand   // be used by LLVM as spill slots for the tail recursive GHC functions.  Thus
42022f94291SUlrich Weigand   // do not allocate stack space here, too.
42122f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC) {
42222f94291SUlrich Weigand     if (MFFrame.getStackSize() > 2048 * sizeof(long)) {
42322f94291SUlrich Weigand       report_fatal_error(
42422f94291SUlrich Weigand           "Pre allocated stack space for GHC function is too small");
42522f94291SUlrich Weigand     }
42622f94291SUlrich Weigand     if (HasFP) {
42722f94291SUlrich Weigand       report_fatal_error(
42822f94291SUlrich Weigand           "In GHC calling convention a frame pointer is not supported");
42922f94291SUlrich Weigand     }
43022f94291SUlrich Weigand     MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::CallFrameSize);
43122f94291SUlrich Weigand     return;
43222f94291SUlrich Weigand   }
43322f94291SUlrich Weigand 
434057c5a6bSOleg Ranevskyy   // Debug location must be unknown since the first debug location is used
435057c5a6bSOleg Ranevskyy   // to determine the end of the prologue.
436057c5a6bSOleg Ranevskyy   DebugLoc DL;
4375f613dfdSUlrich Weigand 
4385f613dfdSUlrich Weigand   // The current offset of the stack pointer from the CFA.
4395f613dfdSUlrich Weigand   int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
4405f613dfdSUlrich Weigand 
44161f5ba5cSJonas Paulsson   if (ZFI->getSpillGPRRegs().LowGPR) {
4425f613dfdSUlrich Weigand     // Skip over the GPR saves.
4435f613dfdSUlrich Weigand     if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
4445f613dfdSUlrich Weigand       ++MBBI;
4455f613dfdSUlrich Weigand     else
4465f613dfdSUlrich Weigand       llvm_unreachable("Couldn't skip over GPR saves");
4475f613dfdSUlrich Weigand 
4485f613dfdSUlrich Weigand     // Add CFI for the GPR saves.
44928c111ecSRichard Sandiford     for (auto &Save : CSI) {
45028c111ecSRichard Sandiford       unsigned Reg = Save.getReg();
4515f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg)) {
45261f5ba5cSJonas Paulsson         int FI = Save.getFrameIdx();
45361f5ba5cSJonas Paulsson         int64_t Offset = MFFrame.getObjectOffset(FI);
454f23ef437SMatthias Braun         unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
455b1f25f1bSRafael Espindola             nullptr, MRI->getDwarfRegNum(Reg, true), Offset));
456b1f25f1bSRafael Espindola         BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
457b1f25f1bSRafael Espindola             .addCFIIndex(CFIIndex);
4585f613dfdSUlrich Weigand       }
4595f613dfdSUlrich Weigand     }
4605f613dfdSUlrich Weigand   }
4615f613dfdSUlrich Weigand 
46232063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
46332063888SUlrich Weigand   // We need to allocate the ABI-defined 160-byte base area whenever
46432063888SUlrich Weigand   // we allocate stack space for our own use and whenever we call another
46532063888SUlrich Weigand   // function.
46661f5ba5cSJonas Paulsson   bool HasStackObject = false;
46761f5ba5cSJonas Paulsson   for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)
46861f5ba5cSJonas Paulsson     if (!MFFrame.isDeadObjectIndex(i)) {
46961f5ba5cSJonas Paulsson       HasStackObject = true;
47061f5ba5cSJonas Paulsson       break;
47132063888SUlrich Weigand     }
47261f5ba5cSJonas Paulsson   if (HasStackObject || MFFrame.hasCalls())
47361f5ba5cSJonas Paulsson     StackSize += SystemZMC::CallFrameSize;
47461f5ba5cSJonas Paulsson   // Don't allocate the incoming reg save area.
47561f5ba5cSJonas Paulsson   StackSize = StackSize > SystemZMC::CallFrameSize
47661f5ba5cSJonas Paulsson                   ? StackSize - SystemZMC::CallFrameSize
47761f5ba5cSJonas Paulsson                   : 0;
47861f5ba5cSJonas Paulsson   MFFrame.setStackSize(StackSize);
47932063888SUlrich Weigand 
4805f613dfdSUlrich Weigand   if (StackSize) {
481ad1482c6SMarcin Koscielnicki     // Determine if we want to store a backchain.
482f1caa283SMatthias Braun     bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
483ad1482c6SMarcin Koscielnicki 
484ad1482c6SMarcin Koscielnicki     // If we need backchain, save current stack pointer.  R1 is free at this
485ad1482c6SMarcin Koscielnicki     // point.
486ad1482c6SMarcin Koscielnicki     if (StoreBackchain)
487ad1482c6SMarcin Koscielnicki       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))
488ad1482c6SMarcin Koscielnicki         .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
489ad1482c6SMarcin Koscielnicki 
4905f613dfdSUlrich Weigand     // Allocate StackSize bytes.
4915f613dfdSUlrich Weigand     int64_t Delta = -int64_t(StackSize);
492515bfc66SJonas Paulsson     const unsigned ProbeSize = TLI.getStackProbeSize(MF);
493515bfc66SJonas Paulsson     bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&
494515bfc66SJonas Paulsson            (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);
495515bfc66SJonas Paulsson     if (!FreeProbe &&
496515bfc66SJonas Paulsson         MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {
497515bfc66SJonas Paulsson       // Stack probing may involve looping, but splitting the prologue block
498515bfc66SJonas Paulsson       // is not possible at this point since it would invalidate the
499515bfc66SJonas Paulsson       // SaveBlocks / RestoreBlocks sets of PEI in the single block function
500515bfc66SJonas Paulsson       // case. Build a pseudo to be handled later by inlineStackProbe().
501515bfc66SJonas Paulsson       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))
502515bfc66SJonas Paulsson         .addImm(StackSize);
503515bfc66SJonas Paulsson     }
504515bfc66SJonas Paulsson     else {
5055f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
506515bfc66SJonas Paulsson       buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);
507515bfc66SJonas Paulsson     }
5085f613dfdSUlrich Weigand     SPOffsetFromCFA += Delta;
509ad1482c6SMarcin Koscielnicki 
51082879c29SJonas Paulsson     if (StoreBackchain) {
51182879c29SJonas Paulsson       // The back chain is stored topmost with packed-stack.
51282879c29SJonas Paulsson       int Offset = usePackedStack(MF) ? SystemZMC::CallFrameSize - 8 : 0;
513ad1482c6SMarcin Koscielnicki       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
51482879c29SJonas Paulsson         .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
51582879c29SJonas Paulsson         .addImm(Offset).addReg(0);
51682879c29SJonas Paulsson     }
5175f613dfdSUlrich Weigand   }
5185f613dfdSUlrich Weigand 
5195f613dfdSUlrich Weigand   if (HasFP) {
5205f613dfdSUlrich Weigand     // Copy the base of the frame to R11.
5215f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
5225f613dfdSUlrich Weigand       .addReg(SystemZ::R15D);
5235f613dfdSUlrich Weigand 
5245f613dfdSUlrich Weigand     // Add CFI for the new frame location.
525515bfc66SJonas Paulsson     buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);
5265f613dfdSUlrich Weigand 
5275f613dfdSUlrich Weigand     // Mark the FramePtr as live at the beginning of every block except
5285f613dfdSUlrich Weigand     // the entry block.  (We'll have marked R11 as live on entry when
5295f613dfdSUlrich Weigand     // saving the GPRs.)
53028c111ecSRichard Sandiford     for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I)
5315f613dfdSUlrich Weigand       I->addLiveIn(SystemZ::R11D);
5325f613dfdSUlrich Weigand   }
5335f613dfdSUlrich Weigand 
5348b19be46SUlrich Weigand   // Skip over the FPR/VR saves.
535b1f25f1bSRafael Espindola   SmallVector<unsigned, 8> CFIIndexes;
53628c111ecSRichard Sandiford   for (auto &Save : CSI) {
53728c111ecSRichard Sandiford     unsigned Reg = Save.getReg();
5385f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
5395f613dfdSUlrich Weigand       if (MBBI != MBB.end() &&
5405f613dfdSUlrich Weigand           (MBBI->getOpcode() == SystemZ::STD ||
5415f613dfdSUlrich Weigand            MBBI->getOpcode() == SystemZ::STDY))
5425f613dfdSUlrich Weigand         ++MBBI;
5435f613dfdSUlrich Weigand       else
5445f613dfdSUlrich Weigand         llvm_unreachable("Couldn't skip over FPR save");
5458b19be46SUlrich Weigand     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
5468b19be46SUlrich Weigand       if (MBBI != MBB.end() &&
5478b19be46SUlrich Weigand           MBBI->getOpcode() == SystemZ::VST)
5488b19be46SUlrich Weigand         ++MBBI;
5498b19be46SUlrich Weigand       else
5508b19be46SUlrich Weigand         llvm_unreachable("Couldn't skip over VR save");
5518b19be46SUlrich Weigand     } else
5528b19be46SUlrich Weigand       continue;
5535f613dfdSUlrich Weigand 
5545f613dfdSUlrich Weigand     // Add CFI for the this save.
55528c111ecSRichard Sandiford     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
5562481f26aSMatt Arsenault     Register IgnoredFrameReg;
5575567bafeSJames Y Knight     int64_t Offset =
5585567bafeSJames Y Knight         getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg);
5595567bafeSJames Y Knight 
560f23ef437SMatthias Braun     unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
561b1f25f1bSRafael Espindola           nullptr, DwarfReg, SPOffsetFromCFA + Offset));
562b1f25f1bSRafael Espindola     CFIIndexes.push_back(CFIIndex);
5635f613dfdSUlrich Weigand   }
5648b19be46SUlrich Weigand   // Complete the CFI for the FPR/VR saves, modelling them as taking effect
5655f613dfdSUlrich Weigand   // after the last save.
566b1f25f1bSRafael Espindola   for (auto CFIIndex : CFIIndexes) {
567b1f25f1bSRafael Espindola     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
568b1f25f1bSRafael Espindola         .addCFIIndex(CFIIndex);
569b1f25f1bSRafael Espindola   }
5705f613dfdSUlrich Weigand }
5715f613dfdSUlrich Weigand 
5725f613dfdSUlrich Weigand void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
5735f613dfdSUlrich Weigand                                         MachineBasicBlock &MBB) const {
5745f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
575fc6de428SEric Christopher   auto *ZII =
576fc6de428SEric Christopher       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
5775f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
57832063888SUlrich Weigand   MachineFrameInfo &MFFrame = MF.getFrameInfo();
5795f613dfdSUlrich Weigand 
58022f94291SUlrich Weigand   // See SystemZFrameLowering::emitPrologue
58122f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC)
58222f94291SUlrich Weigand     return;
58322f94291SUlrich Weigand 
5845f613dfdSUlrich Weigand   // Skip the return instruction.
585709bda66SRichard Sandiford   assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
5865f613dfdSUlrich Weigand 
58732063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
58861f5ba5cSJonas Paulsson   if (ZFI->getRestoreGPRRegs().LowGPR) {
5895f613dfdSUlrich Weigand     --MBBI;
5905f613dfdSUlrich Weigand     unsigned Opcode = MBBI->getOpcode();
5915f613dfdSUlrich Weigand     if (Opcode != SystemZ::LMG)
5925f613dfdSUlrich Weigand       llvm_unreachable("Expected to see callee-save register restore code");
5935f613dfdSUlrich Weigand 
5945f613dfdSUlrich Weigand     unsigned AddrOpNo = 2;
5955f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
5965f613dfdSUlrich Weigand     uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
5975f613dfdSUlrich Weigand     unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
5985f613dfdSUlrich Weigand 
5995f613dfdSUlrich Weigand     // If the offset is too large, use the largest stack-aligned offset
6005f613dfdSUlrich Weigand     // and add the rest to the base register (the stack or frame pointer).
6015f613dfdSUlrich Weigand     if (!NewOpcode) {
6025f613dfdSUlrich Weigand       uint64_t NumBytes = Offset - 0x7fff8;
6035f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
6045f613dfdSUlrich Weigand                     NumBytes, ZII);
6055f613dfdSUlrich Weigand       Offset -= NumBytes;
6065f613dfdSUlrich Weigand       NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
6075f613dfdSUlrich Weigand       assert(NewOpcode && "No restore instruction available");
6085f613dfdSUlrich Weigand     }
6095f613dfdSUlrich Weigand 
6105f613dfdSUlrich Weigand     MBBI->setDesc(ZII->get(NewOpcode));
6115f613dfdSUlrich Weigand     MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
6125f613dfdSUlrich Weigand   } else if (StackSize) {
6135f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
6145f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
6155f613dfdSUlrich Weigand   }
6165f613dfdSUlrich Weigand }
6175f613dfdSUlrich Weigand 
618515bfc66SJonas Paulsson void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF,
619515bfc66SJonas Paulsson                                             MachineBasicBlock &PrologMBB) const {
620515bfc66SJonas Paulsson   auto *ZII =
621515bfc66SJonas Paulsson     static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
622515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
623515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
624515bfc66SJonas Paulsson 
625515bfc66SJonas Paulsson   MachineInstr *StackAllocMI = nullptr;
626515bfc66SJonas Paulsson   for (MachineInstr &MI : PrologMBB)
627515bfc66SJonas Paulsson     if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {
628515bfc66SJonas Paulsson       StackAllocMI = &MI;
629515bfc66SJonas Paulsson       break;
630515bfc66SJonas Paulsson     }
631515bfc66SJonas Paulsson   if (StackAllocMI == nullptr)
632515bfc66SJonas Paulsson     return;
633515bfc66SJonas Paulsson   uint64_t StackSize = StackAllocMI->getOperand(0).getImm();
634515bfc66SJonas Paulsson   const unsigned ProbeSize = TLI.getStackProbeSize(MF);
635515bfc66SJonas Paulsson   uint64_t NumFullBlocks = StackSize / ProbeSize;
636515bfc66SJonas Paulsson   uint64_t Residual = StackSize % ProbeSize;
637515bfc66SJonas Paulsson   int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
638515bfc66SJonas Paulsson   MachineBasicBlock *MBB = &PrologMBB;
639515bfc66SJonas Paulsson   MachineBasicBlock::iterator MBBI = StackAllocMI;
640515bfc66SJonas Paulsson   const DebugLoc DL = StackAllocMI->getDebugLoc();
641515bfc66SJonas Paulsson 
642515bfc66SJonas Paulsson   // Allocate a block of Size bytes on the stack and probe it.
643515bfc66SJonas Paulsson   auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,
644515bfc66SJonas Paulsson                               MachineBasicBlock::iterator InsPt, unsigned Size,
645515bfc66SJonas Paulsson                               bool EmitCFI) -> void {
646515bfc66SJonas Paulsson     emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);
647515bfc66SJonas Paulsson     if (EmitCFI) {
648515bfc66SJonas Paulsson       SPOffsetFromCFA -= Size;
649515bfc66SJonas Paulsson       buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);
650515bfc66SJonas Paulsson     }
651515bfc66SJonas Paulsson     // Probe by means of a volatile compare.
652515bfc66SJonas Paulsson     MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),
653515bfc66SJonas Paulsson       MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));
654515bfc66SJonas Paulsson     BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))
655515bfc66SJonas Paulsson       .addReg(SystemZ::R0D, RegState::Undef)
656515bfc66SJonas Paulsson       .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)
657515bfc66SJonas Paulsson       .addMemOperand(MMO);
658515bfc66SJonas Paulsson   };
659515bfc66SJonas Paulsson 
660515bfc66SJonas Paulsson   if (NumFullBlocks < 3) {
661515bfc66SJonas Paulsson     // Emit unrolled probe statements.
662515bfc66SJonas Paulsson     for (unsigned int i = 0; i < NumFullBlocks; i++)
663515bfc66SJonas Paulsson       allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);
664515bfc66SJonas Paulsson   } else {
665515bfc66SJonas Paulsson     // Emit a loop probing the pages.
666515bfc66SJonas Paulsson     uint64_t LoopAlloc = ProbeSize * NumFullBlocks;
667515bfc66SJonas Paulsson     SPOffsetFromCFA -= LoopAlloc;
668515bfc66SJonas Paulsson 
669515bfc66SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R1D)
670515bfc66SJonas Paulsson       .addReg(SystemZ::R15D);
671515bfc66SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R1D, ZII);
672515bfc66SJonas Paulsson     emitIncrement(*MBB, MBBI, DL, SystemZ::R1D, -int64_t(LoopAlloc), ZII);
673515bfc66SJonas Paulsson     buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::CallFrameSize + LoopAlloc),
674515bfc66SJonas Paulsson                  ZII);
675515bfc66SJonas Paulsson 
676515bfc66SJonas Paulsson     MachineBasicBlock *DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);
677515bfc66SJonas Paulsson     MachineBasicBlock *LoopMBB = SystemZ::emitBlockAfter(MBB);
678515bfc66SJonas Paulsson     MBB->addSuccessor(LoopMBB);
679515bfc66SJonas Paulsson     LoopMBB->addSuccessor(LoopMBB);
680515bfc66SJonas Paulsson     LoopMBB->addSuccessor(DoneMBB);
681515bfc66SJonas Paulsson 
682515bfc66SJonas Paulsson     MBB = LoopMBB;
683515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);
684515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))
685515bfc66SJonas Paulsson       .addReg(SystemZ::R15D).addReg(SystemZ::R1D);
686515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))
687515bfc66SJonas Paulsson       .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);
688515bfc66SJonas Paulsson 
689515bfc66SJonas Paulsson     MBB = DoneMBB;
690515bfc66SJonas Paulsson     MBBI = DoneMBB->begin();
691515bfc66SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);
692515bfc66SJonas Paulsson 
693515bfc66SJonas Paulsson     recomputeLiveIns(*DoneMBB);
694515bfc66SJonas Paulsson     recomputeLiveIns(*LoopMBB);
695515bfc66SJonas Paulsson   }
696515bfc66SJonas Paulsson 
697515bfc66SJonas Paulsson   if (Residual)
698515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);
699515bfc66SJonas Paulsson 
700515bfc66SJonas Paulsson   StackAllocMI->eraseFromParent();
701515bfc66SJonas Paulsson }
702515bfc66SJonas Paulsson 
7035f613dfdSUlrich Weigand bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
7045f613dfdSUlrich Weigand   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
705941a705bSMatthias Braun           MF.getFrameInfo().hasVarSizedObjects() ||
7065f613dfdSUlrich Weigand           MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP());
7075f613dfdSUlrich Weigand }
7085f613dfdSUlrich Weigand 
7095f613dfdSUlrich Weigand bool
7105f613dfdSUlrich Weigand SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
7115f613dfdSUlrich Weigand   // The ABI requires us to allocate 160 bytes of stack space for the callee,
7125f613dfdSUlrich Weigand   // with any outgoing stack arguments being placed above that.  It seems
7135f613dfdSUlrich Weigand   // better to make that area a permanent feature of the frame even if
7145f613dfdSUlrich Weigand   // we're using a frame pointer.
7155f613dfdSUlrich Weigand   return true;
7165f613dfdSUlrich Weigand }
7175f613dfdSUlrich Weigand 
71861f5ba5cSJonas Paulsson int SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF,
71961f5ba5cSJonas Paulsson                                                  int FI,
7202481f26aSMatt Arsenault                                                  Register &FrameReg) const {
72161f5ba5cSJonas Paulsson   // Our incoming SP is actually SystemZMC::CallFrameSize below the CFA, so
72261f5ba5cSJonas Paulsson   // add that difference here.
72361f5ba5cSJonas Paulsson   int64_t Offset =
72461f5ba5cSJonas Paulsson     TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);
72561f5ba5cSJonas Paulsson   return Offset + SystemZMC::CallFrameSize;
72661f5ba5cSJonas Paulsson }
72761f5ba5cSJonas Paulsson 
728e1a2e90fSHans Wennborg MachineBasicBlock::iterator SystemZFrameLowering::
7295f613dfdSUlrich Weigand eliminateCallFramePseudoInstr(MachineFunction &MF,
7305f613dfdSUlrich Weigand                               MachineBasicBlock &MBB,
7315f613dfdSUlrich Weigand                               MachineBasicBlock::iterator MI) const {
7325f613dfdSUlrich Weigand   switch (MI->getOpcode()) {
7335f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKDOWN:
7345f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKUP:
7355f613dfdSUlrich Weigand     assert(hasReservedCallFrame(MF) &&
7365f613dfdSUlrich Weigand            "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
737e1a2e90fSHans Wennborg     return MBB.erase(MI);
7385f613dfdSUlrich Weigand     break;
7395f613dfdSUlrich Weigand 
7405f613dfdSUlrich Weigand   default:
7415f613dfdSUlrich Weigand     llvm_unreachable("Unexpected call frame instruction");
7425f613dfdSUlrich Weigand   }
7435f613dfdSUlrich Weigand }
74461f5ba5cSJonas Paulsson 
74582879c29SJonas Paulsson unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF,
7462481f26aSMatt Arsenault                                                  Register Reg) const {
74782879c29SJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
74882879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
74982879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
75082879c29SJonas Paulsson   unsigned Offset = RegSpillOffsets[Reg];
75182879c29SJonas Paulsson   if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
75282879c29SJonas Paulsson     if (SystemZ::GR64BitRegClass.contains(Reg))
75382879c29SJonas Paulsson       // Put all GPRs at the top of the Register save area with packed
75482879c29SJonas Paulsson       // stack. Make room for the backchain if needed.
75582879c29SJonas Paulsson       Offset += BackChain ? 24 : 32;
75682879c29SJonas Paulsson     else
75782879c29SJonas Paulsson       Offset = 0;
75882879c29SJonas Paulsson   }
75982879c29SJonas Paulsson   return Offset;
76082879c29SJonas Paulsson }
76182879c29SJonas Paulsson 
76261f5ba5cSJonas Paulsson int SystemZFrameLowering::
76361f5ba5cSJonas Paulsson getOrCreateFramePointerSaveIndex(MachineFunction &MF) const {
76461f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
76561f5ba5cSJonas Paulsson   int FI = ZFI->getFramePointerSaveIndex();
76661f5ba5cSJonas Paulsson   if (!FI) {
76761f5ba5cSJonas Paulsson     MachineFrameInfo &MFFrame = MF.getFrameInfo();
76882879c29SJonas Paulsson     // The back chain is stored topmost with packed-stack.
76982879c29SJonas Paulsson     int Offset = usePackedStack(MF) ? -8 : -SystemZMC::CallFrameSize;
77082879c29SJonas Paulsson     FI = MFFrame.CreateFixedObject(8, Offset, false);
77161f5ba5cSJonas Paulsson     ZFI->setFramePointerSaveIndex(FI);
77261f5ba5cSJonas Paulsson   }
77361f5ba5cSJonas Paulsson   return FI;
77461f5ba5cSJonas Paulsson }
77582879c29SJonas Paulsson 
77682879c29SJonas Paulsson bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const {
77782879c29SJonas Paulsson   bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
77882879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
77982879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
78082879c29SJonas Paulsson   if (HasPackedStackAttr && BackChain && !SoftFloat)
78182879c29SJonas Paulsson     report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
78282879c29SJonas Paulsson   bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
78382879c29SJonas Paulsson   return HasPackedStackAttr && CallConv;
78482879c29SJonas Paulsson }
785