Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
35269 views
//===-- SystemZFrameLowering.cpp - Frame lowering for SystemZ -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "SystemZFrameLowering.h"9#include "SystemZCallingConv.h"10#include "SystemZInstrBuilder.h"11#include "SystemZInstrInfo.h"12#include "SystemZMachineFunctionInfo.h"13#include "SystemZRegisterInfo.h"14#include "SystemZSubtarget.h"15#include "llvm/CodeGen/LivePhysRegs.h"16#include "llvm/CodeGen/MachineModuleInfo.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/RegisterScavenging.h"19#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"20#include "llvm/IR/Function.h"21#include "llvm/Target/TargetMachine.h"2223using namespace llvm;2425namespace {26// The ABI-defined register save slots, relative to the CFA (i.e.27// incoming stack pointer + SystemZMC::ELFCallFrameSize).28static const TargetFrameLowering::SpillSlot ELFSpillOffsetTable[] = {29{ SystemZ::R2D, 0x10 },30{ SystemZ::R3D, 0x18 },31{ SystemZ::R4D, 0x20 },32{ SystemZ::R5D, 0x28 },33{ SystemZ::R6D, 0x30 },34{ SystemZ::R7D, 0x38 },35{ SystemZ::R8D, 0x40 },36{ SystemZ::R9D, 0x48 },37{ SystemZ::R10D, 0x50 },38{ SystemZ::R11D, 0x58 },39{ SystemZ::R12D, 0x60 },40{ SystemZ::R13D, 0x68 },41{ SystemZ::R14D, 0x70 },42{ SystemZ::R15D, 0x78 },43{ SystemZ::F0D, 0x80 },44{ SystemZ::F2D, 0x88 },45{ SystemZ::F4D, 0x90 },46{ SystemZ::F6D, 0x98 }47};4849static const TargetFrameLowering::SpillSlot XPLINKSpillOffsetTable[] = {50{SystemZ::R4D, 0x00}, {SystemZ::R5D, 0x08}, {SystemZ::R6D, 0x10},51{SystemZ::R7D, 0x18}, {SystemZ::R8D, 0x20}, {SystemZ::R9D, 0x28},52{SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40},53{SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}};54} // end anonymous namespace5556SystemZFrameLowering::SystemZFrameLowering(StackDirection D, Align StackAl,57int LAO, Align TransAl,58bool StackReal, unsigned PointerSize)59: TargetFrameLowering(D, StackAl, LAO, TransAl, StackReal),60PointerSize(PointerSize) {}6162std::unique_ptr<SystemZFrameLowering>63SystemZFrameLowering::create(const SystemZSubtarget &STI) {64unsigned PtrSz =65STI.getTargetLowering()->getTargetMachine().getPointerSize(0);66if (STI.isTargetXPLINK64())67return std::make_unique<SystemZXPLINKFrameLowering>(PtrSz);68return std::make_unique<SystemZELFFrameLowering>(PtrSz);69}7071namespace {72struct SZFrameSortingObj {73bool IsValid = false; // True if we care about this Object.74uint32_t ObjectIndex = 0; // Index of Object into MFI list.75uint64_t ObjectSize = 0; // Size of Object in bytes.76uint32_t D12Count = 0; // 12-bit displacement only.77uint32_t DPairCount = 0; // 12 or 20 bit displacement.78};79typedef std::vector<SZFrameSortingObj> SZFrameObjVec;80} // namespace8182// TODO: Move to base class.83void SystemZELFFrameLowering::orderFrameObjects(84const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {85const MachineFrameInfo &MFI = MF.getFrameInfo();86auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();8788// Make a vector of sorting objects to track all MFI objects and mark those89// to be sorted as valid.90if (ObjectsToAllocate.size() <= 1)91return;92SZFrameObjVec SortingObjects(MFI.getObjectIndexEnd());93for (auto &Obj : ObjectsToAllocate) {94SortingObjects[Obj].IsValid = true;95SortingObjects[Obj].ObjectIndex = Obj;96SortingObjects[Obj].ObjectSize = MFI.getObjectSize(Obj);97}9899// Examine uses for each object and record short (12-bit) and "pair"100// displacement types.101for (auto &MBB : MF)102for (auto &MI : MBB) {103if (MI.isDebugInstr())104continue;105for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {106const MachineOperand &MO = MI.getOperand(I);107if (!MO.isFI())108continue;109int Index = MO.getIndex();110if (Index >= 0 && Index < MFI.getObjectIndexEnd() &&111SortingObjects[Index].IsValid) {112if (TII->hasDisplacementPairInsn(MI.getOpcode()))113SortingObjects[Index].DPairCount++;114else if (!(MI.getDesc().TSFlags & SystemZII::Has20BitOffset))115SortingObjects[Index].D12Count++;116}117}118}119120// Sort all objects for short/paired displacements, which should be121// sufficient as it seems like all frame objects typically are within the122// long displacement range. Sorting works by computing the "density" as123// Count / ObjectSize. The comparisons of two such fractions are refactored124// by multiplying both sides with A.ObjectSize * B.ObjectSize, in order to125// eliminate the (fp) divisions. A higher density object needs to go after126// in the list in order for it to end up lower on the stack.127auto CmpD12 = [](const SZFrameSortingObj &A, const SZFrameSortingObj &B) {128// Put all invalid and variable sized objects at the end.129if (!A.IsValid || !B.IsValid)130return A.IsValid;131if (!A.ObjectSize || !B.ObjectSize)132return A.ObjectSize > 0;133uint64_t ADensityCmp = A.D12Count * B.ObjectSize;134uint64_t BDensityCmp = B.D12Count * A.ObjectSize;135if (ADensityCmp != BDensityCmp)136return ADensityCmp < BDensityCmp;137return A.DPairCount * B.ObjectSize < B.DPairCount * A.ObjectSize;138};139std::stable_sort(SortingObjects.begin(), SortingObjects.end(), CmpD12);140141// Now modify the original list to represent the final order that142// we want.143unsigned Idx = 0;144for (auto &Obj : SortingObjects) {145// All invalid items are sorted at the end, so it's safe to stop.146if (!Obj.IsValid)147break;148ObjectsToAllocate[Idx++] = Obj.ObjectIndex;149}150}151152bool SystemZFrameLowering::hasReservedCallFrame(153const MachineFunction &MF) const {154// The ELF ABI requires us to allocate 160 bytes of stack space for the155// callee, with any outgoing stack arguments being placed above that. It156// seems better to make that area a permanent feature of the frame even if157// we're using a frame pointer. Similarly, 64-bit XPLINK requires 96 bytes158// of stack space for the register save area.159return true;160}161162bool SystemZELFFrameLowering::assignCalleeSavedSpillSlots(163MachineFunction &MF, const TargetRegisterInfo *TRI,164std::vector<CalleeSavedInfo> &CSI) const {165SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();166MachineFrameInfo &MFFrame = MF.getFrameInfo();167bool IsVarArg = MF.getFunction().isVarArg();168if (CSI.empty())169return true; // Early exit if no callee saved registers are modified!170171unsigned LowGPR = 0;172unsigned HighGPR = SystemZ::R15D;173int StartSPOffset = SystemZMC::ELFCallFrameSize;174for (auto &CS : CSI) {175Register Reg = CS.getReg();176int Offset = getRegSpillOffset(MF, Reg);177if (Offset) {178if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {179LowGPR = Reg;180StartSPOffset = Offset;181}182Offset -= SystemZMC::ELFCallFrameSize;183int FrameIdx =184MFFrame.CreateFixedSpillStackObject(getPointerSize(), Offset);185CS.setFrameIdx(FrameIdx);186} else187CS.setFrameIdx(INT32_MAX);188}189190// Save the range of call-saved registers, for use by the191// prologue/epilogue inserters.192ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);193if (IsVarArg) {194// Also save the GPR varargs, if any. R6D is call-saved, so would195// already be included, but we also need to handle the call-clobbered196// argument registers.197Register FirstGPR = ZFI->getVarArgsFirstGPR();198if (FirstGPR < SystemZ::ELFNumArgGPRs) {199unsigned Reg = SystemZ::ELFArgGPRs[FirstGPR];200int Offset = getRegSpillOffset(MF, Reg);201if (StartSPOffset > Offset) {202LowGPR = Reg; StartSPOffset = Offset;203}204}205}206ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);207208// Create fixed stack objects for the remaining registers.209int CurrOffset = -SystemZMC::ELFCallFrameSize;210if (usePackedStack(MF))211CurrOffset += StartSPOffset;212213for (auto &CS : CSI) {214if (CS.getFrameIdx() != INT32_MAX)215continue;216Register Reg = CS.getReg();217const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);218unsigned Size = TRI->getSpillSize(*RC);219CurrOffset -= Size;220assert(CurrOffset % 8 == 0 &&221"8-byte alignment required for for all register save slots");222int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);223CS.setFrameIdx(FrameIdx);224}225226return true;227}228229void SystemZELFFrameLowering::determineCalleeSaves(MachineFunction &MF,230BitVector &SavedRegs,231RegScavenger *RS) const {232TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);233234MachineFrameInfo &MFFrame = MF.getFrameInfo();235const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();236bool HasFP = hasFP(MF);237SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();238bool IsVarArg = MF.getFunction().isVarArg();239240// va_start stores incoming FPR varargs in the normal way, but delegates241// the saving of incoming GPR varargs to spillCalleeSavedRegisters().242// Record these pending uses, which typically include the call-saved243// argument register R6D.244if (IsVarArg)245for (unsigned I = MFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)246SavedRegs.set(SystemZ::ELFArgGPRs[I]);247248// If there are any landing pads, entering them will modify r6/r7.249if (!MF.getLandingPads().empty()) {250SavedRegs.set(SystemZ::R6D);251SavedRegs.set(SystemZ::R7D);252}253254// If the function requires a frame pointer, record that the hard255// frame pointer will be clobbered.256if (HasFP)257SavedRegs.set(SystemZ::R11D);258259// If the function calls other functions, record that the return260// address register will be clobbered.261if (MFFrame.hasCalls())262SavedRegs.set(SystemZ::R14D);263264// If we are saving GPRs other than the stack pointer, we might as well265// save and restore the stack pointer at the same time, via STMG and LMG.266// This allows the deallocation to be done by the LMG, rather than needing267// a separate %r15 addition.268const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);269for (unsigned I = 0; CSRegs[I]; ++I) {270unsigned Reg = CSRegs[I];271if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {272SavedRegs.set(SystemZ::R15D);273break;274}275}276}277278SystemZELFFrameLowering::SystemZELFFrameLowering(unsigned PointerSize)279: SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0,280Align(8), /* StackRealignable */ false, PointerSize),281RegSpillOffsets(0) {282283// Due to the SystemZ ABI, the DWARF CFA (Canonical Frame Address) is not284// equal to the incoming stack pointer, but to incoming stack pointer plus285// 160. Instead of using a Local Area Offset, the Register save area will286// be occupied by fixed frame objects, and all offsets are actually287// relative to CFA.288289// Create a mapping from register number to save slot offset.290// These offsets are relative to the start of the register save area.291RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);292for (const auto &Entry : ELFSpillOffsetTable)293RegSpillOffsets[Entry.Reg] = Entry.Offset;294}295296// Add GPR64 to the save instruction being built by MIB, which is in basic297// block MBB. IsImplicit says whether this is an explicit operand to the298// instruction, or an implicit one that comes between the explicit start299// and end registers.300static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB,301unsigned GPR64, bool IsImplicit) {302const TargetRegisterInfo *RI =303MBB.getParent()->getSubtarget().getRegisterInfo();304Register GPR32 = RI->getSubReg(GPR64, SystemZ::subreg_l32);305bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);306if (!IsLive || !IsImplicit) {307MIB.addReg(GPR64, getImplRegState(IsImplicit) | getKillRegState(!IsLive));308if (!IsLive)309MBB.addLiveIn(GPR64);310}311}312313bool SystemZELFFrameLowering::spillCalleeSavedRegisters(314MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,315ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {316if (CSI.empty())317return false;318319MachineFunction &MF = *MBB.getParent();320const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();321SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();322bool IsVarArg = MF.getFunction().isVarArg();323DebugLoc DL;324325// Save GPRs326SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();327if (SpillGPRs.LowGPR) {328assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&329"Should be saving %r15 and something else");330331// Build an STMG instruction.332MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));333334// Add the explicit register operands.335addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);336addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);337338// Add the address.339MIB.addReg(SystemZ::R15D).addImm(SpillGPRs.GPROffset);340341// Make sure all call-saved GPRs are included as operands and are342// marked as live on entry.343for (const CalleeSavedInfo &I : CSI) {344Register Reg = I.getReg();345if (SystemZ::GR64BitRegClass.contains(Reg))346addSavedGPR(MBB, MIB, Reg, true);347}348349// ...likewise GPR varargs.350if (IsVarArg)351for (unsigned I = ZFI->getVarArgsFirstGPR(); I < SystemZ::ELFNumArgGPRs; ++I)352addSavedGPR(MBB, MIB, SystemZ::ELFArgGPRs[I], true);353}354355// Save FPRs/VRs in the normal TargetInstrInfo way.356for (const CalleeSavedInfo &I : CSI) {357Register Reg = I.getReg();358if (SystemZ::FP64BitRegClass.contains(Reg)) {359MBB.addLiveIn(Reg);360TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),361&SystemZ::FP64BitRegClass, TRI, Register());362}363if (SystemZ::VR128BitRegClass.contains(Reg)) {364MBB.addLiveIn(Reg);365TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),366&SystemZ::VR128BitRegClass, TRI, Register());367}368}369370return true;371}372373bool SystemZELFFrameLowering::restoreCalleeSavedRegisters(374MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,375MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {376if (CSI.empty())377return false;378379MachineFunction &MF = *MBB.getParent();380const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();381SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();382bool HasFP = hasFP(MF);383DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();384385// Restore FPRs/VRs in the normal TargetInstrInfo way.386for (const CalleeSavedInfo &I : CSI) {387Register Reg = I.getReg();388if (SystemZ::FP64BitRegClass.contains(Reg))389TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),390&SystemZ::FP64BitRegClass, TRI, Register());391if (SystemZ::VR128BitRegClass.contains(Reg))392TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),393&SystemZ::VR128BitRegClass, TRI, Register());394}395396// Restore call-saved GPRs (but not call-clobbered varargs, which at397// this point might hold return values).398SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();399if (RestoreGPRs.LowGPR) {400// If we saved any of %r2-%r5 as varargs, we should also be saving401// and restoring %r6. If we're saving %r6 or above, we should be402// restoring it too.403assert(RestoreGPRs.LowGPR != RestoreGPRs.HighGPR &&404"Should be loading %r15 and something else");405406// Build an LMG instruction.407MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));408409// Add the explicit register operands.410MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);411MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);412413// Add the address.414MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);415MIB.addImm(RestoreGPRs.GPROffset);416417// Do a second scan adding regs as being defined by instruction418for (const CalleeSavedInfo &I : CSI) {419Register Reg = I.getReg();420if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&421SystemZ::GR64BitRegClass.contains(Reg))422MIB.addReg(Reg, RegState::ImplicitDefine);423}424}425426return true;427}428429void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized(430MachineFunction &MF, RegScavenger *RS) const {431MachineFrameInfo &MFFrame = MF.getFrameInfo();432SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();433MachineRegisterInfo *MRI = &MF.getRegInfo();434bool BackChain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();435436if (!usePackedStack(MF) || BackChain)437// Create the incoming register save area.438getOrCreateFramePointerSaveIndex(MF);439440// Get the size of our stack frame to be allocated ...441uint64_t StackSize = (MFFrame.estimateStackSize(MF) +442SystemZMC::ELFCallFrameSize);443// ... and the maximum offset we may need to reach into the444// caller's frame to access the save area or stack arguments.445int64_t MaxArgOffset = 0;446for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I)447if (MFFrame.getObjectOffset(I) >= 0) {448int64_t ArgOffset = MFFrame.getObjectOffset(I) +449MFFrame.getObjectSize(I);450MaxArgOffset = std::max(MaxArgOffset, ArgOffset);451}452453uint64_t MaxReach = StackSize + MaxArgOffset;454if (!isUInt<12>(MaxReach)) {455// We may need register scavenging slots if some parts of the frame456// are outside the reach of an unsigned 12-bit displacement.457// Create 2 for the case where both addresses in an MVC are458// out of range.459RS->addScavengingFrameIndex(460MFFrame.CreateStackObject(getPointerSize(), Align(8), false));461RS->addScavengingFrameIndex(462MFFrame.CreateStackObject(getPointerSize(), Align(8), false));463}464465// If R6 is used as an argument register it is still callee saved. If it in466// this case is not clobbered (and restored) it should never be marked as467// killed.468if (MF.front().isLiveIn(SystemZ::R6D) &&469ZFI->getRestoreGPRRegs().LowGPR != SystemZ::R6D)470for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))471MO.setIsKill(false);472}473474// Emit instructions before MBBI (in MBB) to add NumBytes to Reg.475static void emitIncrement(MachineBasicBlock &MBB,476MachineBasicBlock::iterator &MBBI, const DebugLoc &DL,477Register Reg, int64_t NumBytes,478const TargetInstrInfo *TII) {479while (NumBytes) {480unsigned Opcode;481int64_t ThisVal = NumBytes;482if (isInt<16>(NumBytes))483Opcode = SystemZ::AGHI;484else {485Opcode = SystemZ::AGFI;486// Make sure we maintain 8-byte stack alignment.487int64_t MinVal = -uint64_t(1) << 31;488int64_t MaxVal = (int64_t(1) << 31) - 8;489if (ThisVal < MinVal)490ThisVal = MinVal;491else if (ThisVal > MaxVal)492ThisVal = MaxVal;493}494MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII->get(Opcode), Reg)495.addReg(Reg).addImm(ThisVal);496// The CC implicit def is dead.497MI->getOperand(3).setIsDead();498NumBytes -= ThisVal;499}500}501502// Add CFI for the new CFA offset.503static void buildCFAOffs(MachineBasicBlock &MBB,504MachineBasicBlock::iterator MBBI,505const DebugLoc &DL, int Offset,506const SystemZInstrInfo *ZII) {507unsigned CFIIndex = MBB.getParent()->addFrameInst(508MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset));509BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))510.addCFIIndex(CFIIndex);511}512513// Add CFI for the new frame location.514static void buildDefCFAReg(MachineBasicBlock &MBB,515MachineBasicBlock::iterator MBBI,516const DebugLoc &DL, unsigned Reg,517const SystemZInstrInfo *ZII) {518MachineFunction &MF = *MBB.getParent();519const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();520unsigned RegNum = MRI->getDwarfRegNum(Reg, true);521unsigned CFIIndex = MF.addFrameInst(522MCCFIInstruction::createDefCfaRegister(nullptr, RegNum));523BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))524.addCFIIndex(CFIIndex);525}526527void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF,528MachineBasicBlock &MBB) const {529assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");530const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();531const SystemZTargetLowering &TLI = *STI.getTargetLowering();532MachineFrameInfo &MFFrame = MF.getFrameInfo();533auto *ZII = static_cast<const SystemZInstrInfo *>(STI.getInstrInfo());534SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();535MachineBasicBlock::iterator MBBI = MBB.begin();536const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();537const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();538bool HasFP = hasFP(MF);539540// In GHC calling convention C stack space, including the ABI-defined541// 160-byte base area, is (de)allocated by GHC itself. This stack space may542// be used by LLVM as spill slots for the tail recursive GHC functions. Thus543// do not allocate stack space here, too.544if (MF.getFunction().getCallingConv() == CallingConv::GHC) {545if (MFFrame.getStackSize() > 2048 * sizeof(long)) {546report_fatal_error(547"Pre allocated stack space for GHC function is too small");548}549if (HasFP) {550report_fatal_error(551"In GHC calling convention a frame pointer is not supported");552}553MFFrame.setStackSize(MFFrame.getStackSize() + SystemZMC::ELFCallFrameSize);554return;555}556557// Debug location must be unknown since the first debug location is used558// to determine the end of the prologue.559DebugLoc DL;560561// The current offset of the stack pointer from the CFA.562int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;563564if (ZFI->getSpillGPRRegs().LowGPR) {565// Skip over the GPR saves.566if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)567++MBBI;568else569llvm_unreachable("Couldn't skip over GPR saves");570571// Add CFI for the GPR saves.572for (auto &Save : CSI) {573Register Reg = Save.getReg();574if (SystemZ::GR64BitRegClass.contains(Reg)) {575int FI = Save.getFrameIdx();576int64_t Offset = MFFrame.getObjectOffset(FI);577unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(578nullptr, MRI->getDwarfRegNum(Reg, true), Offset));579BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))580.addCFIIndex(CFIIndex);581}582}583}584585uint64_t StackSize = MFFrame.getStackSize();586// We need to allocate the ABI-defined 160-byte base area whenever587// we allocate stack space for our own use and whenever we call another588// function.589bool HasStackObject = false;590for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)591if (!MFFrame.isDeadObjectIndex(i)) {592HasStackObject = true;593break;594}595if (HasStackObject || MFFrame.hasCalls())596StackSize += SystemZMC::ELFCallFrameSize;597// Don't allocate the incoming reg save area.598StackSize = StackSize > SystemZMC::ELFCallFrameSize599? StackSize - SystemZMC::ELFCallFrameSize600: 0;601MFFrame.setStackSize(StackSize);602603if (StackSize) {604// Allocate StackSize bytes.605int64_t Delta = -int64_t(StackSize);606const unsigned ProbeSize = TLI.getStackProbeSize(MF);607bool FreeProbe = (ZFI->getSpillGPRRegs().GPROffset &&608(ZFI->getSpillGPRRegs().GPROffset + StackSize) < ProbeSize);609if (!FreeProbe &&610MF.getSubtarget().getTargetLowering()->hasInlineStackProbe(MF)) {611// Stack probing may involve looping, but splitting the prologue block612// is not possible at this point since it would invalidate the613// SaveBlocks / RestoreBlocks sets of PEI in the single block function614// case. Build a pseudo to be handled later by inlineStackProbe().615BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::PROBED_STACKALLOC))616.addImm(StackSize);617}618else {619bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();620// If we need backchain, save current stack pointer. R1 is free at621// this point.622if (StoreBackchain)623BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR))624.addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);625emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII);626buildCFAOffs(MBB, MBBI, DL, SPOffsetFromCFA + Delta, ZII);627if (StoreBackchain)628BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))629.addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)630.addImm(getBackchainOffset(MF)).addReg(0);631}632SPOffsetFromCFA += Delta;633}634635if (HasFP) {636// Copy the base of the frame to R11.637BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)638.addReg(SystemZ::R15D);639640// Add CFI for the new frame location.641buildDefCFAReg(MBB, MBBI, DL, SystemZ::R11D, ZII);642643// Mark the FramePtr as live at the beginning of every block except644// the entry block. (We'll have marked R11 as live on entry when645// saving the GPRs.)646for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))647MBBJ.addLiveIn(SystemZ::R11D);648}649650// Skip over the FPR/VR saves.651SmallVector<unsigned, 8> CFIIndexes;652for (auto &Save : CSI) {653Register Reg = Save.getReg();654if (SystemZ::FP64BitRegClass.contains(Reg)) {655if (MBBI != MBB.end() &&656(MBBI->getOpcode() == SystemZ::STD ||657MBBI->getOpcode() == SystemZ::STDY))658++MBBI;659else660llvm_unreachable("Couldn't skip over FPR save");661} else if (SystemZ::VR128BitRegClass.contains(Reg)) {662if (MBBI != MBB.end() &&663MBBI->getOpcode() == SystemZ::VST)664++MBBI;665else666llvm_unreachable("Couldn't skip over VR save");667} else668continue;669670// Add CFI for the this save.671unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);672Register IgnoredFrameReg;673int64_t Offset =674getFrameIndexReference(MF, Save.getFrameIdx(), IgnoredFrameReg)675.getFixed();676677unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(678nullptr, DwarfReg, SPOffsetFromCFA + Offset));679CFIIndexes.push_back(CFIIndex);680}681// Complete the CFI for the FPR/VR saves, modelling them as taking effect682// after the last save.683for (auto CFIIndex : CFIIndexes) {684BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))685.addCFIIndex(CFIIndex);686}687}688689void SystemZELFFrameLowering::emitEpilogue(MachineFunction &MF,690MachineBasicBlock &MBB) const {691MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();692auto *ZII =693static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());694SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();695MachineFrameInfo &MFFrame = MF.getFrameInfo();696697// See SystemZELFFrameLowering::emitPrologue698if (MF.getFunction().getCallingConv() == CallingConv::GHC)699return;700701// Skip the return instruction.702assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");703704uint64_t StackSize = MFFrame.getStackSize();705if (ZFI->getRestoreGPRRegs().LowGPR) {706--MBBI;707unsigned Opcode = MBBI->getOpcode();708if (Opcode != SystemZ::LMG)709llvm_unreachable("Expected to see callee-save register restore code");710711unsigned AddrOpNo = 2;712DebugLoc DL = MBBI->getDebugLoc();713uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();714unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);715716// If the offset is too large, use the largest stack-aligned offset717// and add the rest to the base register (the stack or frame pointer).718if (!NewOpcode) {719uint64_t NumBytes = Offset - 0x7fff8;720emitIncrement(MBB, MBBI, DL, MBBI->getOperand(AddrOpNo).getReg(),721NumBytes, ZII);722Offset -= NumBytes;723NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);724assert(NewOpcode && "No restore instruction available");725}726727MBBI->setDesc(ZII->get(NewOpcode));728MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);729} else if (StackSize) {730DebugLoc DL = MBBI->getDebugLoc();731emitIncrement(MBB, MBBI, DL, SystemZ::R15D, StackSize, ZII);732}733}734735void SystemZELFFrameLowering::inlineStackProbe(736MachineFunction &MF, MachineBasicBlock &PrologMBB) const {737auto *ZII =738static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());739const SystemZSubtarget &STI = MF.getSubtarget<SystemZSubtarget>();740const SystemZTargetLowering &TLI = *STI.getTargetLowering();741742MachineInstr *StackAllocMI = nullptr;743for (MachineInstr &MI : PrologMBB)744if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {745StackAllocMI = &MI;746break;747}748if (StackAllocMI == nullptr)749return;750uint64_t StackSize = StackAllocMI->getOperand(0).getImm();751const unsigned ProbeSize = TLI.getStackProbeSize(MF);752uint64_t NumFullBlocks = StackSize / ProbeSize;753uint64_t Residual = StackSize % ProbeSize;754int64_t SPOffsetFromCFA = -SystemZMC::ELFCFAOffsetFromInitialSP;755MachineBasicBlock *MBB = &PrologMBB;756MachineBasicBlock::iterator MBBI = StackAllocMI;757const DebugLoc DL = StackAllocMI->getDebugLoc();758759// Allocate a block of Size bytes on the stack and probe it.760auto allocateAndProbe = [&](MachineBasicBlock &InsMBB,761MachineBasicBlock::iterator InsPt, unsigned Size,762bool EmitCFI) -> void {763emitIncrement(InsMBB, InsPt, DL, SystemZ::R15D, -int64_t(Size), ZII);764if (EmitCFI) {765SPOffsetFromCFA -= Size;766buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);767}768// Probe by means of a volatile compare.769MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(),770MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad, 8, Align(1));771BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))772.addReg(SystemZ::R0D, RegState::Undef)773.addReg(SystemZ::R15D).addImm(Size - 8).addReg(0)774.addMemOperand(MMO);775};776777bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();778if (StoreBackchain)779BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))780.addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);781782MachineBasicBlock *DoneMBB = nullptr;783MachineBasicBlock *LoopMBB = nullptr;784if (NumFullBlocks < 3) {785// Emit unrolled probe statements.786for (unsigned int i = 0; i < NumFullBlocks; i++)787allocateAndProbe(*MBB, MBBI, ProbeSize, true/*EmitCFI*/);788} else {789// Emit a loop probing the pages.790uint64_t LoopAlloc = ProbeSize * NumFullBlocks;791SPOffsetFromCFA -= LoopAlloc;792793// Use R0D to hold the exit value.794BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)795.addReg(SystemZ::R15D);796buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R0D, ZII);797emitIncrement(*MBB, MBBI, DL, SystemZ::R0D, -int64_t(LoopAlloc), ZII);798buildCFAOffs(*MBB, MBBI, DL, -int64_t(SystemZMC::ELFCallFrameSize + LoopAlloc),799ZII);800801DoneMBB = SystemZ::splitBlockBefore(MBBI, MBB);802LoopMBB = SystemZ::emitBlockAfter(MBB);803MBB->addSuccessor(LoopMBB);804LoopMBB->addSuccessor(LoopMBB);805LoopMBB->addSuccessor(DoneMBB);806807MBB = LoopMBB;808allocateAndProbe(*MBB, MBB->end(), ProbeSize, false/*EmitCFI*/);809BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::CLGR))810.addReg(SystemZ::R15D).addReg(SystemZ::R0D);811BuildMI(*MBB, MBB->end(), DL, ZII->get(SystemZ::BRC))812.addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_GT).addMBB(MBB);813814MBB = DoneMBB;815MBBI = DoneMBB->begin();816buildDefCFAReg(*MBB, MBBI, DL, SystemZ::R15D, ZII);817}818819if (Residual)820allocateAndProbe(*MBB, MBBI, Residual, true/*EmitCFI*/);821822if (StoreBackchain)823BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::STG))824.addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)825.addImm(getBackchainOffset(MF)).addReg(0);826827StackAllocMI->eraseFromParent();828if (DoneMBB != nullptr) {829// Compute the live-in lists for the new blocks.830fullyRecomputeLiveIns({DoneMBB, LoopMBB});831}832}833834bool SystemZELFFrameLowering::hasFP(const MachineFunction &MF) const {835return (MF.getTarget().Options.DisableFramePointerElim(MF) ||836MF.getFrameInfo().hasVarSizedObjects());837}838839StackOffset SystemZELFFrameLowering::getFrameIndexReference(840const MachineFunction &MF, int FI, Register &FrameReg) const {841// Our incoming SP is actually SystemZMC::ELFCallFrameSize below the CFA, so842// add that difference here.843StackOffset Offset =844TargetFrameLowering::getFrameIndexReference(MF, FI, FrameReg);845return Offset + StackOffset::getFixed(SystemZMC::ELFCallFrameSize);846}847848unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF,849Register Reg) const {850bool IsVarArg = MF.getFunction().isVarArg();851const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();852bool BackChain = Subtarget.hasBackChain();853bool SoftFloat = Subtarget.hasSoftFloat();854unsigned Offset = RegSpillOffsets[Reg];855if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {856if (SystemZ::GR64BitRegClass.contains(Reg))857// Put all GPRs at the top of the Register save area with packed858// stack. Make room for the backchain if needed.859Offset += BackChain ? 24 : 32;860else861Offset = 0;862}863return Offset;864}865866int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex(867MachineFunction &MF) const {868SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();869int FI = ZFI->getFramePointerSaveIndex();870if (!FI) {871MachineFrameInfo &MFFrame = MF.getFrameInfo();872int Offset = getBackchainOffset(MF) - SystemZMC::ELFCallFrameSize;873FI = MFFrame.CreateFixedObject(getPointerSize(), Offset, false);874ZFI->setFramePointerSaveIndex(FI);875}876return FI;877}878879bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {880bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");881const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();882bool BackChain = Subtarget.hasBackChain();883bool SoftFloat = Subtarget.hasSoftFloat();884if (HasPackedStackAttr && BackChain && !SoftFloat)885report_fatal_error("packed-stack + backchain + hard-float is unsupported.");886bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;887return HasPackedStackAttr && CallConv;888}889890SystemZXPLINKFrameLowering::SystemZXPLINKFrameLowering(unsigned PointerSize)891: SystemZFrameLowering(TargetFrameLowering::StackGrowsDown, Align(32), 0,892Align(32), /* StackRealignable */ false,893PointerSize),894RegSpillOffsets(-1) {895896// Create a mapping from register number to save slot offset.897// These offsets are relative to the start of the local are area.898RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);899for (const auto &Entry : XPLINKSpillOffsetTable)900RegSpillOffsets[Entry.Reg] = Entry.Offset;901}902903int SystemZXPLINKFrameLowering::getOrCreateFramePointerSaveIndex(904MachineFunction &MF) const {905SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();906int FI = ZFI->getFramePointerSaveIndex();907if (!FI) {908MachineFrameInfo &MFFrame = MF.getFrameInfo();909FI = MFFrame.CreateFixedObject(getPointerSize(), 0, false);910MFFrame.setStackID(FI, TargetStackID::NoAlloc);911ZFI->setFramePointerSaveIndex(FI);912}913return FI;914}915916// Checks if the function is a potential candidate for being a XPLeaf routine.917static bool isXPLeafCandidate(const MachineFunction &MF) {918const MachineFrameInfo &MFFrame = MF.getFrameInfo();919const MachineRegisterInfo &MRI = MF.getRegInfo();920const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();921auto *Regs =922static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());923924// If function calls other functions including alloca, then it is not a XPLeaf925// routine.926if (MFFrame.hasCalls())927return false;928929// If the function has var Sized Objects, then it is not a XPLeaf routine.930if (MFFrame.hasVarSizedObjects())931return false;932933// If the function adjusts the stack, then it is not a XPLeaf routine.934if (MFFrame.adjustsStack())935return false;936937// If function modifies the stack pointer register, then it is not a XPLeaf938// routine.939if (MRI.isPhysRegModified(Regs->getStackPointerRegister()))940return false;941942// If function modifies the ADA register, then it is not a XPLeaf routine.943if (MRI.isPhysRegModified(Regs->getAddressOfCalleeRegister()))944return false;945946// If function modifies the return address register, then it is not a XPLeaf947// routine.948if (MRI.isPhysRegModified(Regs->getReturnFunctionAddressRegister()))949return false;950951// If the backchain pointer should be stored, then it is not a XPLeaf routine.952if (MF.getSubtarget<SystemZSubtarget>().hasBackChain())953return false;954955// If function acquires its own stack frame, then it is not a XPLeaf routine.956// At the time this function is called, only slots for local variables are957// allocated, so this is a very rough estimate.958if (MFFrame.estimateStackSize(MF) > 0)959return false;960961return true;962}963964bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(965MachineFunction &MF, const TargetRegisterInfo *TRI,966std::vector<CalleeSavedInfo> &CSI) const {967MachineFrameInfo &MFFrame = MF.getFrameInfo();968SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();969const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();970auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();971auto &GRRegClass = SystemZ::GR64BitRegClass;972973// At this point, the result of isXPLeafCandidate() is not accurate because974// the size of the save area has not yet been determined. If975// isXPLeafCandidate() indicates a potential leaf function, and there are no976// callee-save registers, then it is indeed a leaf function, and we can early977// exit.978// TODO: It is possible for leaf functions to use callee-saved registers.979// It can use the 0-2k range between R4 and the caller's stack frame without980// acquiring its own stack frame.981bool IsLeaf = CSI.empty() && isXPLeafCandidate(MF);982if (IsLeaf)983return true;984985// For non-leaf functions:986// - the address of callee (entry point) register R6 must be saved987CSI.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister()));988CSI.back().setRestored(false);989990// The return address register R7 must be saved and restored.991CSI.push_back(CalleeSavedInfo(Regs.getReturnFunctionAddressRegister()));992993// If the function needs a frame pointer, or if the backchain pointer should994// be stored, then save the stack pointer register R4.995if (hasFP(MF) || Subtarget.hasBackChain())996CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));997998// If this function has an associated personality function then the999// environment register R5 must be saved in the DSA.1000if (!MF.getLandingPads().empty())1001CSI.push_back(CalleeSavedInfo(Regs.getADARegister()));10021003// Scan the call-saved GPRs and find the bounds of the register spill area.1004Register LowRestoreGPR = 0;1005int LowRestoreOffset = INT32_MAX;1006Register LowSpillGPR = 0;1007int LowSpillOffset = INT32_MAX;1008Register HighGPR = 0;1009int HighOffset = -1;10101011// Query index of the saved frame pointer.1012int FPSI = MFI->getFramePointerSaveIndex();10131014for (auto &CS : CSI) {1015Register Reg = CS.getReg();1016int Offset = RegSpillOffsets[Reg];1017if (Offset >= 0) {1018if (GRRegClass.contains(Reg)) {1019if (LowSpillOffset > Offset) {1020LowSpillOffset = Offset;1021LowSpillGPR = Reg;1022}1023if (CS.isRestored() && LowRestoreOffset > Offset) {1024LowRestoreOffset = Offset;1025LowRestoreGPR = Reg;1026}10271028if (Offset > HighOffset) {1029HighOffset = Offset;1030HighGPR = Reg;1031}1032// Non-volatile GPRs are saved in the dedicated register save area at1033// the bottom of the stack and are not truly part of the "normal" stack1034// frame. Mark the frame index as NoAlloc to indicate it as such.1035unsigned RegSize = getPointerSize();1036int FrameIdx =1037(FPSI && Offset == 0)1038? FPSI1039: MFFrame.CreateFixedSpillStackObject(RegSize, Offset);1040CS.setFrameIdx(FrameIdx);1041MFFrame.setStackID(FrameIdx, TargetStackID::NoAlloc);1042}1043} else {1044Register Reg = CS.getReg();1045const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);1046Align Alignment = TRI->getSpillAlign(*RC);1047unsigned Size = TRI->getSpillSize(*RC);1048Alignment = std::min(Alignment, getStackAlign());1049int FrameIdx = MFFrame.CreateStackObject(Size, Alignment, true);1050CS.setFrameIdx(FrameIdx);1051}1052}10531054// Save the range of call-saved registers, for use by the1055// prologue/epilogue inserters.1056if (LowRestoreGPR)1057MFI->setRestoreGPRRegs(LowRestoreGPR, HighGPR, LowRestoreOffset);10581059// Save the range of call-saved registers, for use by the epilogue inserter.1060assert(LowSpillGPR && "Expected registers to spill");1061MFI->setSpillGPRRegs(LowSpillGPR, HighGPR, LowSpillOffset);10621063return true;1064}10651066void SystemZXPLINKFrameLowering::determineCalleeSaves(MachineFunction &MF,1067BitVector &SavedRegs,1068RegScavenger *RS) const {1069TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);10701071bool HasFP = hasFP(MF);1072const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1073auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();10741075// If the function requires a frame pointer, record that the hard1076// frame pointer will be clobbered.1077if (HasFP)1078SavedRegs.set(Regs.getFramePointerRegister());1079}10801081bool SystemZXPLINKFrameLowering::spillCalleeSavedRegisters(1082MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,1083ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {1084if (CSI.empty())1085return true;10861087MachineFunction &MF = *MBB.getParent();1088SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1089const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1090const TargetInstrInfo *TII = Subtarget.getInstrInfo();1091auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1092SystemZ::GPRRegs SpillGPRs = ZFI->getSpillGPRRegs();1093DebugLoc DL;10941095// Save GPRs1096if (SpillGPRs.LowGPR) {1097assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&1098"Should be saving multiple registers");10991100// Build an STM/STMG instruction.1101MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STMG));11021103// Add the explicit register operands.1104addSavedGPR(MBB, MIB, SpillGPRs.LowGPR, false);1105addSavedGPR(MBB, MIB, SpillGPRs.HighGPR, false);11061107// Add the address r41108MIB.addReg(Regs.getStackPointerRegister());11091110// Add the partial offset1111// We cannot add the actual offset as, at the stack is not finalized1112MIB.addImm(SpillGPRs.GPROffset);11131114// Make sure all call-saved GPRs are included as operands and are1115// marked as live on entry.1116auto &GRRegClass = SystemZ::GR64BitRegClass;1117for (const CalleeSavedInfo &I : CSI) {1118Register Reg = I.getReg();1119if (GRRegClass.contains(Reg))1120addSavedGPR(MBB, MIB, Reg, true);1121}1122}11231124// Spill FPRs to the stack in the normal TargetInstrInfo way1125for (const CalleeSavedInfo &I : CSI) {1126Register Reg = I.getReg();1127if (SystemZ::FP64BitRegClass.contains(Reg)) {1128MBB.addLiveIn(Reg);1129TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),1130&SystemZ::FP64BitRegClass, TRI, Register());1131}1132if (SystemZ::VR128BitRegClass.contains(Reg)) {1133MBB.addLiveIn(Reg);1134TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),1135&SystemZ::VR128BitRegClass, TRI, Register());1136}1137}11381139return true;1140}11411142bool SystemZXPLINKFrameLowering::restoreCalleeSavedRegisters(1143MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,1144MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {11451146if (CSI.empty())1147return false;11481149MachineFunction &MF = *MBB.getParent();1150SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1151const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1152const TargetInstrInfo *TII = Subtarget.getInstrInfo();1153auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();11541155DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();11561157// Restore FPRs in the normal TargetInstrInfo way.1158for (const CalleeSavedInfo &I : CSI) {1159Register Reg = I.getReg();1160if (SystemZ::FP64BitRegClass.contains(Reg))1161TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),1162&SystemZ::FP64BitRegClass, TRI, Register());1163if (SystemZ::VR128BitRegClass.contains(Reg))1164TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),1165&SystemZ::VR128BitRegClass, TRI, Register());1166}11671168// Restore call-saved GPRs (but not call-clobbered varargs, which at1169// this point might hold return values).1170SystemZ::GPRRegs RestoreGPRs = ZFI->getRestoreGPRRegs();1171if (RestoreGPRs.LowGPR) {1172assert(isInt<20>(Regs.getStackPointerBias() + RestoreGPRs.GPROffset));1173if (RestoreGPRs.LowGPR == RestoreGPRs.HighGPR)1174// Build an LG/L instruction.1175BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LG), RestoreGPRs.LowGPR)1176.addReg(Regs.getStackPointerRegister())1177.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset)1178.addReg(0);1179else {1180// Build an LMG/LM instruction.1181MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG));11821183// Add the explicit register operands.1184MIB.addReg(RestoreGPRs.LowGPR, RegState::Define);1185MIB.addReg(RestoreGPRs.HighGPR, RegState::Define);11861187// Add the address.1188MIB.addReg(Regs.getStackPointerRegister());1189MIB.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset);11901191// Do a second scan adding regs as being defined by instruction1192for (const CalleeSavedInfo &I : CSI) {1193Register Reg = I.getReg();1194if (Reg > RestoreGPRs.LowGPR && Reg < RestoreGPRs.HighGPR)1195MIB.addReg(Reg, RegState::ImplicitDefine);1196}1197}1198}11991200return true;1201}12021203void SystemZXPLINKFrameLowering::emitPrologue(MachineFunction &MF,1204MachineBasicBlock &MBB) const {1205assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");1206const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1207SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1208MachineBasicBlock::iterator MBBI = MBB.begin();1209auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());1210auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();1211MachineFrameInfo &MFFrame = MF.getFrameInfo();1212MachineInstr *StoreInstr = nullptr;12131214determineFrameLayout(MF);12151216bool HasFP = hasFP(MF);1217// Debug location must be unknown since the first debug location is used1218// to determine the end of the prologue.1219DebugLoc DL;1220uint64_t Offset = 0;12211222const uint64_t StackSize = MFFrame.getStackSize();12231224if (ZFI->getSpillGPRRegs().LowGPR) {1225// Skip over the GPR saves.1226if ((MBBI != MBB.end()) && ((MBBI->getOpcode() == SystemZ::STMG))) {1227const int Operand = 3;1228// Now we can set the offset for the operation, since now the Stack1229// has been finalized.1230Offset = Regs.getStackPointerBias() + MBBI->getOperand(Operand).getImm();1231// Maximum displacement for STMG instruction.1232if (isInt<20>(Offset - StackSize))1233Offset -= StackSize;1234else1235StoreInstr = &*MBBI;1236MBBI->getOperand(Operand).setImm(Offset);1237++MBBI;1238} else1239llvm_unreachable("Couldn't skip over GPR saves");1240}12411242if (StackSize) {1243MachineBasicBlock::iterator InsertPt = StoreInstr ? StoreInstr : MBBI;1244// Allocate StackSize bytes.1245int64_t Delta = -int64_t(StackSize);12461247// In case the STM(G) instruction also stores SP (R4), but the displacement1248// is too large, the SP register is manipulated first before storing,1249// resulting in the wrong value stored and retrieved later. In this case, we1250// need to temporarily save the value of SP, and store it later to memory.1251if (StoreInstr && HasFP) {1252// Insert LR r0,r4 before STMG instruction.1253BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::LGR))1254.addReg(SystemZ::R0D, RegState::Define)1255.addReg(SystemZ::R4D);1256// Insert ST r0,xxx(,r4) after STMG instruction.1257BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))1258.addReg(SystemZ::R0D, RegState::Kill)1259.addReg(SystemZ::R4D)1260.addImm(Offset)1261.addReg(0);1262}12631264emitIncrement(MBB, InsertPt, DL, Regs.getStackPointerRegister(), Delta,1265ZII);12661267// If the requested stack size is larger than the guard page, then we need1268// to check if we need to call the stack extender. This requires adding a1269// conditional branch, but splitting the prologue block is not possible at1270// this point since it would invalidate the SaveBlocks / RestoreBlocks sets1271// of PEI in the single block function case. Build a pseudo to be handled1272// later by inlineStackProbe().1273const uint64_t GuardPageSize = 1024 * 1024;1274if (StackSize > GuardPageSize) {1275assert(StoreInstr && "Wrong insertion point");1276BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::XPLINK_STACKALLOC));1277}1278}12791280if (HasFP) {1281// Copy the base of the frame to Frame Pointer Register.1282BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR),1283Regs.getFramePointerRegister())1284.addReg(Regs.getStackPointerRegister());12851286// Mark the FramePtr as live at the beginning of every block except1287// the entry block. (We'll have marked R8 as live on entry when1288// saving the GPRs.)1289for (MachineBasicBlock &B : llvm::drop_begin(MF))1290B.addLiveIn(Regs.getFramePointerRegister());1291}12921293// Save GPRs used for varargs, if any.1294const TargetInstrInfo *TII = Subtarget.getInstrInfo();1295bool IsVarArg = MF.getFunction().isVarArg();12961297if (IsVarArg) {1298// FixedRegs is the number of used registers, accounting for shadow1299// registers.1300unsigned FixedRegs = ZFI->getVarArgsFirstGPR() + ZFI->getVarArgsFirstFPR();1301auto &GPRs = SystemZ::XPLINK64ArgGPRs;1302for (unsigned I = FixedRegs; I < SystemZ::XPLINK64NumArgGPRs; I++) {1303uint64_t StartOffset = MFFrame.getOffsetAdjustment() +1304MFFrame.getStackSize() + Regs.getCallFrameSize() +1305getOffsetOfLocalArea() + I * getPointerSize();1306unsigned Reg = GPRs[I];1307BuildMI(MBB, MBBI, DL, TII->get(SystemZ::STG))1308.addReg(Reg)1309.addReg(Regs.getStackPointerRegister())1310.addImm(StartOffset)1311.addReg(0);1312if (!MBB.isLiveIn(Reg))1313MBB.addLiveIn(Reg);1314}1315}1316}13171318void SystemZXPLINKFrameLowering::emitEpilogue(MachineFunction &MF,1319MachineBasicBlock &MBB) const {1320const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1321MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();1322SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();1323MachineFrameInfo &MFFrame = MF.getFrameInfo();1324auto *ZII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());1325auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();13261327// Skip the return instruction.1328assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");13291330uint64_t StackSize = MFFrame.getStackSize();1331if (StackSize) {1332unsigned SPReg = Regs.getStackPointerRegister();1333if (ZFI->getRestoreGPRRegs().LowGPR != SPReg) {1334DebugLoc DL = MBBI->getDebugLoc();1335emitIncrement(MBB, MBBI, DL, SPReg, StackSize, ZII);1336}1337}1338}13391340// Emit a compare of the stack pointer against the stack floor, and a call to1341// the LE stack extender if needed.1342void SystemZXPLINKFrameLowering::inlineStackProbe(1343MachineFunction &MF, MachineBasicBlock &PrologMBB) const {1344auto *ZII =1345static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());13461347MachineInstr *StackAllocMI = nullptr;1348for (MachineInstr &MI : PrologMBB)1349if (MI.getOpcode() == SystemZ::XPLINK_STACKALLOC) {1350StackAllocMI = &MI;1351break;1352}1353if (StackAllocMI == nullptr)1354return;13551356bool NeedSaveSP = hasFP(MF);1357bool NeedSaveArg = PrologMBB.isLiveIn(SystemZ::R3D);1358const int64_t SaveSlotR3 = 2192;13591360MachineBasicBlock &MBB = PrologMBB;1361const DebugLoc DL = StackAllocMI->getDebugLoc();13621363// The 2nd half of block MBB after split.1364MachineBasicBlock *NextMBB;13651366// Add new basic block for the call to the stack overflow function.1367MachineBasicBlock *StackExtMBB =1368MF.CreateMachineBasicBlock(MBB.getBasicBlock());1369MF.push_back(StackExtMBB);13701371// LG r3,72(,r3)1372BuildMI(StackExtMBB, DL, ZII->get(SystemZ::LG), SystemZ::R3D)1373.addReg(SystemZ::R3D)1374.addImm(72)1375.addReg(0);1376// BASR r3,r31377BuildMI(StackExtMBB, DL, ZII->get(SystemZ::CallBASR_STACKEXT))1378.addReg(SystemZ::R3D);1379if (NeedSaveArg) {1380if (!NeedSaveSP) {1381// LGR r0,r31382BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1383.addReg(SystemZ::R0D, RegState::Define)1384.addReg(SystemZ::R3D);1385} else {1386// In this case, the incoming value of r4 is saved in r0 so the1387// latter register is unavailable. Store r3 in its corresponding1388// slot in the parameter list instead. Do this at the start of1389// the prolog before r4 is manipulated by anything else.1390// STG r3, 2192(r4)1391BuildMI(MBB, MBB.begin(), DL, ZII->get(SystemZ::STG))1392.addReg(SystemZ::R3D)1393.addReg(SystemZ::R4D)1394.addImm(SaveSlotR3)1395.addReg(0);1396}1397}1398// LLGT r3,12081399BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LLGT), SystemZ::R3D)1400.addReg(0)1401.addImm(1208)1402.addReg(0);1403// CG r4,64(,r3)1404BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::CG))1405.addReg(SystemZ::R4D)1406.addReg(SystemZ::R3D)1407.addImm(64)1408.addReg(0);1409// JLL b'0100',F'37'1410BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::BRC))1411.addImm(SystemZ::CCMASK_ICMP)1412.addImm(SystemZ::CCMASK_CMP_LT)1413.addMBB(StackExtMBB);14141415NextMBB = SystemZ::splitBlockBefore(StackAllocMI, &MBB);1416MBB.addSuccessor(NextMBB);1417MBB.addSuccessor(StackExtMBB);1418if (NeedSaveArg) {1419if (!NeedSaveSP) {1420// LGR r3, r01421BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1422.addReg(SystemZ::R3D, RegState::Define)1423.addReg(SystemZ::R0D, RegState::Kill);1424} else {1425// In this case, the incoming value of r4 is saved in r0 so the1426// latter register is unavailable. We stored r3 in its corresponding1427// slot in the parameter list instead and we now restore it from there.1428// LGR r3, r01429BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))1430.addReg(SystemZ::R3D, RegState::Define)1431.addReg(SystemZ::R0D);1432// LG r3, 2192(r3)1433BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LG))1434.addReg(SystemZ::R3D, RegState::Define)1435.addReg(SystemZ::R3D)1436.addImm(SaveSlotR3)1437.addReg(0);1438}1439}14401441// Add jump back from stack extension BB.1442BuildMI(StackExtMBB, DL, ZII->get(SystemZ::J)).addMBB(NextMBB);1443StackExtMBB->addSuccessor(NextMBB);14441445StackAllocMI->eraseFromParent();14461447// Compute the live-in lists for the new blocks.1448fullyRecomputeLiveIns({StackExtMBB, NextMBB});1449}14501451bool SystemZXPLINKFrameLowering::hasFP(const MachineFunction &MF) const {1452return (MF.getFrameInfo().hasVarSizedObjects());1453}14541455void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized(1456MachineFunction &MF, RegScavenger *RS) const {1457MachineFrameInfo &MFFrame = MF.getFrameInfo();1458const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1459auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();14601461// Setup stack frame offset1462MFFrame.setOffsetAdjustment(Regs.getStackPointerBias());14631464// Nothing to do for leaf functions.1465uint64_t StackSize = MFFrame.estimateStackSize(MF);1466if (StackSize == 0 && MFFrame.getCalleeSavedInfo().empty())1467return;14681469// Although the XPLINK specifications for AMODE64 state that minimum size1470// of the param area is minimum 32 bytes and no rounding is otherwise1471// specified, we round this area in 64 bytes increments to be compatible1472// with existing compilers.1473MFFrame.setMaxCallFrameSize(1474std::max(64U, (unsigned)alignTo(MFFrame.getMaxCallFrameSize(), 64)));14751476// Add frame values with positive object offsets. Since the displacement from1477// the SP/FP is calculated by ObjectOffset + StackSize + Bias, object offsets1478// with positive values are in the caller's stack frame. We need to include1479// that since it is accessed by displacement to SP/FP.1480int64_t LargestArgOffset = 0;1481for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) {1482if (MFFrame.getObjectOffset(I) >= 0) {1483int64_t ObjOffset = MFFrame.getObjectOffset(I) + MFFrame.getObjectSize(I);1484LargestArgOffset = std::max(ObjOffset, LargestArgOffset);1485}1486}14871488uint64_t MaxReach = (StackSize + Regs.getCallFrameSize() +1489Regs.getStackPointerBias() + LargestArgOffset);14901491if (!isUInt<12>(MaxReach)) {1492// We may need register scavenging slots if some parts of the frame1493// are outside the reach of an unsigned 12-bit displacement.1494RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));1495RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));1496}1497}14981499// Determines the size of the frame, and creates the deferred spill objects.1500void SystemZXPLINKFrameLowering::determineFrameLayout(1501MachineFunction &MF) const {1502MachineFrameInfo &MFFrame = MF.getFrameInfo();1503const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();1504auto *Regs =1505static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());15061507uint64_t StackSize = MFFrame.getStackSize();1508if (StackSize == 0)1509return;15101511// Add the size of the register save area and the reserved area to the size.1512StackSize += Regs->getCallFrameSize();1513MFFrame.setStackSize(StackSize);15141515// We now know the stack size. Update the stack objects for the register save1516// area now. This has no impact on the stack frame layout, as this is already1517// computed. However, it makes sure that all callee saved registers have a1518// valid offset assigned.1519for (int FrameIdx = MFFrame.getObjectIndexBegin(); FrameIdx != 0;1520++FrameIdx) {1521if (MFFrame.getStackID(FrameIdx) == TargetStackID::NoAlloc) {1522int64_t SPOffset = MFFrame.getObjectOffset(FrameIdx);1523SPOffset -= StackSize;1524MFFrame.setObjectOffset(FrameIdx, SPOffset);1525}1526}1527}152815291530