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"
16989f1c72Sserge-sans-paille #include "llvm/CodeGen/LivePhysRegs.h"
175f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineModuleInfo.h"
185f613dfdSUlrich Weigand #include "llvm/CodeGen/MachineRegisterInfo.h"
195dd52f8cSRichard Sandiford #include "llvm/CodeGen/RegisterScavenging.h"
205f613dfdSUlrich Weigand #include "llvm/IR/Function.h"
21fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h"
225f613dfdSUlrich Weigand 
235f613dfdSUlrich Weigand using namespace llvm;
245f613dfdSUlrich Weigand 
25db39b4a2SRichard Sandiford namespace {
26a7d3f693SJonas Paulsson // The ABI-defined register save slots, relative to the CFA (i.e.
27023b5c1eSYusra Syeda // incoming stack pointer + SystemZMC::ELFCallFrameSize).
280a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = {
2961f5ba5cSJonas Paulsson   { SystemZ::R2D,  0x10 },
3061f5ba5cSJonas Paulsson   { SystemZ::R3D,  0x18 },
3161f5ba5cSJonas Paulsson   { SystemZ::R4D,  0x20 },
3261f5ba5cSJonas Paulsson   { SystemZ::R5D,  0x28 },
3361f5ba5cSJonas Paulsson   { SystemZ::R6D,  0x30 },
3461f5ba5cSJonas Paulsson   { SystemZ::R7D,  0x38 },
3561f5ba5cSJonas Paulsson   { SystemZ::R8D,  0x40 },
3661f5ba5cSJonas Paulsson   { SystemZ::R9D,  0x48 },
3761f5ba5cSJonas Paulsson   { SystemZ::R10D, 0x50 },
3861f5ba5cSJonas Paulsson   { SystemZ::R11D, 0x58 },
3961f5ba5cSJonas Paulsson   { SystemZ::R12D, 0x60 },
4061f5ba5cSJonas Paulsson   { SystemZ::R13D, 0x68 },
4161f5ba5cSJonas Paulsson   { SystemZ::R14D, 0x70 },
4261f5ba5cSJonas Paulsson   { SystemZ::R15D, 0x78 },
4361f5ba5cSJonas Paulsson   { SystemZ::F0D,  0x80 },
4461f5ba5cSJonas Paulsson   { SystemZ::F2D,  0x88 },
4561f5ba5cSJonas Paulsson   { SystemZ::F4D,  0x90 },
4661f5ba5cSJonas Paulsson   { SystemZ::F6D,  0x98 }
475f613dfdSUlrich Weigand };
480a950a2eSKai Nacke 
490a950a2eSKai Nacke static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = {
500a950a2eSKai Nacke     {SystemZ::R4D, 0x00},  {SystemZ::R5D, 0x08},  {SystemZ::R6D, 0x10},
510a950a2eSKai Nacke     {SystemZ::R7D, 0x18},  {SystemZ::R8D, 0x20},  {SystemZ::R9D, 0x28},
520a950a2eSKai Nacke     {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40},
530a950a2eSKai Nacke     {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}};
54c231269fSRichard Sandiford } // end anonymous namespace
555f613dfdSUlrich Weigand 
SystemZFrameLowering(StackDirection D,Align StackAl,int LAO,Align TransAl,bool StackReal)560782e55cSNeumann Hon SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl,
570782e55cSNeumann Hon                                            int LAO, Align TransAl,
580782e55cSNeumann Hon                                            bool StackReal)
590782e55cSNeumann Hon     : TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal) {}
60a7d3f693SJonas Paulsson 
610782e55cSNeumann Hon std::unique_ptr<SystemZFrameLowering>
create(const SystemZSubtarget & STI)620782e55cSNeumann Hon SystemZFrameLowering::create(const SystemZSubtarget &STI) {
630782e55cSNeumann Hon   if (STI.isTargetXPLINK64())
640782e55cSNeumann Hon     return std::make_unique<SystemZXPLINKFrameLowering>();
650782e55cSNeumann Hon   return std::make_unique<SystemZELFFrameLowering>();
66db39b4a2SRichard Sandiford }
67db39b4a2SRichard Sandiford 
eliminateCallFramePseudoInstr(MachineFunction & MF,MachineBasicBlock & MBB,MachineBasicBlock::iterator MI) const680782e55cSNeumann Hon MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr(
690782e55cSNeumann Hon     MachineFunction &MF, MachineBasicBlock &MBB,
700782e55cSNeumann Hon     MachineBasicBlock::iterator MI) const {
710782e55cSNeumann Hon   switch (MI->getOpcode()) {
720782e55cSNeumann Hon   case SystemZ::ADJCALLSTACKDOWN:
730782e55cSNeumann Hon   case SystemZ::ADJCALLSTACKUP:
740782e55cSNeumann Hon     assert(hasReservedCallFrame(MF) &&
750782e55cSNeumann Hon            "ADJSTACKDOWN and ADJSTACKUP should be no-ops");
760782e55cSNeumann Hon     return MBB.erase(MI);
770782e55cSNeumann Hon     break;
780782e55cSNeumann Hon 
790782e55cSNeumann Hon   default:
800782e55cSNeumann Hon     llvm_unreachable("Unexpected call frame instruction");
810782e55cSNeumann Hon   }
820782e55cSNeumann Hon }
830782e55cSNeumann Hon 
84f541a504SJonas Paulsson namespace {
85f541a504SJonas Paulsson struct SZFrameSortingObj {
86f541a504SJonas Paulsson   bool IsValid = false;     // True if we care about this Object.
87f541a504SJonas Paulsson   uint32_t ObjectIndex = 0; // Index of Object into MFI list.
88f541a504SJonas Paulsson   uint64_t ObjectSize = 0;  // Size of Object in bytes.
89f541a504SJonas Paulsson   uint32_t D12Count = 0;    // 12-bit displacement only.
90f541a504SJonas Paulsson   uint32_t DPairCount = 0;  // 12 or 20 bit displacement.
91f541a504SJonas Paulsson };
92f541a504SJonas Paulsson typedef std::vector<SZFrameSortingObj> SZFrameObjVec;
93f541a504SJonas Paulsson } // namespace
94f541a504SJonas Paulsson 
95f541a504SJonas Paulsson // TODO: Move to base class.
orderFrameObjects(const MachineFunction & MF,SmallVectorImpl<int> & ObjectsToAllocate) const96f541a504SJonas Paulsson void SystemZELFFrameLowering::orderFrameObjects(
97f541a504SJonas Paulsson     const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {
98f541a504SJonas Paulsson   const MachineFrameInfo &MFI = MF.getFrameInfo();
993432d40cSJonas Paulsson   auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();
100f541a504SJonas Paulsson 
101f541a504SJonas Paulsson   // Make a vector of sorting objects to track all MFI objects and mark those
102f541a504SJonas Paulsson   // to be sorted as valid.
103f541a504SJonas Paulsson   if (ObjectsToAllocate.size() <= 1)
104f541a504SJonas Paulsson     return;
105f541a504SJonas Paulsson   SZFrameObjVec SortingObjects(MFI.getObjectIndexEnd());
106f541a504SJonas Paulsson   for (auto &Obj : ObjectsToAllocate) {
107f541a504SJonas Paulsson     SortingObjects[Obj].IsValid = true;
108f541a504SJonas Paulsson     SortingObjects[Obj].ObjectIndex = Obj;
109f541a504SJonas Paulsson     SortingObjects[Obj].ObjectSize = MFI.getObjectSize(Obj);
110f541a504SJonas Paulsson   }
111f541a504SJonas Paulsson 
112f541a504SJonas Paulsson   // Examine uses for each object and record short (12-bit) and "pair"
113f541a504SJonas Paulsson   // displacement types.
114f541a504SJonas Paulsson   for (auto &MBB : MF)
115f541a504SJonas Paulsson     for (auto &MI : MBB) {
116f541a504SJonas Paulsson       if (MI.isDebugInstr())
117f541a504SJonas Paulsson         continue;
118f541a504SJonas Paulsson       for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
119f541a504SJonas Paulsson         const MachineOperand &MO = MI.getOperand(I);
120f541a504SJonas Paulsson         if (!MO.isFI())
121f541a504SJonas Paulsson           continue;
122f541a504SJonas Paulsson         int Index = MO.getIndex();
123f541a504SJonas Paulsson         if (Index >= 0 && Index < MFI.getObjectIndexEnd() &&
124f541a504SJonas Paulsson             SortingObjects[Index].IsValid) {
125f541a504SJonas Paulsson           if (TII->hasDisplacementPairInsn(MI.getOpcode()))
126f541a504SJonas Paulsson             SortingObjects[Index].DPairCount++;
127f541a504SJonas Paulsson           else if (!(MI.getDesc().TSFlags & SystemZII::Has20BitOffset))
128f541a504SJonas Paulsson             SortingObjects[Index].D12Count++;
129f541a504SJonas Paulsson         }
130f541a504SJonas Paulsson       }
131f541a504SJonas Paulsson     }
132f541a504SJonas Paulsson 
133f541a504SJonas Paulsson   // Sort all objects for short/paired displacements, which should be
134f541a504SJonas Paulsson   // sufficient as it seems like all frame objects typically are within the
135f541a504SJonas Paulsson   // long displacement range.  Sorting works by computing the "density" as
136f541a504SJonas Paulsson   // Count / ObjectSize. The comparisons of two such fractions are refactored
137f541a504SJonas Paulsson   // by multiplying both sides with A.ObjectSize * B.ObjectSize, in order to
138f541a504SJonas Paulsson   // eliminate the (fp) divisions.  A higher density object needs to go after
139f541a504SJonas Paulsson   // in the list in order for it to end up lower on the stack.
140f541a504SJonas Paulsson   auto CmpD12 = [](const SZFrameSortingObj &A, const SZFrameSortingObj &B) {
141f541a504SJonas Paulsson     // Put all invalid and variable sized objects at the end.
142f541a504SJonas Paulsson     if (!A.IsValid || !B.IsValid)
143f541a504SJonas Paulsson       return A.IsValid;
144f541a504SJonas Paulsson     if (!A.ObjectSize || !B.ObjectSize)
145f541a504SJonas Paulsson       return A.ObjectSize > 0;
146f541a504SJonas Paulsson     uint64_t ADensityCmp = A.D12Count * B.ObjectSize;
147f541a504SJonas Paulsson     uint64_t BDensityCmp = B.D12Count * A.ObjectSize;
148f541a504SJonas Paulsson     if (ADensityCmp != BDensityCmp)
149f541a504SJonas Paulsson       return ADensityCmp < BDensityCmp;
150f541a504SJonas Paulsson     return A.DPairCount * B.ObjectSize < B.DPairCount * A.ObjectSize;
151f541a504SJonas Paulsson   };
152f541a504SJonas Paulsson   std::stable_sort(SortingObjects.begin(), SortingObjects.end(), CmpD12);
153f541a504SJonas Paulsson 
154f541a504SJonas Paulsson   // Now modify the original list to represent the final order that
155f541a504SJonas Paulsson   // we want.
156f541a504SJonas Paulsson   unsigned Idx = 0;
157f541a504SJonas Paulsson   for (auto &Obj : SortingObjects) {
158f541a504SJonas Paulsson     // All invalid items are sorted at the end, so it's safe to stop.
159f541a504SJonas Paulsson     if (!Obj.IsValid)
160f541a504SJonas Paulsson       break;
161f541a504SJonas Paulsson     ObjectsToAllocate[Idx++] = Obj.ObjectIndex;
162f541a504SJonas Paulsson   }
163f541a504SJonas Paulsson }
164f541a504SJonas Paulsson 
hasReservedCallFrame(const MachineFunction & MF) const1650782e55cSNeumann Hon bool SystemZFrameLowering::hasReservedCallFrame(
1660782e55cSNeumann Hon     const MachineFunction &MF) const {
1670782e55cSNeumann Hon   // The ELF ABI requires us to allocate 160 bytes of stack space for the
1680782e55cSNeumann Hon   // callee, with any outgoing stack arguments being placed above that. It
1690782e55cSNeumann Hon   // seems better to make that area a permanent feature of the frame even if
1700782e55cSNeumann Hon   // we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes
1710782e55cSNeumann Hon   // of stack space for the register save area.
1720782e55cSNeumann Hon   return true;
1730782e55cSNeumann Hon }
1740782e55cSNeumann Hon 
assignCalleeSavedSpillSlots(MachineFunction & MF,const TargetRegisterInfo * TRI,std::vector<CalleeSavedInfo> & CSI) const1750782e55cSNeumann Hon bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots(
1760782e55cSNeumann Hon     MachineFunction &MF, const TargetRegisterInfo *TRI,
17761f5ba5cSJonas Paulsson     std::vector<CalleeSavedInfo> &CSI) const {
17861f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
17961f5ba5cSJonas Paulsson   MachineFrameInfo &MFFrame = MF.getFrameInfo();
18061f5ba5cSJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
18161f5ba5cSJonas Paulsson   if (CSI.empty())
18261f5ba5cSJonas Paulsson     return true; // Early exit if no callee saved registers are modified!
18361f5ba5cSJonas Paulsson 
18461f5ba5cSJonas Paulsson   unsigned LowGPR = 0;
18561f5ba5cSJonas Paulsson   unsigned HighGPR = SystemZ::R15D;
186023b5c1eSYusra Syeda   int StartSPOffset = SystemZMC::ELFCallFrameSize;
18761f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
188d6b07348SJim Lin     Register Reg = CS.getReg();
18982879c29SJonas Paulsson     int Offset = getRegSpillOffset(MF, Reg);
19061f5ba5cSJonas Paulsson     if (Offset) {
19161f5ba5cSJonas Paulsson       if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {
19261f5ba5cSJonas Paulsson         LowGPR = Reg;
19361f5ba5cSJonas Paulsson         StartSPOffset = Offset;
19461f5ba5cSJonas Paulsson       }
195023b5c1eSYusra Syeda       Offset -= SystemZMC::ELFCallFrameSize;
19661f5ba5cSJonas Paulsson       int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
19761f5ba5cSJonas Paulsson       CS.setFrameIdx(FrameIdx);
19861f5ba5cSJonas Paulsson     } else
19961f5ba5cSJonas Paulsson       CS.setFrameIdx(INT32_MAX);
20061f5ba5cSJonas Paulsson   }
20161f5ba5cSJonas Paulsson 
20261f5ba5cSJonas Paulsson   // Save the range of call-saved registers, for use by the
20361f5ba5cSJonas Paulsson   // prologue/epilogue inserters.
20461f5ba5cSJonas Paulsson   ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
20561f5ba5cSJonas Paulsson   if (IsVarArg) {
20661f5ba5cSJonas Paulsson     // Also save the GPR varargs, if any.  R6D is call-saved, so would
20761f5ba5cSJonas Paulsson     // already be included, but we also need to handle the call-clobbered
20861f5ba5cSJonas Paulsson     // argument registers.
209d6b07348SJim Lin     Register FirstGPR = ZFI->getVarArgsFirstGPR();
210023b5c1eSYusra Syeda     if (FirstGPR < SystemZ::ELFNumArgGPRs) {
211023b5c1eSYusra Syeda       unsigned Reg = SystemZ::ELFArgGPRs[FirstGPR];
21282879c29SJonas Paulsson       int Offset = getRegSpillOffset(MF, Reg);
21361f5ba5cSJonas Paulsson       if (StartSPOffset > Offset) {
21461f5ba5cSJonas Paulsson         LowGPR = Reg; StartSPOffset = Offset;
21561f5ba5cSJonas Paulsson       }
21661f5ba5cSJonas Paulsson     }
21761f5ba5cSJonas Paulsson   }
21861f5ba5cSJonas Paulsson   ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
21961f5ba5cSJonas Paulsson 
22061f5ba5cSJonas Paulsson   // Create fixed stack objects for the remaining registers.
221023b5c1eSYusra Syeda   int CurrOffset = -SystemZMC::ELFCallFrameSize;
22282879c29SJonas Paulsson   if (usePackedStack(MF))
22382879c29SJonas Paulsson     CurrOffset += StartSPOffset;
22482879c29SJonas Paulsson 
22561f5ba5cSJonas Paulsson   for (auto &CS : CSI) {
22661f5ba5cSJonas Paulsson     if (CS.getFrameIdx() != INT32_MAX)
22761f5ba5cSJonas Paulsson       continue;
228d6b07348SJim Lin     Register Reg = CS.getReg();
22961f5ba5cSJonas Paulsson     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
23061f5ba5cSJonas Paulsson     unsigned Size = TRI->getSpillSize(*RC);
23161f5ba5cSJonas Paulsson     CurrOffset -= Size;
23261f5ba5cSJonas Paulsson     assert(CurrOffset % 8 == 0 &&
23361f5ba5cSJonas Paulsson            "8-byte alignment required for for all register save slots");
23461f5ba5cSJonas Paulsson     int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);
23561f5ba5cSJonas Paulsson     CS.setFrameIdx(FrameIdx);
23661f5ba5cSJonas Paulsson   }
23761f5ba5cSJonas Paulsson 
23861f5ba5cSJonas Paulsson   return true;
2395f613dfdSUlrich Weigand }
2405f613dfdSUlrich Weigand 
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const2410782e55cSNeumann Hon void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF,
24202564865SMatthias Braun                                                    BitVector &SavedRegs,
2435f613dfdSUlrich Weigand                                                    RegScavenger *RS) const {
24402564865SMatthias Braun   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
24502564865SMatthias Braun 
246941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
247fc6de428SEric Christopher   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2485f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
2495f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
250f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
2515f613dfdSUlrich Weigand 
2525f613dfdSUlrich Weigand   // va_start stores incoming FPR varargs in the normal way, but delegates
2535f613dfdSUlrich Weigand   // the saving of incoming GPR varargs to spillCalleeSavedRegisters().
2545f613dfdSUlrich Weigand   // Record these pending uses, which typically include the call-saved
2555f613dfdSUlrich Weigand   // argument register R6D.
2565f613dfdSUlrich Weigand   if (IsVarArg)
257023b5c1eSYusra Syeda     for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)
258023b5c1eSYusra Syeda       SavedRegs.set(SystemZ::ELFArgGPRs[I]);
2595f613dfdSUlrich Weigand 
260234e5a80SMarcin Koscielnicki   // If there are any landing pads, entering them will modify r6/r7.
261d0ee66c2SMatthias Braun   if (!MF.getLandingPads().empty()) {
262234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R6D);
263234e5a80SMarcin Koscielnicki     SavedRegs.set(SystemZ::R7D);
264234e5a80SMarcin Koscielnicki   }
265234e5a80SMarcin Koscielnicki 
2665f613dfdSUlrich Weigand   // If the function requires a frame pointer, record that the hard
2675f613dfdSUlrich Weigand   // frame pointer will be clobbered.
2685f613dfdSUlrich Weigand   if (HasFP)
26902564865SMatthias Braun     SavedRegs.set(SystemZ::R11D);
2705f613dfdSUlrich Weigand 
2715f613dfdSUlrich Weigand   // If the function calls other functions, record that the return
2725f613dfdSUlrich Weigand   // address register will be clobbered.
273941a705bSMatthias Braun   if (MFFrame.hasCalls())
27402564865SMatthias Braun     SavedRegs.set(SystemZ::R14D);
2755f613dfdSUlrich Weigand 
2765f613dfdSUlrich Weigand   // If we are saving GPRs other than the stack pointer, we might as well
2775f613dfdSUlrich Weigand   // save and restore the stack pointer at the same time, via STMG and LMG.
2785f613dfdSUlrich Weigand   // This allows the deallocation to be done by the LMG, rather than needing
2795f613dfdSUlrich Weigand   // a separate %r15 addition.
280840beec2SCraig Topper   const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
2815f613dfdSUlrich Weigand   for (unsigned I = 0; CSRegs[I]; ++I) {
2825f613dfdSUlrich Weigand     unsigned Reg = CSRegs[I];
28302564865SMatthias Braun     if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {
28402564865SMatthias Braun       SavedRegs.set(SystemZ::R15D);
2855f613dfdSUlrich Weigand       break;
2865f613dfdSUlrich Weigand     }
2875f613dfdSUlrich Weigand   }
2885f613dfdSUlrich Weigand }
2895f613dfdSUlrich Weigand 
SystemZELFFrameLowering()2900782e55cSNeumann Hon SystemZELFFrameLowering::SystemZELFFrameLowering()
2910782e55cSNeumann Hon     : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0,
2920a950a2eSKai Nacke                            Align(8), /* StackRealignable */ false),
2930782e55cSNeumann Hon       RegSpillOffsets(0) {
2940a950a2eSKai Nacke 
2950782e55cSNeumann Hon   // Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not
2960782e55cSNeumann Hon   // equal to the incoming stack pointer, but to incoming stack pointer plus
2970782e55cSNeumann Hon   // 160.  Instead of using a Local Area Offset, the Register save area will
2980782e55cSNeumann Hon   // be occupied by fixed frame objects, and all offsets are actually
2990782e55cSNeumann Hon   // relative to CFA.
3000782e55cSNeumann Hon 
3010782e55cSNeumann Hon   // Create a mapping from register number to save slot offset.
3020782e55cSNeumann Hon   // These offsets are relative to the start of the register save area.
3030782e55cSNeumann Hon   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
304f15014ffSBenjamin Kramer   for (unsigned I = 0, E = array_lengthof(ELFSpillOffsetTable); I != E; ++I)
3050a950a2eSKai Nacke     RegSpillOffsets[ELFSpillOffsetTable[I].Reg] = ELFSpillOffsetTable[I].Offset;
3060782e55cSNeumann Hon }
3070782e55cSNeumann Hon 
3085f613dfdSUlrich Weigand // Add GPR64 to the save instruction being built by MIB, which is in basic
3095f613dfdSUlrich Weigand // block MBB.  IsImplicit says whether this is an explicit operand to the
3105f613dfdSUlrich Weigand // instruction, or an implicit one that comes between the explicit start
3115f613dfdSUlrich Weigand // and end registers.
addSavedGPR(MachineBasicBlock & MBB,MachineInstrBuilder & MIB,unsigned GPR64,bool IsImplicit)3125f613dfdSUlrich Weigand static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,
3135f613dfdSUlrich Weigand                         unsigned GPR64, bool IsImplicit) {
314d913448bSEric Christopher   const TargetRegisterInfo *RI =
315fc6de428SEric Christopher       MBB.getParent()->getSubtarget().getRegisterInfo();
3160c476111SDaniel Sanders   Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);
3175f613dfdSUlrich Weigand   bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);
3185f613dfdSUlrich Weigand   if (!IsLive || !IsImplicit) {
3195f613dfdSUlrich Weigand     MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));
3205f613dfdSUlrich Weigand     if (!IsLive)
3215f613dfdSUlrich Weigand       MBB.addLiveIn(GPR64);
3225f613dfdSUlrich Weigand   }
3235f613dfdSUlrich Weigand }
3245f613dfdSUlrich Weigand 
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const3250782e55cSNeumann Hon bool SystemZELFFrameLowering::spillCalleeSavedRegisters(
326e4230a9fSBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
327e4230a9fSBenjamin Kramer     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3285f613dfdSUlrich Weigand   if (CSI.empty())
3295f613dfdSUlrich Weigand     return false;
3305f613dfdSUlrich Weigand 
3315f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
332fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
3335f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
334f1caa283SMatthias Braun   bool IsVarArg = MF.getFunction().isVarArg();
335057c5a6bSOleg Ranevskyy   DebugLoc DL;
3365f613dfdSUlrich Weigand 
3375f613dfdSUlrich Weigand   // Save GPRs
33861f5ba5cSJonas Paulsson   SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();
33961f5ba5cSJonas Paulsson   if (SpillGPRs.LowGPR) {
34061f5ba5cSJonas Paulsson     assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&
34161f5ba5cSJonas Paulsson            "Should be saving %r15 and something else");
3425f613dfdSUlrich Weigand 
3435f613dfdSUlrich Weigand     // Build an STMG instruction.
3445f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
3455f613dfdSUlrich Weigand 
3465f613dfdSUlrich Weigand     // Add the explicit register operands.
34761f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);
34861f5ba5cSJonas Paulsson     addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);
3495f613dfdSUlrich Weigand 
3505f613dfdSUlrich Weigand     // Add the address.
35161f5ba5cSJonas Paulsson     MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset);
3525f613dfdSUlrich Weigand 
3535f613dfdSUlrich Weigand     // Make sure all call-saved GPRs are included as operands and are
3545f613dfdSUlrich Weigand     // marked as live on entry.
355ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
356d6b07348SJim Lin       Register Reg = I.getReg();
3575f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg))
358f1bd22dfSEric Christopher         addSavedGPR(MBB, MIB, Reg, true);
3595f613dfdSUlrich Weigand     }
3605f613dfdSUlrich Weigand 
3615f613dfdSUlrich Weigand     // ...likewise GPR varargs.
3625f613dfdSUlrich Weigand     if (IsVarArg)
363023b5c1eSYusra Syeda       for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)
364023b5c1eSYusra Syeda         addSavedGPR(MBB, MIB, SystemZ::ELFArgGPRs[I], true);
3655f613dfdSUlrich Weigand   }
3665f613dfdSUlrich Weigand 
3678b19be46SUlrich Weigand   // Save FPRs/VRs in the normal TargetInstrInfo way.
368ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
369d6b07348SJim Lin     Register Reg = I.getReg();
3705f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
3715f613dfdSUlrich Weigand       MBB.addLiveIn(Reg);
372ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
3735f613dfdSUlrich Weigand                                &SystemZ::FP64BitRegClass, TRI);
3745f613dfdSUlrich Weigand     }
3758b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg)) {
3768b19be46SUlrich Weigand       MBB.addLiveIn(Reg);
377ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
3788b19be46SUlrich Weigand                                &SystemZ::VR128BitRegClass, TRI);
3798b19be46SUlrich Weigand     }
3805f613dfdSUlrich Weigand   }
3815f613dfdSUlrich Weigand 
3825f613dfdSUlrich Weigand   return true;
3835f613dfdSUlrich Weigand }
3845f613dfdSUlrich Weigand 
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const3850782e55cSNeumann Hon bool SystemZELFFrameLowering::restoreCalleeSavedRegisters(
386186dd631SBenjamin Kramer     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
387186dd631SBenjamin Kramer     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
3885f613dfdSUlrich Weigand   if (CSI.empty())
3895f613dfdSUlrich Weigand     return false;
3905f613dfdSUlrich Weigand 
3915f613dfdSUlrich Weigand   MachineFunction &MF = *MBB.getParent();
392fc6de428SEric Christopher   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
3935f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
3945f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
3955f613dfdSUlrich Weigand   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
3965f613dfdSUlrich Weigand 
3978b19be46SUlrich Weigand   // Restore FPRs/VRs in the normal TargetInstrInfo way.
398ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
399d6b07348SJim Lin     Register Reg = I.getReg();
4005f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg))
401ea5421bdSKazu Hirata       TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),
4025f613dfdSUlrich Weigand                                 &SystemZ::FP64BitRegClass, TRI);
4038b19be46SUlrich Weigand     if (SystemZ::VR128BitRegClass.contains(Reg))
404ea5421bdSKazu Hirata       TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),
4058b19be46SUlrich Weigand                                 &SystemZ::VR128BitRegClass, TRI);
4065f613dfdSUlrich Weigand   }
4075f613dfdSUlrich Weigand 
4085f613dfdSUlrich Weigand   // Restore call-saved GPRs (but not call-clobbered varargs, which at
4095f613dfdSUlrich Weigand   // this point might hold return values).
41061f5ba5cSJonas Paulsson   SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();
41161f5ba5cSJonas Paulsson   if (RestoreGPRs.LowGPR) {
4125f613dfdSUlrich Weigand     // If we saved any of %r2-%r5 as varargs, we should also be saving
4135f613dfdSUlrich Weigand     // and restoring %r6.  If we're saving %r6 or above, we should be
4145f613dfdSUlrich Weigand     // restoring it too.
41561f5ba5cSJonas Paulsson     assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR &&
41661f5ba5cSJonas Paulsson            "Should be loading %r15 and something else");
4175f613dfdSUlrich Weigand 
4185f613dfdSUlrich Weigand     // Build an LMG instruction.
4195f613dfdSUlrich Weigand     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
4205f613dfdSUlrich Weigand 
4215f613dfdSUlrich Weigand     // Add the explicit register operands.
42261f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);
42361f5ba5cSJonas Paulsson     MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);
4245f613dfdSUlrich Weigand 
4255f613dfdSUlrich Weigand     // Add the address.
4265f613dfdSUlrich Weigand     MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);
42761f5ba5cSJonas Paulsson     MIB.addImm(RestoreGPRs.GPROffset);
4285f613dfdSUlrich Weigand 
4295f613dfdSUlrich Weigand     // Do a second scan adding regs as being defined by instruction
430ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
431d6b07348SJim Lin       Register Reg = I.getReg();
43261f5ba5cSJonas Paulsson       if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&
433f0344826SJonas Paulsson           SystemZ::GR64BitRegClass.contains(Reg))
4345f613dfdSUlrich Weigand         MIB.addReg(Reg, RegState::ImplicitDefine);
4355f613dfdSUlrich Weigand     }
4365f613dfdSUlrich Weigand   }
4375f613dfdSUlrich Weigand 
4385f613dfdSUlrich Weigand   return true;
4395f613dfdSUlrich Weigand }
4405f613dfdSUlrich Weigand 
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger * RS) const4410782e55cSNeumann Hon void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized(
4420782e55cSNeumann Hon     MachineFunction &MF, RegScavenger *RS) const {
443941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
4441606755dSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
4451606755dSJonas Paulsson   MachineRegisterInfo *MRI = &MF.getRegInfo();
44623762575SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
44761f5ba5cSJonas Paulsson 
44823762575SJonas Paulsson   if (!usePackedStack(MF) || BackChain)
44923762575SJonas Paulsson     // Create the incoming register save area.
45061f5ba5cSJonas Paulsson     getOrCreateFramePointerSaveIndex(MF);
45161f5ba5cSJonas Paulsson 
452af98b748SUlrich Weigand   // Get the size of our stack frame to be allocated ...
453af98b748SUlrich Weigand   uint64_t StackSize = (MFFrame.estimateStackSize(MF) +
454023b5c1eSYusra Syeda                         SystemZMC::ELFCallFrameSize);
455af98b748SUlrich Weigand   // ... and the maximum offset we may need to reach into the
456af98b748SUlrich Weigand   // caller's frame to access the save area or stack arguments.
45761f5ba5cSJonas Paulsson   int64_t MaxArgOffset = 0;
458af98b748SUlrich Weigand   for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)
459af98b748SUlrich Weigand     if (MFFrame.getObjectOffset(I) >= 0) {
46061f5ba5cSJonas Paulsson       int64_t ArgOffset = MFFrame.getObjectOffset(I) +
461af98b748SUlrich Weigand                           MFFrame.getObjectSize(I);
462af98b748SUlrich Weigand       MaxArgOffset = std::max(MaxArgOffset, ArgOffset);
463af98b748SUlrich Weigand     }
464af98b748SUlrich Weigand 
465af98b748SUlrich Weigand   uint64_t MaxReach = StackSize + MaxArgOffset;
46623943229SRichard Sandiford   if (!isUInt<12>(MaxReach)) {
46723943229SRichard Sandiford     // We may need register scavenging slots if some parts of the frame
4685dd52f8cSRichard Sandiford     // are outside the reach of an unsigned 12-bit displacement.
46923943229SRichard Sandiford     // Create 2 for the case where both addresses in an MVC are
47023943229SRichard Sandiford     // out of range.
47128de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
47228de229bSGuillaume Chatelet     RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
47323943229SRichard Sandiford   }
4741606755dSJonas Paulsson 
4751606755dSJonas Paulsson   // If R6 is used as an argument register it is still callee saved. If it in
4761606755dSJonas Paulsson   // this case is not clobbered (and restored) it should never be marked as
4771606755dSJonas Paulsson   // killed.
4781606755dSJonas Paulsson   if (MF.front().isLiveIn(SystemZ::R6D) &&
4791606755dSJonas Paulsson       ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D)
4801606755dSJonas Paulsson     for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))
4811606755dSJonas Paulsson       MO.setIsKill(false);
4825dd52f8cSRichard Sandiford }
4835dd52f8cSRichard Sandiford 
4845f613dfdSUlrich Weigand // Emit instructions before MBBI (in MBB) to add NumBytes to Reg.
emitIncrement(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,const DebugLoc & DL,Register Reg,int64_t NumBytes,const TargetInstrInfo * TII)4855f613dfdSUlrich Weigand static void emitIncrement(MachineBasicBlock &MBB,
4862481f26aSMatt Arsenault                           MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,
4872481f26aSMatt Arsenault                           Register Reg, int64_t NumBytes,
4885f613dfdSUlrich Weigand                           const TargetInstrInfo *TII) {
4895f613dfdSUlrich Weigand   while (NumBytes) {
4905f613dfdSUlrich Weigand     unsigned Opcode;
4915f613dfdSUlrich Weigand     int64_t ThisVal = NumBytes;
4925f613dfdSUlrich Weigand     if (isInt<16>(NumBytes))
4935f613dfdSUlrich Weigand       Opcode = SystemZ::AGHI;
4945f613dfdSUlrich Weigand     else {
4955f613dfdSUlrich Weigand       Opcode = SystemZ::AGFI;
4965f613dfdSUlrich Weigand       // Make sure we maintain 8-byte stack alignment.
497fffd56ecSAlexey Samsonov       int64_t MinVal = -uint64_t(1) << 31;
4985f613dfdSUlrich Weigand       int64_t MaxVal = (int64_t(1) << 31) - 8;
4995f613dfdSUlrich Weigand       if (ThisVal < MinVal)
5005f613dfdSUlrich Weigand         ThisVal = MinVal;
5015f613dfdSUlrich Weigand       else if (ThisVal > MaxVal)
5025f613dfdSUlrich Weigand         ThisVal = MaxVal;
5035f613dfdSUlrich Weigand     }
5045f613dfdSUlrich Weigand     MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)
5055f613dfdSUlrich Weigand       .addReg(Reg).addImm(ThisVal);
50614a44495SRichard Sandiford     // The CC implicit def is dead.
5075f613dfdSUlrich Weigand     MI->getOperand(3).setIsDead();
5085f613dfdSUlrich Weigand     NumBytes -= ThisVal;
5095f613dfdSUlrich Weigand   }
5105f613dfdSUlrich Weigand }
5115f613dfdSUlrich Weigand 
512515bfc66SJonas Paulsson // Add CFI for the new CFA offset.
buildCFAOffs(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,int Offset,const SystemZInstrInfo * ZII)513515bfc66SJonas Paulsson static void buildCFAOffs(MachineBasicBlock &MBB,
514515bfc66SJonas Paulsson                          MachineBasicBlock::iterator MBBI,
515515bfc66SJonas Paulsson                          const DebugLoc &DL, int Offset,
516515bfc66SJonas Paulsson                          const SystemZInstrInfo *ZII) {
517515bfc66SJonas Paulsson   unsigned CFIIndex = MBB.getParent()->addFrameInst(
518515bfc66SJonas Paulsson     MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));
519515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
520515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
521515bfc66SJonas Paulsson }
522515bfc66SJonas Paulsson 
523515bfc66SJonas Paulsson // Add CFI for the new frame location.
buildDefCFAReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,unsigned Reg,const SystemZInstrInfo * ZII)524515bfc66SJonas Paulsson static void buildDefCFAReg(MachineBasicBlock &MBB,
525515bfc66SJonas Paulsson                            MachineBasicBlock::iterator MBBI,
526515bfc66SJonas Paulsson                            const DebugLoc &DL, unsigned Reg,
527515bfc66SJonas Paulsson                            const SystemZInstrInfo *ZII) {
528515bfc66SJonas Paulsson   MachineFunction &MF = *MBB.getParent();
529515bfc66SJonas Paulsson   MachineModuleInfo &MMI = MF.getMMI();
530515bfc66SJonas Paulsson   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
531515bfc66SJonas Paulsson   unsigned RegNum = MRI->getDwarfRegNum(Reg, true);
532515bfc66SJonas Paulsson   unsigned CFIIndex = MF.addFrameInst(
533515bfc66SJonas Paulsson                         MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));
534515bfc66SJonas Paulsson   BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
535515bfc66SJonas Paulsson     .addCFIIndex(CFIIndex);
536515bfc66SJonas Paulsson }
537515bfc66SJonas Paulsson 
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const5380782e55cSNeumann Hon void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF,
53961b305edSQuentin Colombet                                            MachineBasicBlock &MBB) const {
54061b305edSQuentin Colombet   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
541515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
542515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
543941a705bSMatthias Braun   MachineFrameInfo &MFFrame = MF.getFrameInfo();
544515bfc66SJonas Paulsson   auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo());
5455f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
5465f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.begin();
5475f613dfdSUlrich Weigand   MachineModuleInfo &MMI = MF.getMMI();
548bc07a890SBill Wendling   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
549941a705bSMatthias Braun   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
5505f613dfdSUlrich Weigand   bool HasFP = hasFP(MF);
551057c5a6bSOleg Ranevskyy 
55222f94291SUlrich Weigand   // In GHC calling convention C stack space, including the ABI-defined
55322f94291SUlrich Weigand   // 160-byte base area, is (de)allocated by GHC itself.  This stack space may
55422f94291SUlrich Weigand   // be used by LLVM as spill slots for the tail recursive GHC functions.  Thus
55522f94291SUlrich Weigand   // do not allocate stack space here, too.
55622f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC) {
55722f94291SUlrich Weigand     if (MFFrame.getStackSize() > 2048 * sizeof(long)) {
55822f94291SUlrich Weigand       report_fatal_error(
55922f94291SUlrich Weigand           "Pre allocated stack space for GHC function is too small");
56022f94291SUlrich Weigand     }
56122f94291SUlrich Weigand     if (HasFP) {
56222f94291SUlrich Weigand       report_fatal_error(
56322f94291SUlrich Weigand           "In GHC calling convention a frame pointer is not supported");
56422f94291SUlrich Weigand     }
565023b5c1eSYusra Syeda     MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::ELFCallFrameSize);
56622f94291SUlrich Weigand     return;
56722f94291SUlrich Weigand   }
56822f94291SUlrich Weigand 
569057c5a6bSOleg Ranevskyy   // Debug location must be unknown since the first debug location is used
570057c5a6bSOleg Ranevskyy   // to determine the end of the prologue.
571057c5a6bSOleg Ranevskyy   DebugLoc DL;
5725f613dfdSUlrich Weigand 
5735f613dfdSUlrich Weigand   // The current offset of the stack pointer from the CFA.
574023b5c1eSYusra Syeda   int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;
5755f613dfdSUlrich Weigand 
57661f5ba5cSJonas Paulsson   if (ZFI->getSpillGPRRegs().LowGPR) {
5775f613dfdSUlrich Weigand     // Skip over the GPR saves.
5785f613dfdSUlrich Weigand     if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)
5795f613dfdSUlrich Weigand       ++MBBI;
5805f613dfdSUlrich Weigand     else
5815f613dfdSUlrich Weigand       llvm_unreachable("Couldn't skip over GPR saves");
5825f613dfdSUlrich Weigand 
5835f613dfdSUlrich Weigand     // Add CFI for the GPR saves.
58428c111ecSRichard Sandiford     for (auto &Save : CSI) {
585d6b07348SJim Lin       Register Reg = Save.getReg();
5865f613dfdSUlrich Weigand       if (SystemZ::GR64BitRegClass.contains(Reg)) {
58761f5ba5cSJonas Paulsson         int FI = Save.getFrameIdx();
58861f5ba5cSJonas Paulsson         int64_t Offset = MFFrame.getObjectOffset(FI);
589f23ef437SMatthias Braun         unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
590b1f25f1bSRafael Espindola             nullptr, MRI->getDwarfRegNum(Reg, true), Offset));
591b1f25f1bSRafael Espindola         BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
592b1f25f1bSRafael Espindola             .addCFIIndex(CFIIndex);
5935f613dfdSUlrich Weigand       }
5945f613dfdSUlrich Weigand     }
5955f613dfdSUlrich Weigand   }
5965f613dfdSUlrich Weigand 
59732063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
59832063888SUlrich Weigand   // We need to allocate the ABI-defined 160-byte base area whenever
59932063888SUlrich Weigand   // we allocate stack space for our own use and whenever we call another
60032063888SUlrich Weigand   // function.
60161f5ba5cSJonas Paulsson   bool HasStackObject = false;
60261f5ba5cSJonas Paulsson   for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)
60361f5ba5cSJonas Paulsson     if (!MFFrame.isDeadObjectIndex(i)) {
60461f5ba5cSJonas Paulsson       HasStackObject = true;
60561f5ba5cSJonas Paulsson       break;
60632063888SUlrich Weigand     }
60761f5ba5cSJonas Paulsson   if (HasStackObject || MFFrame.hasCalls())
608023b5c1eSYusra Syeda     StackSize += SystemZMC::ELFCallFrameSize;
60961f5ba5cSJonas Paulsson   // Don't allocate the incoming reg save area.
610023b5c1eSYusra Syeda   StackSize = StackSize > SystemZMC::ELFCallFrameSize
611023b5c1eSYusra Syeda                   ? StackSize - SystemZMC::ELFCallFrameSize
61261f5ba5cSJonas Paulsson                   : 0;
61361f5ba5cSJonas Paulsson   MFFrame.setStackSize(StackSize);
61432063888SUlrich Weigand 
6155f613dfdSUlrich Weigand   if (StackSize) {
6165f613dfdSUlrich Weigand     // Allocate StackSize bytes.
6175f613dfdSUlrich Weigand     int64_t Delta = -int64_t(StackSize);
618515bfc66SJonas Paulsson     const unsigned ProbeSize = TLI.getStackProbeSize(MF);
619515bfc66SJonas Paulsson     bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&
620515bfc66SJonas Paulsson            (ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);
621515bfc66SJonas Paulsson     if (!FreeProbe &&
622515bfc66SJonas Paulsson         MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {
623515bfc66SJonas Paulsson       // Stack probing may involve looping, but splitting the prologue block
624515bfc66SJonas Paulsson       // is not possible at this point since it would invalidate the
625515bfc66SJonas Paulsson       // SaveBlocks / RestoreBlocks sets of PEI in the single block function
626515bfc66SJonas Paulsson       // case. Build a pseudo to be handled later by inlineStackProbe().
627515bfc66SJonas Paulsson       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))
628515bfc66SJonas Paulsson         .addImm(StackSize);
629515bfc66SJonas Paulsson     }
630515bfc66SJonas Paulsson     else {
63142f628c8SJonas Paulsson       bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
63242f628c8SJonas Paulsson       // If we need backchain, save current stack pointer.  R1 is free at
63342f628c8SJonas Paulsson       // this point.
63442f628c8SJonas Paulsson       if (StoreBackchain)
63542f628c8SJonas Paulsson         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))
63642f628c8SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
6375f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);
638515bfc66SJonas Paulsson       buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);
639653b9769SJonas Paulsson       if (StoreBackchain)
640ad1482c6SMarcin Koscielnicki         BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
64182879c29SJonas Paulsson           .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
642653b9769SJonas Paulsson           .addImm(getBackchainOffset(MF)).addReg(0);
6435f613dfdSUlrich Weigand     }
64442f628c8SJonas Paulsson     SPOffsetFromCFA += Delta;
64542f628c8SJonas Paulsson   }
6465f613dfdSUlrich Weigand 
6475f613dfdSUlrich Weigand   if (HasFP) {
6485f613dfdSUlrich Weigand     // Copy the base of the frame to R11.
6495f613dfdSUlrich Weigand     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)
6505f613dfdSUlrich Weigand       .addReg(SystemZ::R15D);
6515f613dfdSUlrich Weigand 
6525f613dfdSUlrich Weigand     // Add CFI for the new frame location.
653515bfc66SJonas Paulsson     buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);
6545f613dfdSUlrich Weigand 
6555f613dfdSUlrich Weigand     // Mark the FramePtr as live at the beginning of every block except
6565f613dfdSUlrich Weigand     // the entry block.  (We'll have marked R11 as live on entry when
6575f613dfdSUlrich Weigand     // saving the GPRs.)
658cfc74024SKazu Hirata     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
659cfc74024SKazu Hirata       MBBJ.addLiveIn(SystemZ::R11D);
6605f613dfdSUlrich Weigand   }
6615f613dfdSUlrich Weigand 
6628b19be46SUlrich Weigand   // Skip over the FPR/VR saves.
663b1f25f1bSRafael Espindola   SmallVector<unsigned, 8> CFIIndexes;
66428c111ecSRichard Sandiford   for (auto &Save : CSI) {
665d6b07348SJim Lin     Register Reg = Save.getReg();
6665f613dfdSUlrich Weigand     if (SystemZ::FP64BitRegClass.contains(Reg)) {
6675f613dfdSUlrich Weigand       if (MBBI != MBB.end() &&
6685f613dfdSUlrich Weigand           (MBBI->getOpcode() == SystemZ::STD ||
6695f613dfdSUlrich Weigand            MBBI->getOpcode() == SystemZ::STDY))
6705f613dfdSUlrich Weigand         ++MBBI;
6715f613dfdSUlrich Weigand       else
6725f613dfdSUlrich Weigand         llvm_unreachable("Couldn't skip over FPR save");
6738b19be46SUlrich Weigand     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
6748b19be46SUlrich Weigand       if (MBBI != MBB.end() &&
6758b19be46SUlrich Weigand           MBBI->getOpcode() == SystemZ::VST)
6768b19be46SUlrich Weigand         ++MBBI;
6778b19be46SUlrich Weigand       else
6788b19be46SUlrich Weigand         llvm_unreachable("Couldn't skip over VR save");
6798b19be46SUlrich Weigand     } else
6808b19be46SUlrich Weigand       continue;
6815f613dfdSUlrich Weigand 
6825f613dfdSUlrich Weigand     // Add CFI for the this save.
68328c111ecSRichard Sandiford     unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
6842481f26aSMatt Arsenault     Register IgnoredFrameReg;
6855567bafeSJames Y Knight     int64_t Offset =
686d57bba7cSSander de Smalen         getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg)
687d57bba7cSSander de Smalen             .getFixed();
6885567bafeSJames Y Knight 
689f23ef437SMatthias Braun     unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
690b1f25f1bSRafael Espindola           nullptr, DwarfReg, SPOffsetFromCFA + Offset));
691b1f25f1bSRafael Espindola     CFIIndexes.push_back(CFIIndex);
6925f613dfdSUlrich Weigand   }
6938b19be46SUlrich Weigand   // Complete the CFI for the FPR/VR saves, modelling them as taking effect
6945f613dfdSUlrich Weigand   // after the last save.
695b1f25f1bSRafael Espindola   for (auto CFIIndex : CFIIndexes) {
696b1f25f1bSRafael Espindola     BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))
697b1f25f1bSRafael Espindola         .addCFIIndex(CFIIndex);
698b1f25f1bSRafael Espindola   }
6995f613dfdSUlrich Weigand }
7005f613dfdSUlrich Weigand 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const7010782e55cSNeumann Hon void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF,
7025f613dfdSUlrich Weigand                                            MachineBasicBlock &MBB) const {
7035f613dfdSUlrich Weigand   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
704fc6de428SEric Christopher   auto *ZII =
705fc6de428SEric Christopher       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
7065f613dfdSUlrich Weigand   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
70732063888SUlrich Weigand   MachineFrameInfo &MFFrame = MF.getFrameInfo();
7085f613dfdSUlrich Weigand 
7090782e55cSNeumann Hon   // See SystemZELFFrameLowering::emitPrologue
71022f94291SUlrich Weigand   if (MF.getFunction().getCallingConv() == CallingConv::GHC)
71122f94291SUlrich Weigand     return;
71222f94291SUlrich Weigand 
7135f613dfdSUlrich Weigand   // Skip the return instruction.
714709bda66SRichard Sandiford   assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
7155f613dfdSUlrich Weigand 
71632063888SUlrich Weigand   uint64_t StackSize = MFFrame.getStackSize();
71761f5ba5cSJonas Paulsson   if (ZFI->getRestoreGPRRegs().LowGPR) {
7185f613dfdSUlrich Weigand     --MBBI;
7195f613dfdSUlrich Weigand     unsigned Opcode = MBBI->getOpcode();
7205f613dfdSUlrich Weigand     if (Opcode != SystemZ::LMG)
7215f613dfdSUlrich Weigand       llvm_unreachable("Expected to see callee-save register restore code");
7225f613dfdSUlrich Weigand 
7235f613dfdSUlrich Weigand     unsigned AddrOpNo = 2;
7245f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
7255f613dfdSUlrich Weigand     uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();
7265f613dfdSUlrich Weigand     unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
7275f613dfdSUlrich Weigand 
7285f613dfdSUlrich Weigand     // If the offset is too large, use the largest stack-aligned offset
7295f613dfdSUlrich Weigand     // and add the rest to the base register (the stack or frame pointer).
7305f613dfdSUlrich Weigand     if (!NewOpcode) {
7315f613dfdSUlrich Weigand       uint64_t NumBytes = Offset - 0x7fff8;
7325f613dfdSUlrich Weigand       emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),
7335f613dfdSUlrich Weigand                     NumBytes, ZII);
7345f613dfdSUlrich Weigand       Offset -= NumBytes;
7355f613dfdSUlrich Weigand       NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);
7365f613dfdSUlrich Weigand       assert(NewOpcode && "No restore instruction available");
7375f613dfdSUlrich Weigand     }
7385f613dfdSUlrich Weigand 
7395f613dfdSUlrich Weigand     MBBI->setDesc(ZII->get(NewOpcode));
7405f613dfdSUlrich Weigand     MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);
7415f613dfdSUlrich Weigand   } else if (StackSize) {
7425f613dfdSUlrich Weigand     DebugLoc DL = MBBI->getDebugLoc();
7435f613dfdSUlrich Weigand     emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);
7445f613dfdSUlrich Weigand   }
7455f613dfdSUlrich Weigand }
7465f613dfdSUlrich Weigand 
inlineStackProbe(MachineFunction & MF,MachineBasicBlock & PrologMBB) const7470782e55cSNeumann Hon void SystemZELFFrameLowering::inlineStackProbe(
7480782e55cSNeumann Hon     MachineFunction &MF, MachineBasicBlock &PrologMBB) const {
749515bfc66SJonas Paulsson   auto *ZII =
750515bfc66SJonas Paulsson     static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
751515bfc66SJonas Paulsson   const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();
752515bfc66SJonas Paulsson   const SystemZTargetLowering &TLI = *STI.getTargetLowering();
753515bfc66SJonas Paulsson 
754515bfc66SJonas Paulsson   MachineInstr *StackAllocMI = nullptr;
755515bfc66SJonas Paulsson   for (MachineInstr &MI : PrologMBB)
756515bfc66SJonas Paulsson     if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {
757515bfc66SJonas Paulsson       StackAllocMI = &MI;
758515bfc66SJonas Paulsson       break;
759515bfc66SJonas Paulsson     }
760515bfc66SJonas Paulsson   if (StackAllocMI == nullptr)
761515bfc66SJonas Paulsson     return;
762515bfc66SJonas Paulsson   uint64_t StackSize = StackAllocMI->getOperand(0).getImm();
763515bfc66SJonas Paulsson   const unsigned ProbeSize = TLI.getStackProbeSize(MF);
764515bfc66SJonas Paulsson   uint64_t NumFullBlocks = StackSize / ProbeSize;
765515bfc66SJonas Paulsson   uint64_t Residual = StackSize % ProbeSize;
766023b5c1eSYusra Syeda   int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;
767515bfc66SJonas Paulsson   MachineBasicBlock *MBB = &PrologMBB;
768515bfc66SJonas Paulsson   MachineBasicBlock::iterator MBBI = StackAllocMI;
769515bfc66SJonas Paulsson   const DebugLoc DL = StackAllocMI->getDebugLoc();
770515bfc66SJonas Paulsson 
771515bfc66SJonas Paulsson   // Allocate a block of Size bytes on the stack and probe it.
772515bfc66SJonas Paulsson   auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,
773515bfc66SJonas Paulsson                               MachineBasicBlock::iterator InsPt, unsigned Size,
774515bfc66SJonas Paulsson                               bool EmitCFI) -> void {
775515bfc66SJonas Paulsson     emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);
776515bfc66SJonas Paulsson     if (EmitCFI) {
777515bfc66SJonas Paulsson       SPOffsetFromCFA -= Size;
778515bfc66SJonas Paulsson       buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);
779515bfc66SJonas Paulsson     }
780515bfc66SJonas Paulsson     // Probe by means of a volatile compare.
781515bfc66SJonas Paulsson     MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),
782515bfc66SJonas Paulsson       MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));
783515bfc66SJonas Paulsson     BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))
784515bfc66SJonas Paulsson       .addReg(SystemZ::R0D, RegState::Undef)
785515bfc66SJonas Paulsson       .addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)
786515bfc66SJonas Paulsson       .addMemOperand(MMO);
787515bfc66SJonas Paulsson   };
788515bfc66SJonas Paulsson 
78942f628c8SJonas Paulsson   bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
79042f628c8SJonas Paulsson   if (StoreBackchain)
79142f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))
79242f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
79342f628c8SJonas Paulsson 
79442f628c8SJonas Paulsson   MachineBasicBlock *DoneMBB = nullptr;
79542f628c8SJonas Paulsson   MachineBasicBlock *LoopMBB = nullptr;
796515bfc66SJonas Paulsson   if (NumFullBlocks < 3) {
797515bfc66SJonas Paulsson     // Emit unrolled probe statements.
798515bfc66SJonas Paulsson     for (unsigned int i = 0; i < NumFullBlocks; i++)
799515bfc66SJonas Paulsson       allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);
800515bfc66SJonas Paulsson   } else {
801515bfc66SJonas Paulsson     // Emit a loop probing the pages.
802515bfc66SJonas Paulsson     uint64_t LoopAlloc = ProbeSize * NumFullBlocks;
803515bfc66SJonas Paulsson     SPOffsetFromCFA -= LoopAlloc;
804515bfc66SJonas Paulsson 
80542f628c8SJonas Paulsson     // Use R0D to hold the exit value.
80642f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)
807515bfc66SJonas Paulsson       .addReg(SystemZ::R15D);
80842f628c8SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII);
80942f628c8SJonas Paulsson     emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII);
810023b5c1eSYusra Syeda     buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::ELFCallFrameSize + LoopAlloc),
811515bfc66SJonas Paulsson                  ZII);
812515bfc66SJonas Paulsson 
81342f628c8SJonas Paulsson     DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);
81442f628c8SJonas Paulsson     LoopMBB = SystemZ::emitBlockAfter(MBB);
815515bfc66SJonas Paulsson     MBB->addSuccessor(LoopMBB);
816515bfc66SJonas Paulsson     LoopMBB->addSuccessor(LoopMBB);
817515bfc66SJonas Paulsson     LoopMBB->addSuccessor(DoneMBB);
818515bfc66SJonas Paulsson 
819515bfc66SJonas Paulsson     MBB = LoopMBB;
820515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);
821515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))
82242f628c8SJonas Paulsson       .addReg(SystemZ::R15D).addReg(SystemZ::R0D);
823515bfc66SJonas Paulsson     BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))
824515bfc66SJonas Paulsson       .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);
825515bfc66SJonas Paulsson 
826515bfc66SJonas Paulsson     MBB = DoneMBB;
827515bfc66SJonas Paulsson     MBBI = DoneMBB->begin();
828515bfc66SJonas Paulsson     buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);
829515bfc66SJonas Paulsson   }
830515bfc66SJonas Paulsson 
831515bfc66SJonas Paulsson   if (Residual)
832515bfc66SJonas Paulsson     allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);
833515bfc66SJonas Paulsson 
834653b9769SJonas Paulsson   if (StoreBackchain)
83542f628c8SJonas Paulsson     BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG))
83642f628c8SJonas Paulsson       .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
837653b9769SJonas Paulsson       .addImm(getBackchainOffset(MF)).addReg(0);
83842f628c8SJonas Paulsson 
839515bfc66SJonas Paulsson   StackAllocMI->eraseFromParent();
84042f628c8SJonas Paulsson   if (DoneMBB != nullptr) {
84142f628c8SJonas Paulsson     // Compute the live-in lists for the new blocks.
84242f628c8SJonas Paulsson     recomputeLiveIns(*DoneMBB);
84342f628c8SJonas Paulsson     recomputeLiveIns(*LoopMBB);
84442f628c8SJonas Paulsson   }
845515bfc66SJonas Paulsson }
846515bfc66SJonas Paulsson 
hasFP(const MachineFunction & MF) const8470782e55cSNeumann Hon bool SystemZELFFrameLowering::hasFP(const MachineFunction &MF) const {
8485f613dfdSUlrich Weigand   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
849792853cbSJonas Paulsson           MF.getFrameInfo().hasVarSizedObjects());
8505f613dfdSUlrich Weigand }
8515f613dfdSUlrich Weigand 
getFrameIndexReference(const MachineFunction & MF,int FI,Register & FrameReg) const8520782e55cSNeumann Hon StackOffset SystemZELFFrameLowering::getFrameIndexReference(
8530782e55cSNeumann Hon     const MachineFunction &MF, int FI, Register &FrameReg) const {
854023b5c1eSYusra Syeda   // Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so
85561f5ba5cSJonas Paulsson   // add that difference here.
856d57bba7cSSander de Smalen   StackOffset Offset =
85761f5ba5cSJonas Paulsson       TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);
858023b5c1eSYusra Syeda   return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize);
85961f5ba5cSJonas Paulsson }
86061f5ba5cSJonas Paulsson 
getRegSpillOffset(MachineFunction & MF,Register Reg) const8610782e55cSNeumann Hon unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF,
8622481f26aSMatt Arsenault                                                     Register Reg) const {
86382879c29SJonas Paulsson   bool IsVarArg = MF.getFunction().isVarArg();
86482879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
86582879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
86682879c29SJonas Paulsson   unsigned Offset = RegSpillOffsets[Reg];
86782879c29SJonas Paulsson   if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
86882879c29SJonas Paulsson     if (SystemZ::GR64BitRegClass.contains(Reg))
86982879c29SJonas Paulsson       // Put all GPRs at the top of the Register save area with packed
87082879c29SJonas Paulsson       // stack. Make room for the backchain if needed.
87182879c29SJonas Paulsson       Offset += BackChain ? 24 : 32;
87282879c29SJonas Paulsson     else
87382879c29SJonas Paulsson       Offset = 0;
87482879c29SJonas Paulsson   }
87582879c29SJonas Paulsson   return Offset;
87682879c29SJonas Paulsson }
87782879c29SJonas Paulsson 
getOrCreateFramePointerSaveIndex(MachineFunction & MF) const8780782e55cSNeumann Hon int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex(
8790782e55cSNeumann Hon     MachineFunction &MF) const {
88061f5ba5cSJonas Paulsson   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
88161f5ba5cSJonas Paulsson   int FI = ZFI->getFramePointerSaveIndex();
88261f5ba5cSJonas Paulsson   if (!FI) {
88361f5ba5cSJonas Paulsson     MachineFrameInfo &MFFrame = MF.getFrameInfo();
884023b5c1eSYusra Syeda     int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize;
88582879c29SJonas Paulsson     FI = MFFrame.CreateFixedObject(8, Offset, false);
88661f5ba5cSJonas Paulsson     ZFI->setFramePointerSaveIndex(FI);
88761f5ba5cSJonas Paulsson   }
88861f5ba5cSJonas Paulsson   return FI;
88961f5ba5cSJonas Paulsson }
89082879c29SJonas Paulsson 
usePackedStack(MachineFunction & MF) const8910782e55cSNeumann Hon bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {
89282879c29SJonas Paulsson   bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
89382879c29SJonas Paulsson   bool BackChain = MF.getFunction().hasFnAttribute("backchain");
89482879c29SJonas Paulsson   bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
89582879c29SJonas Paulsson   if (HasPackedStackAttr && BackChain && !SoftFloat)
89682879c29SJonas Paulsson     report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
89782879c29SJonas Paulsson   bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
89882879c29SJonas Paulsson   return HasPackedStackAttr && CallConv;
89982879c29SJonas Paulsson }
9000782e55cSNeumann Hon 
SystemZXPLINKFrameLowering()9010782e55cSNeumann Hon SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering()
9029a358449SNeumann Hon     : SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0,
9030a950a2eSKai Nacke                            Align(32), /* StackRealignable */ false),
9040a950a2eSKai Nacke       RegSpillOffsets(-1) {
9050a950a2eSKai Nacke 
9060a950a2eSKai Nacke   // Create a mapping from register number to save slot offset.
9070a950a2eSKai Nacke   // These offsets are relative to the start of the local are area.
9080a950a2eSKai Nacke   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
909f15014ffSBenjamin Kramer   for (unsigned I = 0, E = array_lengthof(XPLINKSpillOffsetTable); I != E; ++I)
9100a950a2eSKai Nacke     RegSpillOffsets[XPLINKSpillOffsetTable[I].Reg] =
9110a950a2eSKai Nacke         XPLINKSpillOffsetTable[I].Offset;
9120a950a2eSKai Nacke }
9130a950a2eSKai Nacke 
914*e8f9a74fSNeumann Hon // Checks if the function is a potential candidate for being a XPLeaf routine.
isXPLeafCandidate(const MachineFunction & MF)915*e8f9a74fSNeumann Hon static bool isXPLeafCandidate(const MachineFunction &MF) {
916*e8f9a74fSNeumann Hon   const MachineFrameInfo &MFFrame = MF.getFrameInfo();
917*e8f9a74fSNeumann Hon   const MachineRegisterInfo &MRI = MF.getRegInfo();
918*e8f9a74fSNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
919*e8f9a74fSNeumann Hon   auto *Regs =
920*e8f9a74fSNeumann Hon       static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());
921*e8f9a74fSNeumann Hon 
922*e8f9a74fSNeumann Hon   // If function calls other functions including alloca, then it is not a XPLeaf
923*e8f9a74fSNeumann Hon   // routine.
924*e8f9a74fSNeumann Hon   if (MFFrame.hasCalls())
925*e8f9a74fSNeumann Hon     return false;
926*e8f9a74fSNeumann Hon 
927*e8f9a74fSNeumann Hon   // If the function has var Sized Objects, then it is not a XPLeaf routine.
928*e8f9a74fSNeumann Hon   if (MFFrame.hasVarSizedObjects())
929*e8f9a74fSNeumann Hon     return false;
930*e8f9a74fSNeumann Hon 
931*e8f9a74fSNeumann Hon   // If the function adjusts the stack, then it is not a XPLeaf routine.
932*e8f9a74fSNeumann Hon   if (MFFrame.adjustsStack())
933*e8f9a74fSNeumann Hon     return false;
934*e8f9a74fSNeumann Hon 
935*e8f9a74fSNeumann Hon   // If function modifies the stack pointer register, then it is not a XPLeaf
936*e8f9a74fSNeumann Hon   // routine.
937*e8f9a74fSNeumann Hon   if (MRI.isPhysRegModified(Regs->getStackPointerRegister()))
938*e8f9a74fSNeumann Hon     return false;
939*e8f9a74fSNeumann Hon 
940*e8f9a74fSNeumann Hon   // If function modifies the ADA register, then it is not a XPLeaf routine.
941*e8f9a74fSNeumann Hon   if (MRI.isPhysRegModified(Regs->getAddressOfCalleeRegister()))
942*e8f9a74fSNeumann Hon     return false;
943*e8f9a74fSNeumann Hon 
944*e8f9a74fSNeumann Hon   // If function modifies the return address register, then it is not a XPLeaf
945*e8f9a74fSNeumann Hon   // routine.
946*e8f9a74fSNeumann Hon   if (MRI.isPhysRegModified(Regs->getReturnFunctionAddressRegister()))
947*e8f9a74fSNeumann Hon     return false;
948*e8f9a74fSNeumann Hon 
949*e8f9a74fSNeumann Hon   // If the backchain pointer should be stored, then it is not a XPLeaf routine.
950*e8f9a74fSNeumann Hon   if (MF.getFunction().hasFnAttribute("backchain"))
951*e8f9a74fSNeumann Hon     return false;
952*e8f9a74fSNeumann Hon 
953*e8f9a74fSNeumann Hon   // If function acquires its own stack frame, then it is not a XPLeaf routine.
954*e8f9a74fSNeumann Hon   // At the time this function is called, only slots for local variables are
955*e8f9a74fSNeumann Hon   // allocated, so this is a very rough estimate.
956*e8f9a74fSNeumann Hon   if (MFFrame.estimateStackSize(MF) > 0)
957*e8f9a74fSNeumann Hon     return false;
958*e8f9a74fSNeumann Hon 
959*e8f9a74fSNeumann Hon   return true;
960*e8f9a74fSNeumann Hon }
961*e8f9a74fSNeumann Hon 
assignCalleeSavedSpillSlots(MachineFunction & MF,const TargetRegisterInfo * TRI,std::vector<CalleeSavedInfo> & CSI) const9620a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(
9630a950a2eSKai Nacke     MachineFunction &MF, const TargetRegisterInfo *TRI,
9640a950a2eSKai Nacke     std::vector<CalleeSavedInfo> &CSI) const {
9650a950a2eSKai Nacke   MachineFrameInfo &MFFrame = MF.getFrameInfo();
9660a950a2eSKai Nacke   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
9670a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
9680a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
969c45ec53eSNeumann Hon   auto &GRRegClass = SystemZ::GR64BitRegClass;
970c45ec53eSNeumann Hon 
971*e8f9a74fSNeumann Hon   // At this point, the result of isXPLeafCandidate() is not accurate because
972*e8f9a74fSNeumann Hon   // the size of the save area has not yet been determined. If
973*e8f9a74fSNeumann Hon   // isXPLeafCandidate() indicates a potential leaf function, and there are no
974*e8f9a74fSNeumann Hon   // callee-save registers, then it is indeed a leaf function, and we can early
975*e8f9a74fSNeumann Hon   // exit.
976*e8f9a74fSNeumann Hon   // TODO: It is possible for leaf functions to use callee-saved registers.
977*e8f9a74fSNeumann Hon   // It can use the 0-2k range between R4 and the caller's stack frame without
978*e8f9a74fSNeumann Hon   // acquiring its own stack frame.
979*e8f9a74fSNeumann Hon   bool IsLeaf = CSI.empty() && isXPLeafCandidate(MF);
980*e8f9a74fSNeumann Hon   if (IsLeaf)
981*e8f9a74fSNeumann Hon     return true;
982*e8f9a74fSNeumann Hon 
983c45ec53eSNeumann Hon   // For non-leaf functions:
984c45ec53eSNeumann Hon   // - the address of callee (entry point) register R6 must be saved
985c45ec53eSNeumann Hon   CSI.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister()));
986c45ec53eSNeumann Hon   CSI.back().setRestored(false);
987c45ec53eSNeumann Hon 
988c45ec53eSNeumann Hon   // The return address register R7 must be saved and restored.
989c45ec53eSNeumann Hon   CSI.push_back(CalleeSavedInfo(Regs.getReturnFunctionAddressRegister()));
990c45ec53eSNeumann Hon 
991c45ec53eSNeumann Hon   // If the function needs a frame pointer, or if the backchain pointer should
992c45ec53eSNeumann Hon   // be stored, then save the stack pointer register R4.
993c45ec53eSNeumann Hon   if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain"))
994c45ec53eSNeumann Hon     CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));
9950a950a2eSKai Nacke 
9960a950a2eSKai Nacke   // Scan the call-saved GPRs and find the bounds of the register spill area.
997c45ec53eSNeumann Hon   Register LowRestoreGPR = 0;
998c45ec53eSNeumann Hon   int LowRestoreOffset = INT32_MAX;
999c45ec53eSNeumann Hon   Register LowSpillGPR = 0;
1000c45ec53eSNeumann Hon   int LowSpillOffset = INT32_MAX;
1001c45ec53eSNeumann Hon   Register HighGPR = 0;
10020a950a2eSKai Nacke   int HighOffset = -1;
10030a950a2eSKai Nacke 
1004c45ec53eSNeumann Hon   for (auto &CS : CSI) {
1005d6b07348SJim Lin     Register Reg = CS.getReg();
10060a950a2eSKai Nacke     int Offset = RegSpillOffsets[Reg];
10070a950a2eSKai Nacke     if (Offset >= 0) {
10080a950a2eSKai Nacke       if (GRRegClass.contains(Reg)) {
1009c45ec53eSNeumann Hon         if (LowSpillOffset > Offset) {
1010c45ec53eSNeumann Hon           LowSpillOffset = Offset;
1011c45ec53eSNeumann Hon           LowSpillGPR = Reg;
1012c45ec53eSNeumann Hon         }
1013c45ec53eSNeumann Hon         if (CS.isRestored() && LowRestoreOffset > Offset) {
1014c45ec53eSNeumann Hon           LowRestoreOffset = Offset;
1015c45ec53eSNeumann Hon           LowRestoreGPR = Reg;
10160a950a2eSKai Nacke         }
10170a950a2eSKai Nacke 
10180a950a2eSKai Nacke         if (Offset > HighOffset) {
10190a950a2eSKai Nacke           HighOffset = Offset;
10200a950a2eSKai Nacke           HighGPR = Reg;
10210a950a2eSKai Nacke         }
1022c45ec53eSNeumann Hon         // Non-volatile GPRs are saved in the dedicated register save area at
1023c45ec53eSNeumann Hon         // the bottom of the stack and are not truly part of the "normal" stack
1024c45ec53eSNeumann Hon         // frame. Mark the frame index as NoAlloc to indicate it as such.
1025c45ec53eSNeumann Hon         unsigned RegSize = 8;
10260a950a2eSKai Nacke         int FrameIdx = MFFrame.CreateFixedSpillStackObject(RegSize, Offset);
10270a950a2eSKai Nacke         CS.setFrameIdx(FrameIdx);
1028c45ec53eSNeumann Hon         MFFrame.setStackID(FrameIdx, TargetStackID::NoAlloc);
10290a950a2eSKai Nacke       }
1030c45ec53eSNeumann Hon     } else {
1031d6b07348SJim Lin       Register Reg = CS.getReg();
10320a950a2eSKai Nacke       const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
10330a950a2eSKai Nacke       Align Alignment = TRI->getSpillAlign(*RC);
10340a950a2eSKai Nacke       unsigned Size = TRI->getSpillSize(*RC);
10350a950a2eSKai Nacke       Alignment = std::min(Alignment, getStackAlign());
10360a950a2eSKai Nacke       int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true);
10370a950a2eSKai Nacke       CS.setFrameIdx(FrameIdx);
10380a950a2eSKai Nacke     }
1039c45ec53eSNeumann Hon   }
1040c45ec53eSNeumann Hon 
1041c45ec53eSNeumann Hon   // Save the range of call-saved registers, for use by the
1042c45ec53eSNeumann Hon   // prologue/epilogue inserters.
1043c45ec53eSNeumann Hon   if (LowRestoreGPR)
1044c45ec53eSNeumann Hon     MFI->setRestoreGPRRegs(LowRestoreGPR, HighGPR, LowRestoreOffset);
1045c45ec53eSNeumann Hon 
1046c45ec53eSNeumann Hon   // Save the range of call-saved registers, for use by the epilogue inserter.
1047c45ec53eSNeumann Hon   assert(LowSpillGPR && "Expected registers to spill");
1048c45ec53eSNeumann Hon   MFI->setSpillGPRRegs(LowSpillGPR, HighGPR, LowSpillOffset);
10490a950a2eSKai Nacke 
10500a950a2eSKai Nacke   return true;
10510a950a2eSKai Nacke }
10520a950a2eSKai Nacke 
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const10530a950a2eSKai Nacke void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF,
10540a950a2eSKai Nacke                                                       BitVector &SavedRegs,
10550a950a2eSKai Nacke                                                       RegScavenger *RS) const {
10560a950a2eSKai Nacke   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
10570a950a2eSKai Nacke 
10580a950a2eSKai Nacke   bool HasFP = hasFP(MF);
10590a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
10600a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
10610a950a2eSKai Nacke 
10620a950a2eSKai Nacke   // If the function requires a frame pointer, record that the hard
10630a950a2eSKai Nacke   // frame pointer will be clobbered.
10640a950a2eSKai Nacke   if (HasFP)
10650a950a2eSKai Nacke     SavedRegs.set(Regs.getFramePointerRegister());
10660a950a2eSKai Nacke }
10670a950a2eSKai Nacke 
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,ArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const10680a950a2eSKai Nacke bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters(
10690a950a2eSKai Nacke     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
10700a950a2eSKai Nacke     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
10710a950a2eSKai Nacke   if (CSI.empty())
10720a950a2eSKai Nacke     return true;
10730a950a2eSKai Nacke 
10740a950a2eSKai Nacke   MachineFunction &MF = *MBB.getParent();
10750a950a2eSKai Nacke   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
10760a950a2eSKai Nacke   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
10770a950a2eSKai Nacke   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
10780a950a2eSKai Nacke   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
10790a950a2eSKai Nacke   SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();
10800a950a2eSKai Nacke   DebugLoc DL;
10810a950a2eSKai Nacke 
10820a950a2eSKai Nacke   // Save GPRs
10830a950a2eSKai Nacke   if (SpillGPRs.LowGPR) {
10840a950a2eSKai Nacke     assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&
10850a950a2eSKai Nacke            "Should be saving multiple registers");
10860a950a2eSKai Nacke 
10870a950a2eSKai Nacke     // Build an STM/STMG instruction.
10880a950a2eSKai Nacke     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));
10890a950a2eSKai Nacke 
10900a950a2eSKai Nacke     // Add the explicit register operands.
10910a950a2eSKai Nacke     addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);
10920a950a2eSKai Nacke     addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);
10930a950a2eSKai Nacke 
10940a950a2eSKai Nacke     // Add the address r4
10950a950a2eSKai Nacke     MIB.addReg(Regs.getStackPointerRegister());
10960a950a2eSKai Nacke 
10970a950a2eSKai Nacke     // Add the partial offset
10980a950a2eSKai Nacke     // We cannot add the actual offset as, at the stack is not finalized
10990a950a2eSKai Nacke     MIB.addImm(SpillGPRs.GPROffset);
11000a950a2eSKai Nacke 
11010a950a2eSKai Nacke     // Make sure all call-saved GPRs are included as operands and are
11020a950a2eSKai Nacke     // marked as live on entry.
11030a950a2eSKai Nacke     auto &GRRegClass = SystemZ::GR64BitRegClass;
1104ea5421bdSKazu Hirata     for (const CalleeSavedInfo &I : CSI) {
1105d6b07348SJim Lin       Register Reg = I.getReg();
11060a950a2eSKai Nacke       if (GRRegClass.contains(Reg))
11070a950a2eSKai Nacke         addSavedGPR(MBB, MIB, Reg, true);
11080a950a2eSKai Nacke     }
11090a950a2eSKai Nacke   }
11100a950a2eSKai Nacke 
11110a950a2eSKai Nacke   // Spill FPRs to the stack in the normal TargetInstrInfo way
1112ea5421bdSKazu Hirata   for (const CalleeSavedInfo &I : CSI) {
1113d6b07348SJim Lin     Register Reg = I.getReg();
11140a950a2eSKai Nacke     if (SystemZ::FP64BitRegClass.contains(Reg)) {
11150a950a2eSKai Nacke       MBB.addLiveIn(Reg);
1116ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
11170a950a2eSKai Nacke                                &SystemZ::FP64BitRegClass, TRI);
11180a950a2eSKai Nacke     }
11190a950a2eSKai Nacke     if (SystemZ::VR128BitRegClass.contains(Reg)) {
11200a950a2eSKai Nacke       MBB.addLiveIn(Reg);
1121ea5421bdSKazu Hirata       TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),
11220a950a2eSKai Nacke                                &SystemZ::VR128BitRegClass, TRI);
11230a950a2eSKai Nacke     }
11240a950a2eSKai Nacke   }
11250a950a2eSKai Nacke 
11260a950a2eSKai Nacke   return true;
11270a950a2eSKai Nacke }
11280782e55cSNeumann Hon 
restoreCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MutableArrayRef<CalleeSavedInfo> CSI,const TargetRegisterInfo * TRI) const11299a358449SNeumann Hon bool SystemZXPLINKFrameLowering::restoreCalleeSavedRegisters(
11309a358449SNeumann Hon     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
11319a358449SNeumann Hon     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
11329a358449SNeumann Hon 
11339a358449SNeumann Hon   if (CSI.empty())
11349a358449SNeumann Hon     return false;
11359a358449SNeumann Hon 
11369a358449SNeumann Hon   MachineFunction &MF = *MBB.getParent();
11379a358449SNeumann Hon   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
11389a358449SNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
11399a358449SNeumann Hon   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
11409a358449SNeumann Hon   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
11419a358449SNeumann Hon 
11429a358449SNeumann Hon   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
11439a358449SNeumann Hon 
11449a358449SNeumann Hon   // Restore FPRs in the normal TargetInstrInfo way.
11459a358449SNeumann Hon   for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
1146d6b07348SJim Lin     Register Reg = CSI[I].getReg();
11479a358449SNeumann Hon     if (SystemZ::FP64BitRegClass.contains(Reg))
11489a358449SNeumann Hon       TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
11499a358449SNeumann Hon                                 &SystemZ::FP64BitRegClass, TRI);
11509a358449SNeumann Hon     if (SystemZ::VR128BitRegClass.contains(Reg))
11519a358449SNeumann Hon       TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(),
11529a358449SNeumann Hon                                 &SystemZ::VR128BitRegClass, TRI);
11539a358449SNeumann Hon   }
11549a358449SNeumann Hon 
11559a358449SNeumann Hon   // Restore call-saved GPRs (but not call-clobbered varargs, which at
11569a358449SNeumann Hon   // this point might hold return values).
11579a358449SNeumann Hon   SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();
11589a358449SNeumann Hon   if (RestoreGPRs.LowGPR) {
11599a358449SNeumann Hon     assert(isInt<20>(Regs.getStackPointerBias() + RestoreGPRs.GPROffset));
11609a358449SNeumann Hon     if (RestoreGPRs.LowGPR == RestoreGPRs.HighGPR)
11619a358449SNeumann Hon       // Build an LG/L instruction.
11629a358449SNeumann Hon       BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LG), RestoreGPRs.LowGPR)
11639a358449SNeumann Hon           .addReg(Regs.getStackPointerRegister())
11649a358449SNeumann Hon           .addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset)
11659a358449SNeumann Hon           .addReg(0);
11669a358449SNeumann Hon     else {
11679a358449SNeumann Hon       // Build an LMG/LM instruction.
11689a358449SNeumann Hon       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));
11699a358449SNeumann Hon 
11709a358449SNeumann Hon       // Add the explicit register operands.
11719a358449SNeumann Hon       MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);
11729a358449SNeumann Hon       MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);
11739a358449SNeumann Hon 
11749a358449SNeumann Hon       // Add the address.
11759a358449SNeumann Hon       MIB.addReg(Regs.getStackPointerRegister());
11769a358449SNeumann Hon       MIB.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset);
11779a358449SNeumann Hon 
11789a358449SNeumann Hon       // Do a second scan adding regs as being defined by instruction
11799a358449SNeumann Hon       for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
1180d6b07348SJim Lin         Register Reg = CSI[I].getReg();
11819a358449SNeumann Hon         if (Reg > RestoreGPRs.LowGPR && Reg < RestoreGPRs.HighGPR)
11829a358449SNeumann Hon           MIB.addReg(Reg, RegState::ImplicitDefine);
11839a358449SNeumann Hon       }
11849a358449SNeumann Hon     }
11859a358449SNeumann Hon   }
11869a358449SNeumann Hon 
11879a358449SNeumann Hon   return true;
11889a358449SNeumann Hon }
11899a358449SNeumann Hon 
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const11900782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF,
11919a358449SNeumann Hon                                               MachineBasicBlock &MBB) const {
11929a358449SNeumann Hon   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
11939a358449SNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
11949a358449SNeumann Hon   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
11959a358449SNeumann Hon   MachineBasicBlock::iterator MBBI = MBB.begin();
11969a358449SNeumann Hon   auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());
11979a358449SNeumann Hon   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
11989a358449SNeumann Hon   MachineFrameInfo &MFFrame = MF.getFrameInfo();
11999a358449SNeumann Hon   MachineInstr *StoreInstr = nullptr;
1200*e8f9a74fSNeumann Hon 
1201*e8f9a74fSNeumann Hon   determineFrameLayout(MF);
1202*e8f9a74fSNeumann Hon 
12039a358449SNeumann Hon   bool HasFP = hasFP(MF);
12049a358449SNeumann Hon   // Debug location must be unknown since the first debug location is used
12059a358449SNeumann Hon   // to determine the end of the prologue.
12069a358449SNeumann Hon   DebugLoc DL;
12079a358449SNeumann Hon   uint64_t Offset = 0;
12089a358449SNeumann Hon 
1209*e8f9a74fSNeumann Hon   const uint64_t StackSize = MFFrame.getStackSize();
12109a358449SNeumann Hon 
12119a358449SNeumann Hon   if (ZFI->getSpillGPRRegs().LowGPR) {
12129a358449SNeumann Hon     // Skip over the GPR saves.
12139a358449SNeumann Hon     if ((MBBI != MBB.end()) && ((MBBI->getOpcode() == SystemZ::STMG))) {
12149a358449SNeumann Hon       const int Operand = 3;
12159a358449SNeumann Hon       // Now we can set the offset for the operation, since now the Stack
12169a358449SNeumann Hon       // has been finalized.
12179a358449SNeumann Hon       Offset = Regs.getStackPointerBias() + MBBI->getOperand(Operand).getImm();
12189a358449SNeumann Hon       // Maximum displacement for STMG instruction.
12199a358449SNeumann Hon       if (isInt<20>(Offset - StackSize))
12209a358449SNeumann Hon         Offset -= StackSize;
12219a358449SNeumann Hon       else
12229a358449SNeumann Hon         StoreInstr = &*MBBI;
12239a358449SNeumann Hon       MBBI->getOperand(Operand).setImm(Offset);
12249a358449SNeumann Hon       ++MBBI;
12259a358449SNeumann Hon     } else
12269a358449SNeumann Hon       llvm_unreachable("Couldn't skip over GPR saves");
12279a358449SNeumann Hon   }
12289a358449SNeumann Hon 
12299a358449SNeumann Hon   if (StackSize) {
12309a358449SNeumann Hon     MachineBasicBlock::iterator InsertPt = StoreInstr ? StoreInstr : MBBI;
12319a358449SNeumann Hon     // Allocate StackSize bytes.
12329a358449SNeumann Hon     int64_t Delta = -int64_t(StackSize);
12339a358449SNeumann Hon 
12349a358449SNeumann Hon     // In case the STM(G) instruction also stores SP (R4), but the displacement
12359a358449SNeumann Hon     // is too large, the SP register is manipulated first before storing,
12369a358449SNeumann Hon     // resulting in the wrong value stored and retrieved later. In this case, we
12379a358449SNeumann Hon     // need to temporarily save the value of SP, and store it later to memory.
12389a358449SNeumann Hon     if (StoreInstr && HasFP) {
12399a358449SNeumann Hon       // Insert LR r0,r4 before STMG instruction.
12409a358449SNeumann Hon       BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::LGR))
12419a358449SNeumann Hon           .addReg(SystemZ::R0D, RegState::Define)
12429a358449SNeumann Hon           .addReg(SystemZ::R4D);
12439a358449SNeumann Hon       // Insert ST r0,xxx(,r4) after STMG instruction.
12449a358449SNeumann Hon       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
12459a358449SNeumann Hon           .addReg(SystemZ::R0D, RegState::Kill)
12469a358449SNeumann Hon           .addReg(SystemZ::R4D)
12479a358449SNeumann Hon           .addImm(Offset)
12489a358449SNeumann Hon           .addReg(0);
12499a358449SNeumann Hon     }
12509a358449SNeumann Hon 
12519a358449SNeumann Hon     emitIncrement(MBB, InsertPt, DL, Regs.getStackPointerRegister(), Delta,
12529a358449SNeumann Hon                   ZII);
1253eb3e09c9SNeumann Hon 
1254eb3e09c9SNeumann Hon     // If the requested stack size is larger than the guard page, then we need
1255eb3e09c9SNeumann Hon     // to check if we need to call the stack extender. This requires adding a
1256eb3e09c9SNeumann Hon     // conditional branch, but splitting the prologue block is not possible at
1257eb3e09c9SNeumann Hon     // this point since it would invalidate the SaveBlocks / RestoreBlocks sets
1258eb3e09c9SNeumann Hon     // of PEI in the single block function case. Build a pseudo to be handled
1259eb3e09c9SNeumann Hon     // later by inlineStackProbe().
1260eb3e09c9SNeumann Hon     const uint64_t GuardPageSize = 1024 * 1024;
1261eb3e09c9SNeumann Hon     if (StackSize > GuardPageSize) {
1262eb3e09c9SNeumann Hon       assert(StoreInstr && "Wrong insertion point");
1263eb3e09c9SNeumann Hon       BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::XPLINK_STACKALLOC));
1264eb3e09c9SNeumann Hon     }
12659a358449SNeumann Hon   }
12669a358449SNeumann Hon 
12679a358449SNeumann Hon   if (HasFP) {
12689a358449SNeumann Hon     // Copy the base of the frame to Frame Pointer Register.
12699a358449SNeumann Hon     BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR),
12709a358449SNeumann Hon             Regs.getFramePointerRegister())
12719a358449SNeumann Hon         .addReg(Regs.getStackPointerRegister());
12729a358449SNeumann Hon 
12739a358449SNeumann Hon     // Mark the FramePtr as live at the beginning of every block except
12749a358449SNeumann Hon     // the entry block.  (We'll have marked R8 as live on entry when
12759a358449SNeumann Hon     // saving the GPRs.)
12765605a1eeSKazu Hirata     for (MachineBasicBlock &B : llvm::drop_begin(MF))
12775605a1eeSKazu Hirata       B.addLiveIn(Regs.getFramePointerRegister());
12789a358449SNeumann Hon   }
12799a358449SNeumann Hon }
12800782e55cSNeumann Hon 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const12810782e55cSNeumann Hon void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF,
12829a358449SNeumann Hon                                               MachineBasicBlock &MBB) const {
12839a358449SNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
12849a358449SNeumann Hon   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
12859a358449SNeumann Hon   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
12869a358449SNeumann Hon   MachineFrameInfo &MFFrame = MF.getFrameInfo();
12879a358449SNeumann Hon   auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());
12889a358449SNeumann Hon   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
12899a358449SNeumann Hon 
12909a358449SNeumann Hon   // Skip the return instruction.
12919a358449SNeumann Hon   assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");
12929a358449SNeumann Hon 
12939a358449SNeumann Hon   uint64_t StackSize = MFFrame.getStackSize();
12949a358449SNeumann Hon   if (StackSize) {
12959a358449SNeumann Hon     unsigned SPReg = Regs.getStackPointerRegister();
12969a358449SNeumann Hon     if (ZFI->getRestoreGPRRegs().LowGPR != SPReg) {
12979a358449SNeumann Hon       DebugLoc DL = MBBI->getDebugLoc();
12989a358449SNeumann Hon       emitIncrement(MBB, MBBI, DL, SPReg, StackSize, ZII);
12999a358449SNeumann Hon     }
13009a358449SNeumann Hon   }
13019a358449SNeumann Hon }
13020782e55cSNeumann Hon 
1303eb3e09c9SNeumann Hon // Emit a compare of the stack pointer against the stack floor, and a call to
1304eb3e09c9SNeumann Hon // the LE stack extender if needed.
inlineStackProbe(MachineFunction & MF,MachineBasicBlock & PrologMBB) const1305eb3e09c9SNeumann Hon void SystemZXPLINKFrameLowering::inlineStackProbe(
1306eb3e09c9SNeumann Hon     MachineFunction &MF, MachineBasicBlock &PrologMBB) const {
1307eb3e09c9SNeumann Hon   auto *ZII =
1308eb3e09c9SNeumann Hon       static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
1309eb3e09c9SNeumann Hon 
1310eb3e09c9SNeumann Hon   MachineInstr *StackAllocMI = nullptr;
1311eb3e09c9SNeumann Hon   for (MachineInstr &MI : PrologMBB)
1312eb3e09c9SNeumann Hon     if (MI.getOpcode() == SystemZ::XPLINK_STACKALLOC) {
1313eb3e09c9SNeumann Hon       StackAllocMI = &MI;
1314eb3e09c9SNeumann Hon       break;
1315eb3e09c9SNeumann Hon     }
1316eb3e09c9SNeumann Hon   if (StackAllocMI == nullptr)
1317eb3e09c9SNeumann Hon     return;
1318eb3e09c9SNeumann Hon 
1319eb3e09c9SNeumann Hon   MachineBasicBlock &MBB = PrologMBB;
1320eb3e09c9SNeumann Hon   const DebugLoc DL = StackAllocMI->getDebugLoc();
1321eb3e09c9SNeumann Hon 
1322eb3e09c9SNeumann Hon   // The 2nd half of block MBB after split.
1323eb3e09c9SNeumann Hon   MachineBasicBlock *NextMBB;
1324eb3e09c9SNeumann Hon 
1325eb3e09c9SNeumann Hon   // Add new basic block for the call to the stack overflow function.
1326eb3e09c9SNeumann Hon   MachineBasicBlock *StackExtMBB =
1327eb3e09c9SNeumann Hon       MF.CreateMachineBasicBlock(MBB.getBasicBlock());
1328eb3e09c9SNeumann Hon   MF.push_back(StackExtMBB);
1329eb3e09c9SNeumann Hon 
1330eb3e09c9SNeumann Hon   // LG r3,72(,r3)
1331eb3e09c9SNeumann Hon   BuildMI(StackExtMBB, DL, ZII->get(SystemZ::LG), SystemZ::R3D)
1332eb3e09c9SNeumann Hon       .addReg(SystemZ::R3D)
1333eb3e09c9SNeumann Hon       .addImm(72)
1334eb3e09c9SNeumann Hon       .addReg(0);
1335eb3e09c9SNeumann Hon   // BASR r3,r3
1336eb3e09c9SNeumann Hon   BuildMI(StackExtMBB, DL, ZII->get(SystemZ::CallBASR_STACKEXT))
1337eb3e09c9SNeumann Hon       .addReg(SystemZ::R3D);
1338eb3e09c9SNeumann Hon 
1339eb3e09c9SNeumann Hon   // LLGT r3,1208
1340eb3e09c9SNeumann Hon   BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LLGT), SystemZ::R3D)
1341eb3e09c9SNeumann Hon       .addReg(0)
1342eb3e09c9SNeumann Hon       .addImm(1208)
1343eb3e09c9SNeumann Hon       .addReg(0);
1344eb3e09c9SNeumann Hon   // CG r4,64(,r3)
1345eb3e09c9SNeumann Hon   BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::CG))
1346eb3e09c9SNeumann Hon       .addReg(SystemZ::R4D)
1347eb3e09c9SNeumann Hon       .addReg(SystemZ::R3D)
1348eb3e09c9SNeumann Hon       .addImm(64)
1349eb3e09c9SNeumann Hon       .addReg(0);
1350eb3e09c9SNeumann Hon   // JLL b'0100',F'37'
1351eb3e09c9SNeumann Hon   BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::BRC))
1352eb3e09c9SNeumann Hon       .addImm(SystemZ::CCMASK_ICMP)
1353eb3e09c9SNeumann Hon       .addImm(SystemZ::CCMASK_CMP_LT)
1354eb3e09c9SNeumann Hon       .addMBB(StackExtMBB);
1355eb3e09c9SNeumann Hon 
1356eb3e09c9SNeumann Hon   NextMBB = SystemZ::splitBlockBefore(StackAllocMI, &MBB);
1357eb3e09c9SNeumann Hon   MBB.addSuccessor(NextMBB);
1358eb3e09c9SNeumann Hon   MBB.addSuccessor(StackExtMBB);
1359eb3e09c9SNeumann Hon 
1360eb3e09c9SNeumann Hon   // Add jump back from stack extension BB.
1361eb3e09c9SNeumann Hon   BuildMI(StackExtMBB, DL, ZII->get(SystemZ::J)).addMBB(NextMBB);
1362eb3e09c9SNeumann Hon   StackExtMBB->addSuccessor(NextMBB);
1363eb3e09c9SNeumann Hon 
1364eb3e09c9SNeumann Hon   StackAllocMI->eraseFromParent();
1365eb3e09c9SNeumann Hon 
1366eb3e09c9SNeumann Hon   // Compute the live-in lists for the new blocks.
1367eb3e09c9SNeumann Hon   recomputeLiveIns(*NextMBB);
1368eb3e09c9SNeumann Hon   recomputeLiveIns(*StackExtMBB);
1369eb3e09c9SNeumann Hon }
1370eb3e09c9SNeumann Hon 
hasFP(const MachineFunction & MF) const13710782e55cSNeumann Hon bool SystemZXPLINKFrameLowering::hasFP(const MachineFunction &MF) const {
13729a358449SNeumann Hon   return (MF.getFrameInfo().hasVarSizedObjects());
13739a358449SNeumann Hon }
13749a358449SNeumann Hon 
processFunctionBeforeFrameFinalized(MachineFunction & MF,RegScavenger * RS) const13759a358449SNeumann Hon void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized(
13769a358449SNeumann Hon     MachineFunction &MF, RegScavenger *RS) const {
13779a358449SNeumann Hon   MachineFrameInfo &MFFrame = MF.getFrameInfo();
13789a358449SNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
13799a358449SNeumann Hon   auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
13809a358449SNeumann Hon 
13819a358449SNeumann Hon   // Setup stack frame offset
13829a358449SNeumann Hon   MFFrame.setOffsetAdjustment(Regs.getStackPointerBias());
13830782e55cSNeumann Hon }
1384*e8f9a74fSNeumann Hon 
1385*e8f9a74fSNeumann Hon // Determines the size of the frame, and creates the deferred spill objects.
determineFrameLayout(MachineFunction & MF) const1386*e8f9a74fSNeumann Hon void SystemZXPLINKFrameLowering::determineFrameLayout(
1387*e8f9a74fSNeumann Hon     MachineFunction &MF) const {
1388*e8f9a74fSNeumann Hon   MachineFrameInfo &MFFrame = MF.getFrameInfo();
1389*e8f9a74fSNeumann Hon   const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
1390*e8f9a74fSNeumann Hon   auto *Regs =
1391*e8f9a74fSNeumann Hon       static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());
1392*e8f9a74fSNeumann Hon 
1393*e8f9a74fSNeumann Hon   uint64_t StackSize = MFFrame.getStackSize();
1394*e8f9a74fSNeumann Hon   if (StackSize == 0)
1395*e8f9a74fSNeumann Hon     return;
1396*e8f9a74fSNeumann Hon 
1397*e8f9a74fSNeumann Hon   // Add the size of the register save area and the reserved area to the size.
1398*e8f9a74fSNeumann Hon   StackSize += Regs->getCallFrameSize();
1399*e8f9a74fSNeumann Hon   MFFrame.setStackSize(StackSize);
1400*e8f9a74fSNeumann Hon 
1401*e8f9a74fSNeumann Hon   // We now know the stack size. Create the fixed spill stack objects for the
1402*e8f9a74fSNeumann Hon   // register save area now. This has no impact on the stack frame layout, as
1403*e8f9a74fSNeumann Hon   // this is already computed. However, it makes sure that all callee saved
1404*e8f9a74fSNeumann Hon   // registers have a valid frame index assigned.
1405*e8f9a74fSNeumann Hon   const unsigned RegSize = MF.getDataLayout().getPointerSize();
1406*e8f9a74fSNeumann Hon   for (auto &CS : MFFrame.getCalleeSavedInfo()) {
1407*e8f9a74fSNeumann Hon     int Offset = RegSpillOffsets[CS.getReg()];
1408*e8f9a74fSNeumann Hon     if (Offset >= 0)
1409*e8f9a74fSNeumann Hon       CS.setFrameIdx(
1410*e8f9a74fSNeumann Hon           MFFrame.CreateFixedSpillStackObject(RegSize, Offset - StackSize));
1411*e8f9a74fSNeumann Hon   }
1412*e8f9a74fSNeumann Hon }
1413