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();
3191606755dSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
3201606755dSJonas Paulsson   MachineRegisterInfo *MRI = &MF.getRegInfo();
32123762575SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
32261f5ba5cSJonas Paulsson 
32323762575SJonas Paulsson   if (!usePackedStack(MF) || BackChain)
32423762575SJonas Paulsson     // Create the incoming register save area.
32561f5ba5cSJonas Paulsson     getOrCreateFramePointerSaveIndex(MF);
32661f5ba5cSJonas Paulsson 
327af98b748SUlrich Weigand   // Get the size of our stack frame to be allocated ...
328af98b748SUlrich Weigand   uint64_t StackSize = (MFFrame.estimateStackSize(MF) +
329af98b748SUlrich Weigand                         SystemZMC::CallFrameSize);
330af98b748SUlrich Weigand   // ... and the maximum offset we may need to reach into the
331af98b748SUlrich Weigand   // caller's frame to access the save area or stack arguments.
33261f5ba5cSJonas Paulsson   int64_t MaxArgOffset = 0;
333af98b748SUlrich Weigand   for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)
334af98b748SUlrich Weigand     if (MFFrame.getObjectOffset(I) >= 0) {
33561f5ba5cSJonas Paulsson       int64_t ArgOffset = MFFrame.getObjectOffset(I) +
336af98b748SUlrich Weigand                           MFFrame.getObjectSize(I);
337af98b748SUlrich Weigand       MaxArgOffset = std::max(MaxArgOffset, ArgOffset);
338af98b748SUlrich Weigand     }
339af98b748SUlrich Weigand 
340af98b748SUlrich Weigand   uint64_t MaxReach = StackSize + MaxArgOffset;
34123943229SRichard Sandiford   if (!isUInt<12>(MaxReach)) {
34223943229SRichard Sandiford     // We may need register scavenging slots if some parts of the frame
3435dd52f8cSRichard Sandiford     // are outside the reach of an unsigned 12-bit displacement.
34423943229SRichard Sandiford     // Create 2 for the case where both addresses in an MVC are
34523943229SRichard Sandiford     // out of range.
34628de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
34728de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
34823943229SRichard Sandiford   }
3491606755dSJonas Paulsson 
3501606755dSJonas Paulsson   // If R6 is used as an argument register it is still callee saved. If it in
3511606755dSJonas Paulsson   // this case is not clobbered (and restored) it should never be marked as
3521606755dSJonas Paulsson   // killed.
3531606755dSJonas Paulsson   if (MF.front().isLiveIn(SystemZ::R6D) &&
3541606755dSJonas Paulsson       ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D)
3551606755dSJonas Paulsson     for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))
3561606755dSJonas Paulsson       MO.setIsKill(false);
3575dd52f8cSRichard Sandiford }
3585dd52f8cSRichard Sandiford 
3595f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
3605f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB,
3612481f26aSMatt Arsenault                           MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,
3622481f26aSMatt Arsenault                           Register Reg, int64_t NumBytes,
3635f613dfdSUlrich Weigand                           const TargetInstrInfo *TII) {
3645f613dfdSUlrich Weigand   while (NumBytes) {
3655f613dfdSUlrich Weigand     unsigned Opcode;
3665f613dfdSUlrich Weigand     int64_t ThisVal = NumBytes;
3675f613dfdSUlrich Weigand     if (isInt<16>(NumBytes))
3685f613dfdSUlrich Weigand       Opcode = SystemZ::AGHI;
3695f613dfdSUlrich Weigand     else {
3705f613dfdSUlrich Weigand       Opcode = SystemZ::AGFI;
3715f613dfdSUlrich Weigand       // Make sure we maintain 8-byte stack alignment.
372fffd56ecSAlexey Samsonov       int64_t MinVal = -uint64_t(1) << 31;
3735f613dfdSUlrich Weigand       int64_t MaxVal = (int64_t(1) << 31) - 8;
3745f613dfdSUlrich Weigand       if (ThisVal < MinVal)
3755f613dfdSUlrich Weigand         ThisVal = MinVal;
3765f613dfdSUlrich Weigand       else if (ThisVal > MaxVal)
3775f613dfdSUlrich Weigand         ThisVal = MaxVal;
3785f613dfdSUlrich Weigand     }
3795f613dfdSUlrich Weigand     MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
3805f613dfdSUlrich Weigand       .addReg(Reg).addImm(ThisVal);
38114a44495SRichard Sandiford     // The CC implicit def is dead.
3825f613dfdSUlrich Weigand     MI->getOperand(3).setIsDead();
3835f613dfdSUlrich Weigand     NumBytes -= ThisVal;
3845f613dfdSUlrich Weigand   }
3855f613dfdSUlrich Weigand }
3865f613dfdSUlrich Weigand 
387515bfc66SJonas Paulsson // Add CFI for the new CFA offset.
388515bfc66SJonas Paulsson static void buildCFAOffs(MachineBasicBlock &MBB,
389515bfc66SJonas Paulsson                          MachineBasicBlock::iterator MBBI,
390515bfc66SJonas Paulsson                          const DebugLoc &DL, int Offset,
391515bfc66SJonas Paulsson                          const SystemZInstrInfo *ZII) {
392515bfc66SJonas Paulsson   unsigned CFIIndex = MBB.getParent()->addFrameInst(
393515bfc66SJonas Paulsson     MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));
394515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
395515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
396515bfc66SJonas Paulsson }
397515bfc66SJonas Paulsson 
398515bfc66SJonas Paulsson // Add CFI for the new frame location.
399515bfc66SJonas Paulsson static void buildDefCFAReg(MachineBasicBlock &MBB,
400515bfc66SJonas Paulsson                            MachineBasicBlock::iterator MBBI,
401515bfc66SJonas Paulsson                            const DebugLoc &DL, unsigned Reg,
402515bfc66SJonas Paulsson                            const SystemZInstrInfo *ZII) {
403515bfc66SJonas Paulsson   MachineFunction &MF = *MBB.getParent();
404515bfc66SJonas Paulsson   MachineModuleInfo &MMI = MF.getMMI();
405515bfc66SJonas Paulsson   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
406515bfc66SJonas Paulsson   unsigned RegNum = MRI->getDwarfRegNum(Reg, true);
407515bfc66SJonas Paulsson   unsigned CFIIndex = MF.addFrameInst(
408515bfc66SJonas Paulsson                         MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));
409515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
410515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
411515bfc66SJonas Paulsson }
412515bfc66SJonas Paulsson 
41361b305edSQuentin Colombet void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
41461b305edSQuentin Colombet                                         MachineBasicBlock &MBB) const {
41561b305edSQuentin Colombet   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
416515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
417515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
418941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
419515bfc66SJonas Paulsson   auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo());
4205f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
4215f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.begin();
4225f613dfdSUlrich Weigand   MachineModuleInfo &MMI = MF.getMMI();
423bc07a890SBill Wendling   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
424941a705bSMatthias Braun   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
4255f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
426057c5a6bSOleg Ranevskyy 
42722f94291SUlrich Weigand   // In GHC calling convention C stack space, including the ABI-defined
42822f94291SUlrich Weigand   // 160-byte base area, is (de)allocated by GHC itself.  This stack space may
42922f94291SUlrich Weigand   // be used by LLVM as spill slots for the tail recursive GHC functions.  Thus
43022f94291SUlrich Weigand   // do not allocate stack space here, too.
43122f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC) {
43222f94291SUlrich Weigand     if (MFFrame.getStackSize() > 2048 * sizeof(long)) {
43322f94291SUlrich Weigand       report_fatal_error(
43422f94291SUlrich Weigand           "Pre allocated stack space for GHC function is too small");
43522f94291SUlrich Weigand     }
43622f94291SUlrich Weigand     if (HasFP) {
43722f94291SUlrich Weigand       report_fatal_error(
43822f94291SUlrich Weigand           "In GHC calling convention a frame pointer is not supported");
43922f94291SUlrich Weigand     }
44022f94291SUlrich Weigand     MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::CallFrameSize);
44122f94291SUlrich Weigand     return;
44222f94291SUlrich Weigand   }
44322f94291SUlrich Weigand 
444057c5a6bSOleg Ranevskyy   // Debug location must be unknown since the first debug location is used
445057c5a6bSOleg Ranevskyy   // to determine the end of the prologue.
446057c5a6bSOleg Ranevskyy   DebugLoc DL;
4475f613dfdSUlrich Weigand 
4485f613dfdSUlrich Weigand   // The current offset of the stack pointer from the CFA.
4495f613dfdSUlrich Weigand   int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
4505f613dfdSUlrich Weigand 
45161f5ba5cSJonas Paulsson   if (ZFI->getSpillGPRRegs().LowGPR) {
4525f613dfdSUlrich Weigand     // Skip over the GPR saves.
4535f613dfdSUlrich Weigand     if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
4545f613dfdSUlrich Weigand       ++MBBI;
4555f613dfdSUlrich Weigand     else
4565f613dfdSUlrich Weigand       llvm_unreachable("Couldn't skip over GPR saves");
4575f613dfdSUlrich Weigand 
4585f613dfdSUlrich Weigand     // Add CFI for the GPR saves.
45928c111ecSRichard Sandiford     for (auto &Save : CSI) {
46028c111ecSRichard Sandiford       unsigned Reg = Save.getReg();
4615f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg)) {
46261f5ba5cSJonas Paulsson         int FI = Save.getFrameIdx();
46361f5ba5cSJonas Paulsson         int64_t Offset = MFFrame.getObjectOffset(FI);
464f23ef437SMatthias Braun         unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
465b1f25f1bSRafael Espindola             nullptr, MRI->getDwarfRegNum(Reg, true), Offset));
466b1f25f1bSRafael Espindola         BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
467b1f25f1bSRafael Espindola             .addCFIIndex(CFIIndex);
4685f613dfdSUlrich Weigand       }
4695f613dfdSUlrich Weigand     }
4705f613dfdSUlrich Weigand   }
4715f613dfdSUlrich Weigand 
47232063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
47332063888SUlrich Weigand   // We need to allocate the ABI-defined 160-byte base area whenever
47432063888SUlrich Weigand   // we allocate stack space for our own use and whenever we call another
47532063888SUlrich Weigand   // function.
47661f5ba5cSJonas Paulsson   bool HasStackObject = false;
47761f5ba5cSJonas Paulsson   for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)
47861f5ba5cSJonas Paulsson     if (!MFFrame.isDeadObjectIndex(i)) {
47961f5ba5cSJonas Paulsson       HasStackObject = true;
48061f5ba5cSJonas Paulsson       break;
48132063888SUlrich Weigand     }
48261f5ba5cSJonas Paulsson   if (HasStackObject || MFFrame.hasCalls())
48361f5ba5cSJonas Paulsson     StackSize += SystemZMC::CallFrameSize;
48461f5ba5cSJonas Paulsson   // Don't allocate the incoming reg save area.
48561f5ba5cSJonas Paulsson   StackSize = StackSize > SystemZMC::CallFrameSize
48661f5ba5cSJonas Paulsson                   ? StackSize - SystemZMC::CallFrameSize
48761f5ba5cSJonas Paulsson                   : 0;
48861f5ba5cSJonas Paulsson   MFFrame.setStackSize(StackSize);
48932063888SUlrich Weigand 
4905f613dfdSUlrich Weigand   if (StackSize) {
4915f613dfdSUlrich Weigand     // Allocate StackSize bytes.
4925f613dfdSUlrich Weigand     int64_t Delta = -int64_t(StackSize);
493515bfc66SJonas Paulsson     const unsigned ProbeSize = TLI.getStackProbeSize(MF);
494515bfc66SJonas Paulsson     bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&
495515bfc66SJonas Paulsson            (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);
496515bfc66SJonas Paulsson     if (!FreeProbe &&
497515bfc66SJonas Paulsson         MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {
498515bfc66SJonas Paulsson       // Stack probing may involve looping, but splitting the prologue block
499515bfc66SJonas Paulsson       // is not possible at this point since it would invalidate the
500515bfc66SJonas Paulsson       // SaveBlocks / RestoreBlocks sets of PEI in the single block function
501515bfc66SJonas Paulsson       // case. Build a pseudo to be handled later by inlineStackProbe().
502515bfc66SJonas Paulsson       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))
503515bfc66SJonas Paulsson         .addImm(StackSize);
504515bfc66SJonas Paulsson     }
505515bfc66SJonas Paulsson     else {
50642f628c8SJonas Paulsson       bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
50742f628c8SJonas Paulsson       // If we need backchain, save current stack pointer.  R1 is free at
50842f628c8SJonas Paulsson       // this point.
50942f628c8SJonas Paulsson       if (StoreBackchain)
51042f628c8SJonas Paulsson         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))
51142f628c8SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
5125f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
513515bfc66SJonas Paulsson       buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);
514*653b9769SJonas Paulsson       if (StoreBackchain)
515ad1482c6SMarcin Koscielnicki         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
51682879c29SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
517*653b9769SJonas Paulsson           .addImm(getBackchainOffset(MF)).addReg(0);
5185f613dfdSUlrich Weigand     }
51942f628c8SJonas Paulsson     SPOffsetFromCFA += Delta;
52042f628c8SJonas Paulsson   }
5215f613dfdSUlrich Weigand 
5225f613dfdSUlrich Weigand   if (HasFP) {
5235f613dfdSUlrich Weigand     // Copy the base of the frame to R11.
5245f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
5255f613dfdSUlrich Weigand       .addReg(SystemZ::R15D);
5265f613dfdSUlrich Weigand 
5275f613dfdSUlrich Weigand     // Add CFI for the new frame location.
528515bfc66SJonas Paulsson     buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);
5295f613dfdSUlrich Weigand 
5305f613dfdSUlrich Weigand     // Mark the FramePtr as live at the beginning of every block except
5315f613dfdSUlrich Weigand     // the entry block.  (We'll have marked R11 as live on entry when
5325f613dfdSUlrich Weigand     // saving the GPRs.)
53328c111ecSRichard Sandiford     for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I)
5345f613dfdSUlrich Weigand       I->addLiveIn(SystemZ::R11D);
5355f613dfdSUlrich Weigand   }
5365f613dfdSUlrich Weigand 
5378b19be46SUlrich Weigand   // Skip over the FPR/VR saves.
538b1f25f1bSRafael Espindola   SmallVector<unsigned, 8> CFIIndexes;
53928c111ecSRichard Sandiford   for (auto &Save : CSI) {
54028c111ecSRichard Sandiford     unsigned Reg = Save.getReg();
5415f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
5425f613dfdSUlrich Weigand       if (MBBI != MBB.end() &&
5435f613dfdSUlrich Weigand           (MBBI->getOpcode() == SystemZ::STD ||
5445f613dfdSUlrich Weigand            MBBI->getOpcode() == SystemZ::STDY))
5455f613dfdSUlrich Weigand         ++MBBI;
5465f613dfdSUlrich Weigand       else
5475f613dfdSUlrich Weigand         llvm_unreachable("Couldn't skip over FPR save");
5488b19be46SUlrich Weigand     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
5498b19be46SUlrich Weigand       if (MBBI != MBB.end() &&
5508b19be46SUlrich Weigand           MBBI->getOpcode() == SystemZ::VST)
5518b19be46SUlrich Weigand         ++MBBI;
5528b19be46SUlrich Weigand       else
5538b19be46SUlrich Weigand         llvm_unreachable("Couldn't skip over VR save");
5548b19be46SUlrich Weigand     } else
5558b19be46SUlrich Weigand       continue;
5565f613dfdSUlrich Weigand 
5575f613dfdSUlrich Weigand     // Add CFI for the this save.
55828c111ecSRichard Sandiford     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
5592481f26aSMatt Arsenault     Register IgnoredFrameReg;
5605567bafeSJames Y Knight     int64_t Offset =
561d57bba7cSSander de Smalen         getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg)
562d57bba7cSSander de Smalen             .getFixed();
5635567bafeSJames Y Knight 
564f23ef437SMatthias Braun     unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
565b1f25f1bSRafael Espindola           nullptr, DwarfReg, SPOffsetFromCFA + Offset));
566b1f25f1bSRafael Espindola     CFIIndexes.push_back(CFIIndex);
5675f613dfdSUlrich Weigand   }
5688b19be46SUlrich Weigand   // Complete the CFI for the FPR/VR saves, modelling them as taking effect
5695f613dfdSUlrich Weigand   // after the last save.
570b1f25f1bSRafael Espindola   for (auto CFIIndex : CFIIndexes) {
571b1f25f1bSRafael Espindola     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
572b1f25f1bSRafael Espindola         .addCFIIndex(CFIIndex);
573b1f25f1bSRafael Espindola   }
5745f613dfdSUlrich Weigand }
5755f613dfdSUlrich Weigand 
5765f613dfdSUlrich Weigand void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
5775f613dfdSUlrich Weigand                                         MachineBasicBlock &MBB) const {
5785f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
579fc6de428SEric Christopher   auto *ZII =
580fc6de428SEric Christopher       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
5815f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
58232063888SUlrich Weigand   MachineFrameInfo &MFFrame = MF.getFrameInfo();
5835f613dfdSUlrich Weigand 
58422f94291SUlrich Weigand   // See SystemZFrameLowering::emitPrologue
58522f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC)
58622f94291SUlrich Weigand     return;
58722f94291SUlrich Weigand 
5885f613dfdSUlrich Weigand   // Skip the return instruction.
589709bda66SRichard Sandiford   assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
5905f613dfdSUlrich Weigand 
59132063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
59261f5ba5cSJonas Paulsson   if (ZFI->getRestoreGPRRegs().LowGPR) {
5935f613dfdSUlrich Weigand     --MBBI;
5945f613dfdSUlrich Weigand     unsigned Opcode = MBBI->getOpcode();
5955f613dfdSUlrich Weigand     if (Opcode != SystemZ::LMG)
5965f613dfdSUlrich Weigand       llvm_unreachable("Expected to see callee-save register restore code");
5975f613dfdSUlrich Weigand 
5985f613dfdSUlrich Weigand     unsigned AddrOpNo = 2;
5995f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
6005f613dfdSUlrich Weigand     uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
6015f613dfdSUlrich Weigand     unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
6025f613dfdSUlrich Weigand 
6035f613dfdSUlrich Weigand     // If the offset is too large, use the largest stack-aligned offset
6045f613dfdSUlrich Weigand     // and add the rest to the base register (the stack or frame pointer).
6055f613dfdSUlrich Weigand     if (!NewOpcode) {
6065f613dfdSUlrich Weigand       uint64_t NumBytes = Offset - 0x7fff8;
6075f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
6085f613dfdSUlrich Weigand                     NumBytes, ZII);
6095f613dfdSUlrich Weigand       Offset -= NumBytes;
6105f613dfdSUlrich Weigand       NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
6115f613dfdSUlrich Weigand       assert(NewOpcode && "No restore instruction available");
6125f613dfdSUlrich Weigand     }
6135f613dfdSUlrich Weigand 
6145f613dfdSUlrich Weigand     MBBI->setDesc(ZII->get(NewOpcode));
6155f613dfdSUlrich Weigand     MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
6165f613dfdSUlrich Weigand   } else if (StackSize) {
6175f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
6185f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
6195f613dfdSUlrich Weigand   }
6205f613dfdSUlrich Weigand }
6215f613dfdSUlrich Weigand 
622515bfc66SJonas Paulsson void SystemZFrameLowering::inlineStackProbe(MachineFunction &MF,
623515bfc66SJonas Paulsson                                             MachineBasicBlock &PrologMBB) const {
624515bfc66SJonas Paulsson   auto *ZII =
625515bfc66SJonas Paulsson     static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
626515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
627515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
628515bfc66SJonas Paulsson 
629515bfc66SJonas Paulsson   MachineInstr *StackAllocMI = nullptr;
630515bfc66SJonas Paulsson   for (MachineInstr &MI : PrologMBB)
631515bfc66SJonas Paulsson     if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {
632515bfc66SJonas Paulsson       StackAllocMI = &MI;
633515bfc66SJonas Paulsson       break;
634515bfc66SJonas Paulsson     }
635515bfc66SJonas Paulsson   if (StackAllocMI == nullptr)
636515bfc66SJonas Paulsson     return;
637515bfc66SJonas Paulsson   uint64_t StackSize = StackAllocMI->getOperand(0).getImm();
638515bfc66SJonas Paulsson   const unsigned ProbeSize = TLI.getStackProbeSize(MF);
639515bfc66SJonas Paulsson   uint64_t NumFullBlocks = StackSize / ProbeSize;
640515bfc66SJonas Paulsson   uint64_t Residual = StackSize % ProbeSize;
641515bfc66SJonas Paulsson   int64_t SPOffsetFromCFA = -SystemZMC::CFAOffsetFromInitialSP;
642515bfc66SJonas Paulsson   MachineBasicBlock *MBB = &PrologMBB;
643515bfc66SJonas Paulsson   MachineBasicBlock::iterator MBBI = StackAllocMI;
644515bfc66SJonas Paulsson   const DebugLoc DL = StackAllocMI->getDebugLoc();
645515bfc66SJonas Paulsson 
646515bfc66SJonas Paulsson   // Allocate a block of Size bytes on the stack and probe it.
647515bfc66SJonas Paulsson   auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,
648515bfc66SJonas Paulsson                               MachineBasicBlock::iterator InsPt, unsigned Size,
649515bfc66SJonas Paulsson                               bool EmitCFI) -> void {
650515bfc66SJonas Paulsson     emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);
651515bfc66SJonas Paulsson     if (EmitCFI) {
652515bfc66SJonas Paulsson       SPOffsetFromCFA -= Size;
653515bfc66SJonas Paulsson       buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);
654515bfc66SJonas Paulsson     }
655515bfc66SJonas Paulsson     // Probe by means of a volatile compare.
656515bfc66SJonas Paulsson     MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),
657515bfc66SJonas Paulsson       MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));
658515bfc66SJonas Paulsson     BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))
659515bfc66SJonas Paulsson       .addReg(SystemZ::R0D, RegState::Undef)
660515bfc66SJonas Paulsson       .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)
661515bfc66SJonas Paulsson       .addMemOperand(MMO);
662515bfc66SJonas Paulsson   };
663515bfc66SJonas Paulsson 
66442f628c8SJonas Paulsson   bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
66542f628c8SJonas Paulsson   if (StoreBackchain)
66642f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))
66742f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
66842f628c8SJonas Paulsson 
66942f628c8SJonas Paulsson   MachineBasicBlock *DoneMBB = nullptr;
67042f628c8SJonas Paulsson   MachineBasicBlock *LoopMBB = nullptr;
671515bfc66SJonas Paulsson   if (NumFullBlocks < 3) {
672515bfc66SJonas Paulsson     // Emit unrolled probe statements.
673515bfc66SJonas Paulsson     for (unsigned int i = 0; i < NumFullBlocks; i++)
674515bfc66SJonas Paulsson       allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);
675515bfc66SJonas Paulsson   } else {
676515bfc66SJonas Paulsson     // Emit a loop probing the pages.
677515bfc66SJonas Paulsson     uint64_t LoopAlloc = ProbeSize * NumFullBlocks;
678515bfc66SJonas Paulsson     SPOffsetFromCFA -= LoopAlloc;
679515bfc66SJonas Paulsson 
68042f628c8SJonas Paulsson     // Use R0D to hold the exit value.
68142f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)
682515bfc66SJonas Paulsson       .addReg(SystemZ::R15D);
68342f628c8SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII);
68442f628c8SJonas Paulsson     emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII);
685515bfc66SJonas Paulsson     buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::CallFrameSize + LoopAlloc),
686515bfc66SJonas Paulsson                  ZII);
687515bfc66SJonas Paulsson 
68842f628c8SJonas Paulsson     DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);
68942f628c8SJonas Paulsson     LoopMBB = SystemZ::emitBlockAfter(MBB);
690515bfc66SJonas Paulsson     MBB->addSuccessor(LoopMBB);
691515bfc66SJonas Paulsson     LoopMBB->addSuccessor(LoopMBB);
692515bfc66SJonas Paulsson     LoopMBB->addSuccessor(DoneMBB);
693515bfc66SJonas Paulsson 
694515bfc66SJonas Paulsson     MBB = LoopMBB;
695515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);
696515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))
69742f628c8SJonas Paulsson       .addReg(SystemZ::R15D).addReg(SystemZ::R0D);
698515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))
699515bfc66SJonas Paulsson       .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);
700515bfc66SJonas Paulsson 
701515bfc66SJonas Paulsson     MBB = DoneMBB;
702515bfc66SJonas Paulsson     MBBI = DoneMBB->begin();
703515bfc66SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);
704515bfc66SJonas Paulsson   }
705515bfc66SJonas Paulsson 
706515bfc66SJonas Paulsson   if (Residual)
707515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);
708515bfc66SJonas Paulsson 
709*653b9769SJonas Paulsson   if (StoreBackchain)
71042f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG))
71142f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
712*653b9769SJonas Paulsson       .addImm(getBackchainOffset(MF)).addReg(0);
71342f628c8SJonas Paulsson 
714515bfc66SJonas Paulsson   StackAllocMI->eraseFromParent();
71542f628c8SJonas Paulsson   if (DoneMBB != nullptr) {
71642f628c8SJonas Paulsson     // Compute the live-in lists for the new blocks.
71742f628c8SJonas Paulsson     recomputeLiveIns(*DoneMBB);
71842f628c8SJonas Paulsson     recomputeLiveIns(*LoopMBB);
71942f628c8SJonas Paulsson   }
720515bfc66SJonas Paulsson }
721515bfc66SJonas Paulsson 
7225f613dfdSUlrich Weigand bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
7235f613dfdSUlrich Weigand   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
724941a705bSMatthias Braun           MF.getFrameInfo().hasVarSizedObjects() ||
7255f613dfdSUlrich Weigand           MF.getInfo<SystemZMachineFunctionInfo>()->getManipulatesSP());
7265f613dfdSUlrich Weigand }
7275f613dfdSUlrich Weigand 
7285f613dfdSUlrich Weigand bool
7295f613dfdSUlrich Weigand SystemZFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
7305f613dfdSUlrich Weigand   // The ABI requires us to allocate 160 bytes of stack space for the callee,
7315f613dfdSUlrich Weigand   // with any outgoing stack arguments being placed above that.  It seems
7325f613dfdSUlrich Weigand   // better to make that area a permanent feature of the frame even if
7335f613dfdSUlrich Weigand   // we're using a frame pointer.
7345f613dfdSUlrich Weigand   return true;
7355f613dfdSUlrich Weigand }
7365f613dfdSUlrich Weigand 
737d57bba7cSSander de Smalen StackOffset
738d57bba7cSSander de Smalen SystemZFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
7392481f26aSMatt Arsenault                                              Register &FrameReg) const {
74061f5ba5cSJonas Paulsson   // Our incoming SP is actually SystemZMC::CallFrameSize below the CFA, so
74161f5ba5cSJonas Paulsson   // add that difference here.
742d57bba7cSSander de Smalen   StackOffset Offset =
74361f5ba5cSJonas Paulsson       TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);
744d57bba7cSSander de Smalen   return Offset + StackOffset::getFixed(SystemZMC::CallFrameSize);
74561f5ba5cSJonas Paulsson }
74661f5ba5cSJonas Paulsson 
747e1a2e90fSHans Wennborg MachineBasicBlock::iterator SystemZFrameLowering::
7485f613dfdSUlrich Weigand eliminateCallFramePseudoInstr(MachineFunction &MF,
7495f613dfdSUlrich Weigand                               MachineBasicBlock &MBB,
7505f613dfdSUlrich Weigand                               MachineBasicBlock::iterator MI) const {
7515f613dfdSUlrich Weigand   switch (MI->getOpcode()) {
7525f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKDOWN:
7535f613dfdSUlrich Weigand   case SystemZ::ADJCALLSTACKUP:
7545f613dfdSUlrich Weigand     assert(hasReservedCallFrame(MF) &&
7555f613dfdSUlrich Weigand            "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
756e1a2e90fSHans Wennborg     return MBB.erase(MI);
7575f613dfdSUlrich Weigand     break;
7585f613dfdSUlrich Weigand 
7595f613dfdSUlrich Weigand   default:
7605f613dfdSUlrich Weigand     llvm_unreachable("Unexpected call frame instruction");
7615f613dfdSUlrich Weigand   }
7625f613dfdSUlrich Weigand }
76361f5ba5cSJonas Paulsson 
76482879c29SJonas Paulsson unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF,
7652481f26aSMatt Arsenault                                                  Register Reg) const {
76682879c29SJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
76782879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
76882879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
76982879c29SJonas Paulsson   unsigned Offset = RegSpillOffsets[Reg];
77082879c29SJonas Paulsson   if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
77182879c29SJonas Paulsson     if (SystemZ::GR64BitRegClass.contains(Reg))
77282879c29SJonas Paulsson       // Put all GPRs at the top of the Register save area with packed
77382879c29SJonas Paulsson       // stack. Make room for the backchain if needed.
77482879c29SJonas Paulsson       Offset += BackChain ? 24 : 32;
77582879c29SJonas Paulsson     else
77682879c29SJonas Paulsson       Offset = 0;
77782879c29SJonas Paulsson   }
77882879c29SJonas Paulsson   return Offset;
77982879c29SJonas Paulsson }
78082879c29SJonas Paulsson 
78161f5ba5cSJonas Paulsson int SystemZFrameLowering::
78261f5ba5cSJonas Paulsson getOrCreateFramePointerSaveIndex(MachineFunction &MF) const {
78361f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
78461f5ba5cSJonas Paulsson   int FI = ZFI->getFramePointerSaveIndex();
78561f5ba5cSJonas Paulsson   if (!FI) {
78661f5ba5cSJonas Paulsson     MachineFrameInfo &MFFrame = MF.getFrameInfo();
787*653b9769SJonas Paulsson     int Offset = getBackchainOffset(MF) - SystemZMC::CallFrameSize;
78882879c29SJonas Paulsson     FI = MFFrame.CreateFixedObject(8, Offset, false);
78961f5ba5cSJonas Paulsson     ZFI->setFramePointerSaveIndex(FI);
79061f5ba5cSJonas Paulsson   }
79161f5ba5cSJonas Paulsson   return FI;
79261f5ba5cSJonas Paulsson }
79382879c29SJonas Paulsson 
79482879c29SJonas Paulsson bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const {
79582879c29SJonas Paulsson   bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
79682879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
79782879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
79882879c29SJonas Paulsson   if (HasPackedStackAttr && BackChain && !SoftFloat)
79982879c29SJonas Paulsson     report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
80082879c29SJonas Paulsson   bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
80182879c29SJonas Paulsson   return HasPackedStackAttr && CallConv;
80282879c29SJonas Paulsson }
803