xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===- SIMachineFunctionInfo.cpp - SI Machine Function Info ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h"
105ffd83dbSDimitry Andric #include "AMDGPUTargetMachine.h"
11*fe6060f1SDimitry Andric #include "AMDGPUSubtarget.h"
12*fe6060f1SDimitry Andric #include "SIRegisterInfo.h"
13*fe6060f1SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
14*fe6060f1SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
15*fe6060f1SDimitry Andric #include "llvm/ADT/Optional.h"
16*fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
17*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
18*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
20*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21*fe6060f1SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
22*fe6060f1SDimitry Andric #include "llvm/IR/CallingConv.h"
23*fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
24*fe6060f1SDimitry Andric #include "llvm/IR/Function.h"
25*fe6060f1SDimitry Andric #include <cassert>
26*fe6060f1SDimitry Andric #include <vector>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define MAX_LANES 64
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
330b57cec5SDimitry Andric   : AMDGPUMachineFunction(MF),
340b57cec5SDimitry Andric     PrivateSegmentBuffer(false),
350b57cec5SDimitry Andric     DispatchPtr(false),
360b57cec5SDimitry Andric     QueuePtr(false),
370b57cec5SDimitry Andric     KernargSegmentPtr(false),
380b57cec5SDimitry Andric     DispatchID(false),
390b57cec5SDimitry Andric     FlatScratchInit(false),
400b57cec5SDimitry Andric     WorkGroupIDX(false),
410b57cec5SDimitry Andric     WorkGroupIDY(false),
420b57cec5SDimitry Andric     WorkGroupIDZ(false),
430b57cec5SDimitry Andric     WorkGroupInfo(false),
440b57cec5SDimitry Andric     PrivateSegmentWaveByteOffset(false),
450b57cec5SDimitry Andric     WorkItemIDX(false),
460b57cec5SDimitry Andric     WorkItemIDY(false),
470b57cec5SDimitry Andric     WorkItemIDZ(false),
480b57cec5SDimitry Andric     ImplicitBufferPtr(false),
490b57cec5SDimitry Andric     ImplicitArgPtr(false),
500b57cec5SDimitry Andric     GITPtrHigh(0xffffffff),
510b57cec5SDimitry Andric     HighBitsOf32BitAddress(0),
520b57cec5SDimitry Andric     GDSSize(0) {
530b57cec5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
540b57cec5SDimitry Andric   const Function &F = MF.getFunction();
550b57cec5SDimitry Andric   FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
560b57cec5SDimitry Andric   WavesPerEU = ST.getWavesPerEU(F);
570b57cec5SDimitry Andric 
585ffd83dbSDimitry Andric   Occupancy = ST.computeOccupancy(F, getLDSSize());
590b57cec5SDimitry Andric   CallingConv::ID CC = F.getCallingConv();
600b57cec5SDimitry Andric 
615ffd83dbSDimitry Andric   // FIXME: Should have analysis or something rather than attribute to detect
625ffd83dbSDimitry Andric   // calls.
635ffd83dbSDimitry Andric   const bool HasCalls = F.hasFnAttribute("amdgpu-calls");
645ffd83dbSDimitry Andric 
655ffd83dbSDimitry Andric   // Enable all kernel inputs if we have the fixed ABI. Don't bother if we don't
665ffd83dbSDimitry Andric   // have any calls.
675ffd83dbSDimitry Andric   const bool UseFixedABI = AMDGPUTargetMachine::EnableFixedFunctionABI &&
68*fe6060f1SDimitry Andric                            CC != CallingConv::AMDGPU_Gfx &&
695ffd83dbSDimitry Andric                            (!isEntryFunction() || HasCalls);
705ffd83dbSDimitry Andric 
710b57cec5SDimitry Andric   if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL) {
720b57cec5SDimitry Andric     if (!F.arg_empty())
730b57cec5SDimitry Andric       KernargSegmentPtr = true;
740b57cec5SDimitry Andric     WorkGroupIDX = true;
750b57cec5SDimitry Andric     WorkItemIDX = true;
760b57cec5SDimitry Andric   } else if (CC == CallingConv::AMDGPU_PS) {
770b57cec5SDimitry Andric     PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   if (!isEntryFunction()) {
81*fe6060f1SDimitry Andric     if (UseFixedABI)
82*fe6060f1SDimitry Andric       ArgInfo = AMDGPUArgumentUsageInfo::FixedABIFunctionInfo;
83*fe6060f1SDimitry Andric 
840b57cec5SDimitry Andric     // TODO: Pick a high register, and shift down, similar to a kernel.
855ffd83dbSDimitry Andric     FrameOffsetReg = AMDGPU::SGPR33;
860b57cec5SDimitry Andric     StackPtrOffsetReg = AMDGPU::SGPR32;
870b57cec5SDimitry Andric 
88e8d8bef9SDimitry Andric     if (!ST.enableFlatScratch()) {
89e8d8bef9SDimitry Andric       // Non-entry functions have no special inputs for now, other registers
90e8d8bef9SDimitry Andric       // required for scratch access.
91e8d8bef9SDimitry Andric       ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
92e8d8bef9SDimitry Andric 
930b57cec5SDimitry Andric       ArgInfo.PrivateSegmentBuffer =
940b57cec5SDimitry Andric         ArgDescriptor::createRegister(ScratchRSrcReg);
95e8d8bef9SDimitry Andric     }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-implicitarg-ptr"))
980b57cec5SDimitry Andric       ImplicitArgPtr = true;
990b57cec5SDimitry Andric   } else {
1000b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-implicitarg-ptr")) {
1010b57cec5SDimitry Andric       KernargSegmentPtr = true;
1020b57cec5SDimitry Andric       MaxKernArgAlign = std::max(ST.getAlignmentForImplicitArgPtr(),
1030b57cec5SDimitry Andric                                  MaxKernArgAlign);
1040b57cec5SDimitry Andric     }
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1075ffd83dbSDimitry Andric   if (UseFixedABI) {
1085ffd83dbSDimitry Andric     WorkGroupIDX = true;
1095ffd83dbSDimitry Andric     WorkGroupIDY = true;
1105ffd83dbSDimitry Andric     WorkGroupIDZ = true;
1115ffd83dbSDimitry Andric     WorkItemIDX = true;
1125ffd83dbSDimitry Andric     WorkItemIDY = true;
1135ffd83dbSDimitry Andric     WorkItemIDZ = true;
1145ffd83dbSDimitry Andric     ImplicitArgPtr = true;
1155ffd83dbSDimitry Andric   } else {
1160b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-group-id-x"))
1170b57cec5SDimitry Andric       WorkGroupIDX = true;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-group-id-y"))
1200b57cec5SDimitry Andric       WorkGroupIDY = true;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-group-id-z"))
1230b57cec5SDimitry Andric       WorkGroupIDZ = true;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-item-id-x"))
1260b57cec5SDimitry Andric       WorkItemIDX = true;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-item-id-y"))
1290b57cec5SDimitry Andric       WorkItemIDY = true;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric     if (F.hasFnAttribute("amdgpu-work-item-id-z"))
1320b57cec5SDimitry Andric       WorkItemIDZ = true;
1335ffd83dbSDimitry Andric   }
1340b57cec5SDimitry Andric 
1355ffd83dbSDimitry Andric   bool HasStackObjects = F.hasFnAttribute("amdgpu-stack-objects");
1360b57cec5SDimitry Andric   if (isEntryFunction()) {
1370b57cec5SDimitry Andric     // X, XY, and XYZ are the only supported combinations, so make sure Y is
1380b57cec5SDimitry Andric     // enabled if Z is.
1390b57cec5SDimitry Andric     if (WorkItemIDZ)
1400b57cec5SDimitry Andric       WorkItemIDY = true;
1410b57cec5SDimitry Andric 
142*fe6060f1SDimitry Andric     if (!ST.flatScratchIsArchitected()) {
1430b57cec5SDimitry Andric       PrivateSegmentWaveByteOffset = true;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric       // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
1460b57cec5SDimitry Andric       if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
1470b57cec5SDimitry Andric           (CC == CallingConv::AMDGPU_HS || CC == CallingConv::AMDGPU_GS))
1480b57cec5SDimitry Andric         ArgInfo.PrivateSegmentWaveByteOffset =
1490b57cec5SDimitry Andric             ArgDescriptor::createRegister(AMDGPU::SGPR5);
1500b57cec5SDimitry Andric     }
151*fe6060f1SDimitry Andric   }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   bool isAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
1540b57cec5SDimitry Andric   if (isAmdHsaOrMesa) {
155e8d8bef9SDimitry Andric     if (!ST.enableFlatScratch())
1560b57cec5SDimitry Andric       PrivateSegmentBuffer = true;
1570b57cec5SDimitry Andric 
1585ffd83dbSDimitry Andric     if (UseFixedABI) {
1595ffd83dbSDimitry Andric       DispatchPtr = true;
1605ffd83dbSDimitry Andric       QueuePtr = true;
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric       // FIXME: We don't need this?
1635ffd83dbSDimitry Andric       DispatchID = true;
1645ffd83dbSDimitry Andric     } else {
1650b57cec5SDimitry Andric       if (F.hasFnAttribute("amdgpu-dispatch-ptr"))
1660b57cec5SDimitry Andric         DispatchPtr = true;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric       if (F.hasFnAttribute("amdgpu-queue-ptr"))
1690b57cec5SDimitry Andric         QueuePtr = true;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric       if (F.hasFnAttribute("amdgpu-dispatch-id"))
1720b57cec5SDimitry Andric         DispatchID = true;
1735ffd83dbSDimitry Andric     }
1740b57cec5SDimitry Andric   } else if (ST.isMesaGfxShader(F)) {
1750b57cec5SDimitry Andric     ImplicitBufferPtr = true;
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
1785ffd83dbSDimitry Andric   if (UseFixedABI || F.hasFnAttribute("amdgpu-kernarg-segment-ptr"))
1790b57cec5SDimitry Andric     KernargSegmentPtr = true;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   // TODO: This could be refined a lot. The attribute is a poor way of
1825ffd83dbSDimitry Andric   // detecting calls or stack objects that may require it before argument
1835ffd83dbSDimitry Andric   // lowering.
184*fe6060f1SDimitry Andric   if (ST.hasFlatAddressSpace() && isEntryFunction() &&
185*fe6060f1SDimitry Andric       (isAmdHsaOrMesa || ST.enableFlatScratch()) &&
186*fe6060f1SDimitry Andric       (HasCalls || HasStackObjects || ST.enableFlatScratch()) &&
187*fe6060f1SDimitry Andric       !ST.flatScratchIsArchitected()) {
1880b57cec5SDimitry Andric     FlatScratchInit = true;
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
1920b57cec5SDimitry Andric   StringRef S = A.getValueAsString();
1930b57cec5SDimitry Andric   if (!S.empty())
1940b57cec5SDimitry Andric     S.consumeInteger(0, GITPtrHigh);
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   A = F.getFnAttribute("amdgpu-32bit-address-high-bits");
1970b57cec5SDimitry Andric   S = A.getValueAsString();
1980b57cec5SDimitry Andric   if (!S.empty())
1990b57cec5SDimitry Andric     S.consumeInteger(0, HighBitsOf32BitAddress);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   S = F.getFnAttribute("amdgpu-gds-size").getValueAsString();
2020b57cec5SDimitry Andric   if (!S.empty())
2030b57cec5SDimitry Andric     S.consumeInteger(0, GDSSize);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric void SIMachineFunctionInfo::limitOccupancy(const MachineFunction &MF) {
2070b57cec5SDimitry Andric   limitOccupancy(getMaxWavesPerEU());
2080b57cec5SDimitry Andric   const GCNSubtarget& ST = MF.getSubtarget<GCNSubtarget>();
2090b57cec5SDimitry Andric   limitOccupancy(ST.getOccupancyWithLocalMemSize(getLDSSize(),
2100b57cec5SDimitry Andric                  MF.getFunction()));
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2135ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addPrivateSegmentBuffer(
2140b57cec5SDimitry Andric   const SIRegisterInfo &TRI) {
2150b57cec5SDimitry Andric   ArgInfo.PrivateSegmentBuffer =
2160b57cec5SDimitry Andric     ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2178bcb0991SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SGPR_128RegClass));
2180b57cec5SDimitry Andric   NumUserSGPRs += 4;
2190b57cec5SDimitry Andric   return ArgInfo.PrivateSegmentBuffer.getRegister();
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2225ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addDispatchPtr(const SIRegisterInfo &TRI) {
2230b57cec5SDimitry Andric   ArgInfo.DispatchPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2240b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2250b57cec5SDimitry Andric   NumUserSGPRs += 2;
2260b57cec5SDimitry Andric   return ArgInfo.DispatchPtr.getRegister();
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
2295ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addQueuePtr(const SIRegisterInfo &TRI) {
2300b57cec5SDimitry Andric   ArgInfo.QueuePtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2310b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2320b57cec5SDimitry Andric   NumUserSGPRs += 2;
2330b57cec5SDimitry Andric   return ArgInfo.QueuePtr.getRegister();
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
2365ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addKernargSegmentPtr(const SIRegisterInfo &TRI) {
2370b57cec5SDimitry Andric   ArgInfo.KernargSegmentPtr
2380b57cec5SDimitry Andric     = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2390b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2400b57cec5SDimitry Andric   NumUserSGPRs += 2;
2410b57cec5SDimitry Andric   return ArgInfo.KernargSegmentPtr.getRegister();
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2445ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addDispatchID(const SIRegisterInfo &TRI) {
2450b57cec5SDimitry Andric   ArgInfo.DispatchID = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2460b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2470b57cec5SDimitry Andric   NumUserSGPRs += 2;
2480b57cec5SDimitry Andric   return ArgInfo.DispatchID.getRegister();
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2515ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addFlatScratchInit(const SIRegisterInfo &TRI) {
2520b57cec5SDimitry Andric   ArgInfo.FlatScratchInit = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2530b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2540b57cec5SDimitry Andric   NumUserSGPRs += 2;
2550b57cec5SDimitry Andric   return ArgInfo.FlatScratchInit.getRegister();
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2585ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addImplicitBufferPtr(const SIRegisterInfo &TRI) {
2590b57cec5SDimitry Andric   ArgInfo.ImplicitBufferPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2600b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2610b57cec5SDimitry Andric   NumUserSGPRs += 2;
2620b57cec5SDimitry Andric   return ArgInfo.ImplicitBufferPtr.getRegister();
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2655ffd83dbSDimitry Andric bool SIMachineFunctionInfo::isCalleeSavedReg(const MCPhysReg *CSRegs,
2665ffd83dbSDimitry Andric                                              MCPhysReg Reg) {
2670b57cec5SDimitry Andric   for (unsigned I = 0; CSRegs[I]; ++I) {
2680b57cec5SDimitry Andric     if (CSRegs[I] == Reg)
2690b57cec5SDimitry Andric       return true;
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   return false;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric /// \p returns true if \p NumLanes slots are available in VGPRs already used for
2760b57cec5SDimitry Andric /// SGPR spilling.
2770b57cec5SDimitry Andric //
2780b57cec5SDimitry Andric // FIXME: This only works after processFunctionBeforeFrameFinalized
2790b57cec5SDimitry Andric bool SIMachineFunctionInfo::haveFreeLanesForSGPRSpill(const MachineFunction &MF,
2800b57cec5SDimitry Andric                                                       unsigned NumNeed) const {
2810b57cec5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
2820b57cec5SDimitry Andric   unsigned WaveSize = ST.getWavefrontSize();
2830b57cec5SDimitry Andric   return NumVGPRSpillLanes + NumNeed <= WaveSize * SpillVGPRs.size();
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric /// Reserve a slice of a VGPR to support spilling for FrameIndex \p FI.
2870b57cec5SDimitry Andric bool SIMachineFunctionInfo::allocateSGPRSpillToVGPR(MachineFunction &MF,
2880b57cec5SDimitry Andric                                                     int FI) {
2890b57cec5SDimitry Andric   std::vector<SpilledReg> &SpillLanes = SGPRToVGPRSpills[FI];
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   // This has already been allocated.
2920b57cec5SDimitry Andric   if (!SpillLanes.empty())
2930b57cec5SDimitry Andric     return true;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
2960b57cec5SDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
2970b57cec5SDimitry Andric   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
2980b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
2990b57cec5SDimitry Andric   unsigned WaveSize = ST.getWavefrontSize();
3005ffd83dbSDimitry Andric   SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   unsigned Size = FrameInfo.getObjectSize(FI);
3035ffd83dbSDimitry Andric   unsigned NumLanes = Size / 4;
3040b57cec5SDimitry Andric 
3055ffd83dbSDimitry Andric   if (NumLanes > WaveSize)
3065ffd83dbSDimitry Andric     return false;
3075ffd83dbSDimitry Andric 
3085ffd83dbSDimitry Andric   assert(Size >= 4 && "invalid sgpr spill size");
3095ffd83dbSDimitry Andric   assert(TRI->spillSGPRToVGPR() && "not spilling SGPRs to VGPRs");
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   // Make sure to handle the case where a wide SGPR spill may span between two
3120b57cec5SDimitry Andric   // VGPRs.
3135ffd83dbSDimitry Andric   for (unsigned I = 0; I < NumLanes; ++I, ++NumVGPRSpillLanes) {
3145ffd83dbSDimitry Andric     Register LaneVGPR;
3150b57cec5SDimitry Andric     unsigned VGPRIndex = (NumVGPRSpillLanes % WaveSize);
3160b57cec5SDimitry Andric 
3175ffd83dbSDimitry Andric     // Reserve a VGPR (when NumVGPRSpillLanes = 0, WaveSize, 2*WaveSize, ..) and
3185ffd83dbSDimitry Andric     // when one of the two conditions is true:
3195ffd83dbSDimitry Andric     // 1. One reserved VGPR being tracked by VGPRReservedForSGPRSpill is not yet
3205ffd83dbSDimitry Andric     // reserved.
3215ffd83dbSDimitry Andric     // 2. All spill lanes of reserved VGPR(s) are full and another spill lane is
3225ffd83dbSDimitry Andric     // required.
3235ffd83dbSDimitry Andric     if (FuncInfo->VGPRReservedForSGPRSpill && NumVGPRSpillLanes < WaveSize) {
3245ffd83dbSDimitry Andric       assert(FuncInfo->VGPRReservedForSGPRSpill == SpillVGPRs.back().VGPR);
3255ffd83dbSDimitry Andric       LaneVGPR = FuncInfo->VGPRReservedForSGPRSpill;
3265ffd83dbSDimitry Andric     } else if (VGPRIndex == 0) {
3270b57cec5SDimitry Andric       LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF);
3280b57cec5SDimitry Andric       if (LaneVGPR == AMDGPU::NoRegister) {
3290b57cec5SDimitry Andric         // We have no VGPRs left for spilling SGPRs. Reset because we will not
3300b57cec5SDimitry Andric         // partially spill the SGPR to VGPRs.
3310b57cec5SDimitry Andric         SGPRToVGPRSpills.erase(FI);
3320b57cec5SDimitry Andric         NumVGPRSpillLanes -= I;
333*fe6060f1SDimitry Andric 
334*fe6060f1SDimitry Andric #if 0
335*fe6060f1SDimitry Andric         DiagnosticInfoResourceLimit DiagOutOfRegs(MF.getFunction(),
336*fe6060f1SDimitry Andric                                                   "VGPRs for SGPR spilling",
337*fe6060f1SDimitry Andric                                                   0, DS_Error);
338*fe6060f1SDimitry Andric         MF.getFunction().getContext().diagnose(DiagOutOfRegs);
339*fe6060f1SDimitry Andric #endif
3400b57cec5SDimitry Andric         return false;
3410b57cec5SDimitry Andric       }
3420b57cec5SDimitry Andric 
343*fe6060f1SDimitry Andric       Optional<int> SpillFI;
344*fe6060f1SDimitry Andric       // We need to preserve inactive lanes, so always save, even caller-save
345*fe6060f1SDimitry Andric       // registers.
346*fe6060f1SDimitry Andric       if (!isEntryFunction()) {
347*fe6060f1SDimitry Andric         SpillFI = FrameInfo.CreateSpillStackObject(4, Align(4));
3480b57cec5SDimitry Andric       }
3490b57cec5SDimitry Andric 
350*fe6060f1SDimitry Andric       SpillVGPRs.push_back(SGPRSpillVGPR(LaneVGPR, SpillFI));
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric       // Add this register as live-in to all blocks to avoid machine verifer
3530b57cec5SDimitry Andric       // complaining about use of an undefined physical register.
3540b57cec5SDimitry Andric       for (MachineBasicBlock &BB : MF)
3550b57cec5SDimitry Andric         BB.addLiveIn(LaneVGPR);
3560b57cec5SDimitry Andric     } else {
3570b57cec5SDimitry Andric       LaneVGPR = SpillVGPRs.back().VGPR;
3580b57cec5SDimitry Andric     }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     SpillLanes.push_back(SpilledReg(LaneVGPR, VGPRIndex));
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   return true;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3665ffd83dbSDimitry Andric /// Reserve a VGPR for spilling of SGPRs
3675ffd83dbSDimitry Andric bool SIMachineFunctionInfo::reserveVGPRforSGPRSpills(MachineFunction &MF) {
3685ffd83dbSDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3695ffd83dbSDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
3705ffd83dbSDimitry Andric   SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
3715ffd83dbSDimitry Andric 
3725ffd83dbSDimitry Andric   Register LaneVGPR = TRI->findUnusedRegister(
3735ffd83dbSDimitry Andric       MF.getRegInfo(), &AMDGPU::VGPR_32RegClass, MF, true);
374e8d8bef9SDimitry Andric   if (LaneVGPR == Register())
375e8d8bef9SDimitry Andric     return false;
376*fe6060f1SDimitry Andric   SpillVGPRs.push_back(SGPRSpillVGPR(LaneVGPR, None));
3775ffd83dbSDimitry Andric   FuncInfo->VGPRReservedForSGPRSpill = LaneVGPR;
3785ffd83dbSDimitry Andric   return true;
3795ffd83dbSDimitry Andric }
3805ffd83dbSDimitry Andric 
3810b57cec5SDimitry Andric /// Reserve AGPRs or VGPRs to support spilling for FrameIndex \p FI.
3820b57cec5SDimitry Andric /// Either AGPR is spilled to VGPR to vice versa.
3830b57cec5SDimitry Andric /// Returns true if a \p FI can be eliminated completely.
3840b57cec5SDimitry Andric bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
3850b57cec5SDimitry Andric                                                     int FI,
3860b57cec5SDimitry Andric                                                     bool isAGPRtoVGPR) {
3870b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
3880b57cec5SDimitry Andric   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
3890b57cec5SDimitry Andric   const GCNSubtarget &ST =  MF.getSubtarget<GCNSubtarget>();
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   assert(ST.hasMAIInsts() && FrameInfo.isSpillSlotObjectIndex(FI));
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   auto &Spill = VGPRToAGPRSpills[FI];
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   // This has already been allocated.
3960b57cec5SDimitry Andric   if (!Spill.Lanes.empty())
3970b57cec5SDimitry Andric     return Spill.FullyAllocated;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   unsigned Size = FrameInfo.getObjectSize(FI);
4000b57cec5SDimitry Andric   unsigned NumLanes = Size / 4;
4010b57cec5SDimitry Andric   Spill.Lanes.resize(NumLanes, AMDGPU::NoRegister);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   const TargetRegisterClass &RC =
4040b57cec5SDimitry Andric       isAGPRtoVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::AGPR_32RegClass;
4050b57cec5SDimitry Andric   auto Regs = RC.getRegisters();
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   auto &SpillRegs = isAGPRtoVGPR ? SpillAGPR : SpillVGPR;
4080b57cec5SDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
4090b57cec5SDimitry Andric   Spill.FullyAllocated = true;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   // FIXME: Move allocation logic out of MachineFunctionInfo and initialize
4120b57cec5SDimitry Andric   // once.
4130b57cec5SDimitry Andric   BitVector OtherUsedRegs;
4140b57cec5SDimitry Andric   OtherUsedRegs.resize(TRI->getNumRegs());
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   const uint32_t *CSRMask =
4170b57cec5SDimitry Andric       TRI->getCallPreservedMask(MF, MF.getFunction().getCallingConv());
4180b57cec5SDimitry Andric   if (CSRMask)
4190b57cec5SDimitry Andric     OtherUsedRegs.setBitsInMask(CSRMask);
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   // TODO: Should include register tuples, but doesn't matter with current
4220b57cec5SDimitry Andric   // usage.
4230b57cec5SDimitry Andric   for (MCPhysReg Reg : SpillAGPR)
4240b57cec5SDimitry Andric     OtherUsedRegs.set(Reg);
4250b57cec5SDimitry Andric   for (MCPhysReg Reg : SpillVGPR)
4260b57cec5SDimitry Andric     OtherUsedRegs.set(Reg);
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   SmallVectorImpl<MCPhysReg>::const_iterator NextSpillReg = Regs.begin();
4290b57cec5SDimitry Andric   for (unsigned I = 0; I < NumLanes; ++I) {
4300b57cec5SDimitry Andric     NextSpillReg = std::find_if(
4310b57cec5SDimitry Andric         NextSpillReg, Regs.end(), [&MRI, &OtherUsedRegs](MCPhysReg Reg) {
4320b57cec5SDimitry Andric           return MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg) &&
4330b57cec5SDimitry Andric                  !OtherUsedRegs[Reg];
4340b57cec5SDimitry Andric         });
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric     if (NextSpillReg == Regs.end()) { // Registers exhausted
4370b57cec5SDimitry Andric       Spill.FullyAllocated = false;
4380b57cec5SDimitry Andric       break;
4390b57cec5SDimitry Andric     }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric     OtherUsedRegs.set(*NextSpillReg);
4420b57cec5SDimitry Andric     SpillRegs.push_back(*NextSpillReg);
4430b57cec5SDimitry Andric     Spill.Lanes[I] = *NextSpillReg++;
4440b57cec5SDimitry Andric   }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   return Spill.FullyAllocated;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric void SIMachineFunctionInfo::removeDeadFrameIndices(MachineFrameInfo &MFI) {
4505ffd83dbSDimitry Andric   // The FP & BP spills haven't been inserted yet, so keep them around.
4510b57cec5SDimitry Andric   for (auto &R : SGPRToVGPRSpills) {
4525ffd83dbSDimitry Andric     if (R.first != FramePointerSaveIndex && R.first != BasePointerSaveIndex)
4530b57cec5SDimitry Andric       MFI.RemoveStackObject(R.first);
4540b57cec5SDimitry Andric   }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   // All other SPGRs must be allocated on the default stack, so reset the stack
4570b57cec5SDimitry Andric   // ID.
4580b57cec5SDimitry Andric   for (int i = MFI.getObjectIndexBegin(), e = MFI.getObjectIndexEnd(); i != e;
4590b57cec5SDimitry Andric        ++i)
4605ffd83dbSDimitry Andric     if (i != FramePointerSaveIndex && i != BasePointerSaveIndex)
4610b57cec5SDimitry Andric       MFI.setStackID(i, TargetStackID::Default);
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   for (auto &R : VGPRToAGPRSpills) {
4640b57cec5SDimitry Andric     if (R.second.FullyAllocated)
4650b57cec5SDimitry Andric       MFI.RemoveStackObject(R.first);
4660b57cec5SDimitry Andric   }
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
469*fe6060f1SDimitry Andric int SIMachineFunctionInfo::getScavengeFI(MachineFrameInfo &MFI,
470*fe6060f1SDimitry Andric                                          const SIRegisterInfo &TRI) {
471*fe6060f1SDimitry Andric   if (ScavengeFI)
472*fe6060f1SDimitry Andric     return *ScavengeFI;
473*fe6060f1SDimitry Andric   if (isEntryFunction()) {
474*fe6060f1SDimitry Andric     ScavengeFI = MFI.CreateFixedObject(
475*fe6060f1SDimitry Andric         TRI.getSpillSize(AMDGPU::SGPR_32RegClass), 0, false);
476*fe6060f1SDimitry Andric   } else {
477*fe6060f1SDimitry Andric     ScavengeFI = MFI.CreateStackObject(
478*fe6060f1SDimitry Andric         TRI.getSpillSize(AMDGPU::SGPR_32RegClass),
479*fe6060f1SDimitry Andric         TRI.getSpillAlign(AMDGPU::SGPR_32RegClass), false);
480*fe6060f1SDimitry Andric   }
481*fe6060f1SDimitry Andric   return *ScavengeFI;
482*fe6060f1SDimitry Andric }
483*fe6060f1SDimitry Andric 
4840b57cec5SDimitry Andric MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
4850b57cec5SDimitry Andric   assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
4860b57cec5SDimitry Andric   return AMDGPU::SGPR0 + NumUserSGPRs;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
4900b57cec5SDimitry Andric   return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric 
4935ffd83dbSDimitry Andric Register
4945ffd83dbSDimitry Andric SIMachineFunctionInfo::getGITPtrLoReg(const MachineFunction &MF) const {
4955ffd83dbSDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
4965ffd83dbSDimitry Andric   if (!ST.isAmdPalOS())
4975ffd83dbSDimitry Andric     return Register();
4985ffd83dbSDimitry Andric   Register GitPtrLo = AMDGPU::SGPR0; // Low GIT address passed in
4995ffd83dbSDimitry Andric   if (ST.hasMergedShaders()) {
5005ffd83dbSDimitry Andric     switch (MF.getFunction().getCallingConv()) {
5015ffd83dbSDimitry Andric     case CallingConv::AMDGPU_HS:
5025ffd83dbSDimitry Andric     case CallingConv::AMDGPU_GS:
5035ffd83dbSDimitry Andric       // Low GIT address is passed in s8 rather than s0 for an LS+HS or
5045ffd83dbSDimitry Andric       // ES+GS merged shader on gfx9+.
5055ffd83dbSDimitry Andric       GitPtrLo = AMDGPU::SGPR8;
5065ffd83dbSDimitry Andric       return GitPtrLo;
5075ffd83dbSDimitry Andric     default:
5085ffd83dbSDimitry Andric       return GitPtrLo;
5095ffd83dbSDimitry Andric     }
5105ffd83dbSDimitry Andric   }
5115ffd83dbSDimitry Andric   return GitPtrLo;
5125ffd83dbSDimitry Andric }
5135ffd83dbSDimitry Andric 
5145ffd83dbSDimitry Andric static yaml::StringValue regToString(Register Reg,
5150b57cec5SDimitry Andric                                      const TargetRegisterInfo &TRI) {
5160b57cec5SDimitry Andric   yaml::StringValue Dest;
5170b57cec5SDimitry Andric   {
5180b57cec5SDimitry Andric     raw_string_ostream OS(Dest.Value);
5190b57cec5SDimitry Andric     OS << printReg(Reg, &TRI);
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric   return Dest;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric static Optional<yaml::SIArgumentInfo>
5250b57cec5SDimitry Andric convertArgumentInfo(const AMDGPUFunctionArgInfo &ArgInfo,
5260b57cec5SDimitry Andric                     const TargetRegisterInfo &TRI) {
5270b57cec5SDimitry Andric   yaml::SIArgumentInfo AI;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   auto convertArg = [&](Optional<yaml::SIArgument> &A,
5300b57cec5SDimitry Andric                         const ArgDescriptor &Arg) {
5310b57cec5SDimitry Andric     if (!Arg)
5320b57cec5SDimitry Andric       return false;
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric     // Create a register or stack argument.
5350b57cec5SDimitry Andric     yaml::SIArgument SA = yaml::SIArgument::createArgument(Arg.isRegister());
5360b57cec5SDimitry Andric     if (Arg.isRegister()) {
5370b57cec5SDimitry Andric       raw_string_ostream OS(SA.RegisterName.Value);
5380b57cec5SDimitry Andric       OS << printReg(Arg.getRegister(), &TRI);
5390b57cec5SDimitry Andric     } else
5400b57cec5SDimitry Andric       SA.StackOffset = Arg.getStackOffset();
5410b57cec5SDimitry Andric     // Check and update the optional mask.
5420b57cec5SDimitry Andric     if (Arg.isMasked())
5430b57cec5SDimitry Andric       SA.Mask = Arg.getMask();
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric     A = SA;
5460b57cec5SDimitry Andric     return true;
5470b57cec5SDimitry Andric   };
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   bool Any = false;
5500b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentBuffer, ArgInfo.PrivateSegmentBuffer);
5510b57cec5SDimitry Andric   Any |= convertArg(AI.DispatchPtr, ArgInfo.DispatchPtr);
5520b57cec5SDimitry Andric   Any |= convertArg(AI.QueuePtr, ArgInfo.QueuePtr);
5530b57cec5SDimitry Andric   Any |= convertArg(AI.KernargSegmentPtr, ArgInfo.KernargSegmentPtr);
5540b57cec5SDimitry Andric   Any |= convertArg(AI.DispatchID, ArgInfo.DispatchID);
5550b57cec5SDimitry Andric   Any |= convertArg(AI.FlatScratchInit, ArgInfo.FlatScratchInit);
5560b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentSize, ArgInfo.PrivateSegmentSize);
5570b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDX, ArgInfo.WorkGroupIDX);
5580b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDY, ArgInfo.WorkGroupIDY);
5590b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDZ, ArgInfo.WorkGroupIDZ);
5600b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupInfo, ArgInfo.WorkGroupInfo);
5610b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentWaveByteOffset,
5620b57cec5SDimitry Andric                     ArgInfo.PrivateSegmentWaveByteOffset);
5630b57cec5SDimitry Andric   Any |= convertArg(AI.ImplicitArgPtr, ArgInfo.ImplicitArgPtr);
5640b57cec5SDimitry Andric   Any |= convertArg(AI.ImplicitBufferPtr, ArgInfo.ImplicitBufferPtr);
5650b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDX, ArgInfo.WorkItemIDX);
5660b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDY, ArgInfo.WorkItemIDY);
5670b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDZ, ArgInfo.WorkItemIDZ);
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   if (Any)
5700b57cec5SDimitry Andric     return AI;
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   return None;
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
576*fe6060f1SDimitry Andric     const llvm::SIMachineFunctionInfo &MFI, const TargetRegisterInfo &TRI,
577*fe6060f1SDimitry Andric     const llvm::MachineFunction &MF)
5780b57cec5SDimitry Andric     : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
579e8d8bef9SDimitry Andric       MaxKernArgAlign(MFI.getMaxKernArgAlign()), LDSSize(MFI.getLDSSize()),
580e8d8bef9SDimitry Andric       DynLDSAlign(MFI.getDynLDSAlign()), IsEntryFunction(MFI.isEntryFunction()),
5810b57cec5SDimitry Andric       NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
582e8d8bef9SDimitry Andric       MemoryBound(MFI.isMemoryBound()), WaveLimiter(MFI.needsWaveLimiter()),
583e8d8bef9SDimitry Andric       HasSpilledSGPRs(MFI.hasSpilledSGPRs()),
584e8d8bef9SDimitry Andric       HasSpilledVGPRs(MFI.hasSpilledVGPRs()),
5858bcb0991SDimitry Andric       HighBitsOf32BitAddress(MFI.get32BitAddressHighBits()),
586e8d8bef9SDimitry Andric       Occupancy(MFI.getOccupancy()),
5870b57cec5SDimitry Andric       ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
5880b57cec5SDimitry Andric       FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
5890b57cec5SDimitry Andric       StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)),
590e8d8bef9SDimitry Andric       ArgInfo(convertArgumentInfo(MFI.getArgInfo(), TRI)), Mode(MFI.getMode()) {
591*fe6060f1SDimitry Andric   auto SFI = MFI.getOptionalScavengeFI();
592*fe6060f1SDimitry Andric   if (SFI)
593*fe6060f1SDimitry Andric     ScavengeFI = yaml::FrameIndex(*SFI, MF.getFrameInfo());
594e8d8bef9SDimitry Andric }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
5970b57cec5SDimitry Andric   MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric bool SIMachineFunctionInfo::initializeBaseYamlFields(
601*fe6060f1SDimitry Andric     const yaml::SIMachineFunctionInfo &YamlMFI, const MachineFunction &MF,
602*fe6060f1SDimitry Andric     PerFunctionMIParsingState &PFS, SMDiagnostic &Error, SMRange &SourceRange) {
6030b57cec5SDimitry Andric   ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
6048bcb0991SDimitry Andric   MaxKernArgAlign = assumeAligned(YamlMFI.MaxKernArgAlign);
6050b57cec5SDimitry Andric   LDSSize = YamlMFI.LDSSize;
606e8d8bef9SDimitry Andric   DynLDSAlign = YamlMFI.DynLDSAlign;
6078bcb0991SDimitry Andric   HighBitsOf32BitAddress = YamlMFI.HighBitsOf32BitAddress;
608e8d8bef9SDimitry Andric   Occupancy = YamlMFI.Occupancy;
6090b57cec5SDimitry Andric   IsEntryFunction = YamlMFI.IsEntryFunction;
6100b57cec5SDimitry Andric   NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
6110b57cec5SDimitry Andric   MemoryBound = YamlMFI.MemoryBound;
6120b57cec5SDimitry Andric   WaveLimiter = YamlMFI.WaveLimiter;
613e8d8bef9SDimitry Andric   HasSpilledSGPRs = YamlMFI.HasSpilledSGPRs;
614e8d8bef9SDimitry Andric   HasSpilledVGPRs = YamlMFI.HasSpilledVGPRs;
615*fe6060f1SDimitry Andric 
616*fe6060f1SDimitry Andric   if (YamlMFI.ScavengeFI) {
617*fe6060f1SDimitry Andric     auto FIOrErr = YamlMFI.ScavengeFI->getFI(MF.getFrameInfo());
618*fe6060f1SDimitry Andric     if (!FIOrErr) {
619*fe6060f1SDimitry Andric       // Create a diagnostic for a the frame index.
620*fe6060f1SDimitry Andric       const MemoryBuffer &Buffer =
621*fe6060f1SDimitry Andric           *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
622*fe6060f1SDimitry Andric 
623*fe6060f1SDimitry Andric       Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1, 1,
624*fe6060f1SDimitry Andric                            SourceMgr::DK_Error, toString(FIOrErr.takeError()),
625*fe6060f1SDimitry Andric                            "", None, None);
626*fe6060f1SDimitry Andric       SourceRange = YamlMFI.ScavengeFI->SourceRange;
627*fe6060f1SDimitry Andric       return true;
628*fe6060f1SDimitry Andric     }
629*fe6060f1SDimitry Andric     ScavengeFI = *FIOrErr;
630*fe6060f1SDimitry Andric   } else {
631*fe6060f1SDimitry Andric     ScavengeFI = None;
632*fe6060f1SDimitry Andric   }
6330b57cec5SDimitry Andric   return false;
6340b57cec5SDimitry Andric }
6355ffd83dbSDimitry Andric 
6365ffd83dbSDimitry Andric // Remove VGPR which was reserved for SGPR spills if there are no spilled SGPRs
6375ffd83dbSDimitry Andric bool SIMachineFunctionInfo::removeVGPRForSGPRSpill(Register ReservedVGPR,
6385ffd83dbSDimitry Andric                                                    MachineFunction &MF) {
6395ffd83dbSDimitry Andric   for (auto *i = SpillVGPRs.begin(); i < SpillVGPRs.end(); i++) {
6405ffd83dbSDimitry Andric     if (i->VGPR == ReservedVGPR) {
6415ffd83dbSDimitry Andric       SpillVGPRs.erase(i);
6425ffd83dbSDimitry Andric 
6435ffd83dbSDimitry Andric       for (MachineBasicBlock &MBB : MF) {
6445ffd83dbSDimitry Andric         MBB.removeLiveIn(ReservedVGPR);
6455ffd83dbSDimitry Andric         MBB.sortUniqueLiveIns();
6465ffd83dbSDimitry Andric       }
6475ffd83dbSDimitry Andric       this->VGPRReservedForSGPRSpill = AMDGPU::NoRegister;
6485ffd83dbSDimitry Andric       return true;
6495ffd83dbSDimitry Andric     }
6505ffd83dbSDimitry Andric   }
6515ffd83dbSDimitry Andric   return false;
6525ffd83dbSDimitry Andric }
653