xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
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"
11fe6060f1SDimitry Andric #include "AMDGPUSubtarget.h"
12fe6060f1SDimitry Andric #include "SIRegisterInfo.h"
13fe6060f1SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
14fe6060f1SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
15fe6060f1SDimitry Andric #include "llvm/ADT/Optional.h"
16fe6060f1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
17fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
18fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
20fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21fe6060f1SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
22fe6060f1SDimitry Andric #include "llvm/IR/CallingConv.h"
23fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
24fe6060f1SDimitry Andric #include "llvm/IR/Function.h"
25fe6060f1SDimitry Andric #include <cassert>
26fe6060f1SDimitry 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 
65349cc55cSDimitry Andric   const bool IsKernel = CC == CallingConv::AMDGPU_KERNEL ||
66349cc55cSDimitry Andric                         CC == CallingConv::SPIR_KERNEL;
675ffd83dbSDimitry Andric 
68349cc55cSDimitry Andric   if (IsKernel) {
69349cc55cSDimitry Andric     if (!F.arg_empty() || ST.getImplicitArgNumBytes(F) != 0)
700b57cec5SDimitry Andric       KernargSegmentPtr = true;
710b57cec5SDimitry Andric     WorkGroupIDX = true;
720b57cec5SDimitry Andric     WorkItemIDX = true;
730b57cec5SDimitry Andric   } else if (CC == CallingConv::AMDGPU_PS) {
740b57cec5SDimitry Andric     PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   if (!isEntryFunction()) {
78*0eae32dcSDimitry Andric     if (CC != CallingConv::AMDGPU_Gfx)
79fe6060f1SDimitry Andric       ArgInfo = AMDGPUArgumentUsageInfo::FixedABIFunctionInfo;
80fe6060f1SDimitry Andric 
810b57cec5SDimitry Andric     // TODO: Pick a high register, and shift down, similar to a kernel.
825ffd83dbSDimitry Andric     FrameOffsetReg = AMDGPU::SGPR33;
830b57cec5SDimitry Andric     StackPtrOffsetReg = AMDGPU::SGPR32;
840b57cec5SDimitry Andric 
85e8d8bef9SDimitry Andric     if (!ST.enableFlatScratch()) {
86e8d8bef9SDimitry Andric       // Non-entry functions have no special inputs for now, other registers
87e8d8bef9SDimitry Andric       // required for scratch access.
88e8d8bef9SDimitry Andric       ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
89e8d8bef9SDimitry Andric 
900b57cec5SDimitry Andric       ArgInfo.PrivateSegmentBuffer =
910b57cec5SDimitry Andric         ArgDescriptor::createRegister(ScratchRSrcReg);
92e8d8bef9SDimitry Andric     }
930b57cec5SDimitry Andric 
94349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-implicitarg-ptr"))
950b57cec5SDimitry Andric       ImplicitArgPtr = true;
960b57cec5SDimitry Andric   } else {
97349cc55cSDimitry Andric     ImplicitArgPtr = false;
980b57cec5SDimitry Andric     MaxKernArgAlign = std::max(ST.getAlignmentForImplicitArgPtr(),
990b57cec5SDimitry Andric                                MaxKernArgAlign);
1000b57cec5SDimitry Andric   }
101349cc55cSDimitry Andric 
102349cc55cSDimitry Andric   bool isAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
103349cc55cSDimitry Andric   if (isAmdHsaOrMesa && !ST.enableFlatScratch())
104349cc55cSDimitry Andric     PrivateSegmentBuffer = true;
105349cc55cSDimitry Andric   else if (ST.isMesaGfxShader(F))
106349cc55cSDimitry Andric     ImplicitBufferPtr = true;
1070b57cec5SDimitry Andric 
108*0eae32dcSDimitry Andric   if (!AMDGPU::isGraphics(CC)) {
109349cc55cSDimitry Andric     if (IsKernel || !F.hasFnAttribute("amdgpu-no-workgroup-id-x"))
1100b57cec5SDimitry Andric       WorkGroupIDX = true;
1110b57cec5SDimitry Andric 
112349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-workgroup-id-y"))
1130b57cec5SDimitry Andric       WorkGroupIDY = true;
1140b57cec5SDimitry Andric 
115349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-workgroup-id-z"))
1160b57cec5SDimitry Andric       WorkGroupIDZ = true;
1170b57cec5SDimitry Andric 
118349cc55cSDimitry Andric     if (IsKernel || !F.hasFnAttribute("amdgpu-no-workitem-id-x"))
1190b57cec5SDimitry Andric       WorkItemIDX = true;
1200b57cec5SDimitry Andric 
121349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-workitem-id-y"))
1220b57cec5SDimitry Andric       WorkItemIDY = true;
1230b57cec5SDimitry Andric 
124349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-workitem-id-z"))
1250b57cec5SDimitry Andric       WorkItemIDZ = true;
126349cc55cSDimitry Andric 
127349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-dispatch-ptr"))
128349cc55cSDimitry Andric       DispatchPtr = true;
129349cc55cSDimitry Andric 
130349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-queue-ptr"))
131349cc55cSDimitry Andric       QueuePtr = true;
132349cc55cSDimitry Andric 
133349cc55cSDimitry Andric     if (!F.hasFnAttribute("amdgpu-no-dispatch-id"))
134349cc55cSDimitry Andric       DispatchID = true;
1355ffd83dbSDimitry Andric   }
1360b57cec5SDimitry Andric 
137349cc55cSDimitry Andric   // FIXME: This attribute is a hack, we just need an analysis on the function
138349cc55cSDimitry Andric   // to look for allocas.
1395ffd83dbSDimitry Andric   bool HasStackObjects = F.hasFnAttribute("amdgpu-stack-objects");
140349cc55cSDimitry Andric 
141349cc55cSDimitry Andric   // TODO: This could be refined a lot. The attribute is a poor way of
142349cc55cSDimitry Andric   // detecting calls or stack objects that may require it before argument
143349cc55cSDimitry Andric   // lowering.
144349cc55cSDimitry Andric   if (ST.hasFlatAddressSpace() && isEntryFunction() &&
145349cc55cSDimitry Andric       (isAmdHsaOrMesa || ST.enableFlatScratch()) &&
146349cc55cSDimitry Andric       (HasCalls || HasStackObjects || ST.enableFlatScratch()) &&
147349cc55cSDimitry Andric       !ST.flatScratchIsArchitected()) {
148349cc55cSDimitry Andric     FlatScratchInit = true;
149349cc55cSDimitry Andric   }
150349cc55cSDimitry Andric 
1510b57cec5SDimitry Andric   if (isEntryFunction()) {
1520b57cec5SDimitry Andric     // X, XY, and XYZ are the only supported combinations, so make sure Y is
1530b57cec5SDimitry Andric     // enabled if Z is.
1540b57cec5SDimitry Andric     if (WorkItemIDZ)
1550b57cec5SDimitry Andric       WorkItemIDY = true;
1560b57cec5SDimitry Andric 
157fe6060f1SDimitry Andric     if (!ST.flatScratchIsArchitected()) {
1580b57cec5SDimitry Andric       PrivateSegmentWaveByteOffset = true;
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric       // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
1610b57cec5SDimitry Andric       if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
1620b57cec5SDimitry Andric           (CC == CallingConv::AMDGPU_HS || CC == CallingConv::AMDGPU_GS))
1630b57cec5SDimitry Andric         ArgInfo.PrivateSegmentWaveByteOffset =
1640b57cec5SDimitry Andric             ArgDescriptor::createRegister(AMDGPU::SGPR5);
1650b57cec5SDimitry Andric     }
166fe6060f1SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
1690b57cec5SDimitry Andric   StringRef S = A.getValueAsString();
1700b57cec5SDimitry Andric   if (!S.empty())
1710b57cec5SDimitry Andric     S.consumeInteger(0, GITPtrHigh);
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   A = F.getFnAttribute("amdgpu-32bit-address-high-bits");
1740b57cec5SDimitry Andric   S = A.getValueAsString();
1750b57cec5SDimitry Andric   if (!S.empty())
1760b57cec5SDimitry Andric     S.consumeInteger(0, HighBitsOf32BitAddress);
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   S = F.getFnAttribute("amdgpu-gds-size").getValueAsString();
1790b57cec5SDimitry Andric   if (!S.empty())
1800b57cec5SDimitry Andric     S.consumeInteger(0, GDSSize);
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric void SIMachineFunctionInfo::limitOccupancy(const MachineFunction &MF) {
1840b57cec5SDimitry Andric   limitOccupancy(getMaxWavesPerEU());
1850b57cec5SDimitry Andric   const GCNSubtarget& ST = MF.getSubtarget<GCNSubtarget>();
1860b57cec5SDimitry Andric   limitOccupancy(ST.getOccupancyWithLocalMemSize(getLDSSize(),
1870b57cec5SDimitry Andric                  MF.getFunction()));
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1905ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addPrivateSegmentBuffer(
1910b57cec5SDimitry Andric   const SIRegisterInfo &TRI) {
1920b57cec5SDimitry Andric   ArgInfo.PrivateSegmentBuffer =
1930b57cec5SDimitry Andric     ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
1948bcb0991SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SGPR_128RegClass));
1950b57cec5SDimitry Andric   NumUserSGPRs += 4;
1960b57cec5SDimitry Andric   return ArgInfo.PrivateSegmentBuffer.getRegister();
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1995ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addDispatchPtr(const SIRegisterInfo &TRI) {
2000b57cec5SDimitry Andric   ArgInfo.DispatchPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2010b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2020b57cec5SDimitry Andric   NumUserSGPRs += 2;
2030b57cec5SDimitry Andric   return ArgInfo.DispatchPtr.getRegister();
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2065ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addQueuePtr(const SIRegisterInfo &TRI) {
2070b57cec5SDimitry Andric   ArgInfo.QueuePtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2080b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2090b57cec5SDimitry Andric   NumUserSGPRs += 2;
2100b57cec5SDimitry Andric   return ArgInfo.QueuePtr.getRegister();
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2135ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addKernargSegmentPtr(const SIRegisterInfo &TRI) {
2140b57cec5SDimitry Andric   ArgInfo.KernargSegmentPtr
2150b57cec5SDimitry Andric     = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2160b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2170b57cec5SDimitry Andric   NumUserSGPRs += 2;
2180b57cec5SDimitry Andric   return ArgInfo.KernargSegmentPtr.getRegister();
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
2215ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addDispatchID(const SIRegisterInfo &TRI) {
2220b57cec5SDimitry Andric   ArgInfo.DispatchID = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2230b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2240b57cec5SDimitry Andric   NumUserSGPRs += 2;
2250b57cec5SDimitry Andric   return ArgInfo.DispatchID.getRegister();
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
2285ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addFlatScratchInit(const SIRegisterInfo &TRI) {
2290b57cec5SDimitry Andric   ArgInfo.FlatScratchInit = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2300b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2310b57cec5SDimitry Andric   NumUserSGPRs += 2;
2320b57cec5SDimitry Andric   return ArgInfo.FlatScratchInit.getRegister();
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
2355ffd83dbSDimitry Andric Register SIMachineFunctionInfo::addImplicitBufferPtr(const SIRegisterInfo &TRI) {
2360b57cec5SDimitry Andric   ArgInfo.ImplicitBufferPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
2370b57cec5SDimitry Andric     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
2380b57cec5SDimitry Andric   NumUserSGPRs += 2;
2390b57cec5SDimitry Andric   return ArgInfo.ImplicitBufferPtr.getRegister();
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2425ffd83dbSDimitry Andric bool SIMachineFunctionInfo::isCalleeSavedReg(const MCPhysReg *CSRegs,
2435ffd83dbSDimitry Andric                                              MCPhysReg Reg) {
2440b57cec5SDimitry Andric   for (unsigned I = 0; CSRegs[I]; ++I) {
2450b57cec5SDimitry Andric     if (CSRegs[I] == Reg)
2460b57cec5SDimitry Andric       return true;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   return false;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric /// \p returns true if \p NumLanes slots are available in VGPRs already used for
2530b57cec5SDimitry Andric /// SGPR spilling.
2540b57cec5SDimitry Andric //
2550b57cec5SDimitry Andric // FIXME: This only works after processFunctionBeforeFrameFinalized
2560b57cec5SDimitry Andric bool SIMachineFunctionInfo::haveFreeLanesForSGPRSpill(const MachineFunction &MF,
2570b57cec5SDimitry Andric                                                       unsigned NumNeed) const {
2580b57cec5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
2590b57cec5SDimitry Andric   unsigned WaveSize = ST.getWavefrontSize();
2600b57cec5SDimitry Andric   return NumVGPRSpillLanes + NumNeed <= WaveSize * SpillVGPRs.size();
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric /// Reserve a slice of a VGPR to support spilling for FrameIndex \p FI.
2640b57cec5SDimitry Andric bool SIMachineFunctionInfo::allocateSGPRSpillToVGPR(MachineFunction &MF,
2650b57cec5SDimitry Andric                                                     int FI) {
2660b57cec5SDimitry Andric   std::vector<SpilledReg> &SpillLanes = SGPRToVGPRSpills[FI];
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   // This has already been allocated.
2690b57cec5SDimitry Andric   if (!SpillLanes.empty())
2700b57cec5SDimitry Andric     return true;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
2730b57cec5SDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
2740b57cec5SDimitry Andric   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
2750b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
2760b57cec5SDimitry Andric   unsigned WaveSize = ST.getWavefrontSize();
2775ffd83dbSDimitry Andric   SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   unsigned Size = FrameInfo.getObjectSize(FI);
2805ffd83dbSDimitry Andric   unsigned NumLanes = Size / 4;
2810b57cec5SDimitry Andric 
2825ffd83dbSDimitry Andric   if (NumLanes > WaveSize)
2835ffd83dbSDimitry Andric     return false;
2845ffd83dbSDimitry Andric 
2855ffd83dbSDimitry Andric   assert(Size >= 4 && "invalid sgpr spill size");
2865ffd83dbSDimitry Andric   assert(TRI->spillSGPRToVGPR() && "not spilling SGPRs to VGPRs");
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // Make sure to handle the case where a wide SGPR spill may span between two
2890b57cec5SDimitry Andric   // VGPRs.
2905ffd83dbSDimitry Andric   for (unsigned I = 0; I < NumLanes; ++I, ++NumVGPRSpillLanes) {
2915ffd83dbSDimitry Andric     Register LaneVGPR;
2920b57cec5SDimitry Andric     unsigned VGPRIndex = (NumVGPRSpillLanes % WaveSize);
2930b57cec5SDimitry Andric 
2945ffd83dbSDimitry Andric     // Reserve a VGPR (when NumVGPRSpillLanes = 0, WaveSize, 2*WaveSize, ..) and
2955ffd83dbSDimitry Andric     // when one of the two conditions is true:
2965ffd83dbSDimitry Andric     // 1. One reserved VGPR being tracked by VGPRReservedForSGPRSpill is not yet
2975ffd83dbSDimitry Andric     // reserved.
2985ffd83dbSDimitry Andric     // 2. All spill lanes of reserved VGPR(s) are full and another spill lane is
2995ffd83dbSDimitry Andric     // required.
3005ffd83dbSDimitry Andric     if (FuncInfo->VGPRReservedForSGPRSpill && NumVGPRSpillLanes < WaveSize) {
3015ffd83dbSDimitry Andric       assert(FuncInfo->VGPRReservedForSGPRSpill == SpillVGPRs.back().VGPR);
3025ffd83dbSDimitry Andric       LaneVGPR = FuncInfo->VGPRReservedForSGPRSpill;
3035ffd83dbSDimitry Andric     } else if (VGPRIndex == 0) {
3040b57cec5SDimitry Andric       LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF);
3050b57cec5SDimitry Andric       if (LaneVGPR == AMDGPU::NoRegister) {
3060b57cec5SDimitry Andric         // We have no VGPRs left for spilling SGPRs. Reset because we will not
3070b57cec5SDimitry Andric         // partially spill the SGPR to VGPRs.
3080b57cec5SDimitry Andric         SGPRToVGPRSpills.erase(FI);
3090b57cec5SDimitry Andric         NumVGPRSpillLanes -= I;
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric #if 0
312fe6060f1SDimitry Andric         DiagnosticInfoResourceLimit DiagOutOfRegs(MF.getFunction(),
313fe6060f1SDimitry Andric                                                   "VGPRs for SGPR spilling",
314fe6060f1SDimitry Andric                                                   0, DS_Error);
315fe6060f1SDimitry Andric         MF.getFunction().getContext().diagnose(DiagOutOfRegs);
316fe6060f1SDimitry Andric #endif
3170b57cec5SDimitry Andric         return false;
3180b57cec5SDimitry Andric       }
3190b57cec5SDimitry Andric 
320fe6060f1SDimitry Andric       Optional<int> SpillFI;
321fe6060f1SDimitry Andric       // We need to preserve inactive lanes, so always save, even caller-save
322fe6060f1SDimitry Andric       // registers.
323fe6060f1SDimitry Andric       if (!isEntryFunction()) {
324fe6060f1SDimitry Andric         SpillFI = FrameInfo.CreateSpillStackObject(4, Align(4));
3250b57cec5SDimitry Andric       }
3260b57cec5SDimitry Andric 
327fe6060f1SDimitry Andric       SpillVGPRs.push_back(SGPRSpillVGPR(LaneVGPR, SpillFI));
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric       // Add this register as live-in to all blocks to avoid machine verifer
3300b57cec5SDimitry Andric       // complaining about use of an undefined physical register.
3310b57cec5SDimitry Andric       for (MachineBasicBlock &BB : MF)
3320b57cec5SDimitry Andric         BB.addLiveIn(LaneVGPR);
3330b57cec5SDimitry Andric     } else {
3340b57cec5SDimitry Andric       LaneVGPR = SpillVGPRs.back().VGPR;
3350b57cec5SDimitry Andric     }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric     SpillLanes.push_back(SpilledReg(LaneVGPR, VGPRIndex));
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   return true;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
3435ffd83dbSDimitry Andric /// Reserve a VGPR for spilling of SGPRs
3445ffd83dbSDimitry Andric bool SIMachineFunctionInfo::reserveVGPRforSGPRSpills(MachineFunction &MF) {
3455ffd83dbSDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3465ffd83dbSDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
3475ffd83dbSDimitry Andric   SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
3485ffd83dbSDimitry Andric 
3495ffd83dbSDimitry Andric   Register LaneVGPR = TRI->findUnusedRegister(
3505ffd83dbSDimitry Andric       MF.getRegInfo(), &AMDGPU::VGPR_32RegClass, MF, true);
351e8d8bef9SDimitry Andric   if (LaneVGPR == Register())
352e8d8bef9SDimitry Andric     return false;
353fe6060f1SDimitry Andric   SpillVGPRs.push_back(SGPRSpillVGPR(LaneVGPR, None));
3545ffd83dbSDimitry Andric   FuncInfo->VGPRReservedForSGPRSpill = LaneVGPR;
3555ffd83dbSDimitry Andric   return true;
3565ffd83dbSDimitry Andric }
3575ffd83dbSDimitry Andric 
3580b57cec5SDimitry Andric /// Reserve AGPRs or VGPRs to support spilling for FrameIndex \p FI.
3590b57cec5SDimitry Andric /// Either AGPR is spilled to VGPR to vice versa.
3600b57cec5SDimitry Andric /// Returns true if a \p FI can be eliminated completely.
3610b57cec5SDimitry Andric bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
3620b57cec5SDimitry Andric                                                     int FI,
3630b57cec5SDimitry Andric                                                     bool isAGPRtoVGPR) {
3640b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
3650b57cec5SDimitry Andric   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
3660b57cec5SDimitry Andric   const GCNSubtarget &ST =  MF.getSubtarget<GCNSubtarget>();
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   assert(ST.hasMAIInsts() && FrameInfo.isSpillSlotObjectIndex(FI));
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   auto &Spill = VGPRToAGPRSpills[FI];
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   // This has already been allocated.
3730b57cec5SDimitry Andric   if (!Spill.Lanes.empty())
3740b57cec5SDimitry Andric     return Spill.FullyAllocated;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   unsigned Size = FrameInfo.getObjectSize(FI);
3770b57cec5SDimitry Andric   unsigned NumLanes = Size / 4;
3780b57cec5SDimitry Andric   Spill.Lanes.resize(NumLanes, AMDGPU::NoRegister);
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   const TargetRegisterClass &RC =
3810b57cec5SDimitry Andric       isAGPRtoVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::AGPR_32RegClass;
3820b57cec5SDimitry Andric   auto Regs = RC.getRegisters();
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   auto &SpillRegs = isAGPRtoVGPR ? SpillAGPR : SpillVGPR;
3850b57cec5SDimitry Andric   const SIRegisterInfo *TRI = ST.getRegisterInfo();
3860b57cec5SDimitry Andric   Spill.FullyAllocated = true;
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   // FIXME: Move allocation logic out of MachineFunctionInfo and initialize
3890b57cec5SDimitry Andric   // once.
3900b57cec5SDimitry Andric   BitVector OtherUsedRegs;
3910b57cec5SDimitry Andric   OtherUsedRegs.resize(TRI->getNumRegs());
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   const uint32_t *CSRMask =
3940b57cec5SDimitry Andric       TRI->getCallPreservedMask(MF, MF.getFunction().getCallingConv());
3950b57cec5SDimitry Andric   if (CSRMask)
3960b57cec5SDimitry Andric     OtherUsedRegs.setBitsInMask(CSRMask);
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   // TODO: Should include register tuples, but doesn't matter with current
3990b57cec5SDimitry Andric   // usage.
4000b57cec5SDimitry Andric   for (MCPhysReg Reg : SpillAGPR)
4010b57cec5SDimitry Andric     OtherUsedRegs.set(Reg);
4020b57cec5SDimitry Andric   for (MCPhysReg Reg : SpillVGPR)
4030b57cec5SDimitry Andric     OtherUsedRegs.set(Reg);
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   SmallVectorImpl<MCPhysReg>::const_iterator NextSpillReg = Regs.begin();
406349cc55cSDimitry Andric   for (int I = NumLanes - 1; I >= 0; --I) {
4070b57cec5SDimitry Andric     NextSpillReg = std::find_if(
4080b57cec5SDimitry Andric         NextSpillReg, Regs.end(), [&MRI, &OtherUsedRegs](MCPhysReg Reg) {
4090b57cec5SDimitry Andric           return MRI.isAllocatable(Reg) && !MRI.isPhysRegUsed(Reg) &&
4100b57cec5SDimitry Andric                  !OtherUsedRegs[Reg];
4110b57cec5SDimitry Andric         });
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric     if (NextSpillReg == Regs.end()) { // Registers exhausted
4140b57cec5SDimitry Andric       Spill.FullyAllocated = false;
4150b57cec5SDimitry Andric       break;
4160b57cec5SDimitry Andric     }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     OtherUsedRegs.set(*NextSpillReg);
4190b57cec5SDimitry Andric     SpillRegs.push_back(*NextSpillReg);
4200b57cec5SDimitry Andric     Spill.Lanes[I] = *NextSpillReg++;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   return Spill.FullyAllocated;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric void SIMachineFunctionInfo::removeDeadFrameIndices(MachineFrameInfo &MFI) {
427349cc55cSDimitry Andric   // Remove dead frame indices from function frame, however keep FP & BP since
428349cc55cSDimitry Andric   // spills for them haven't been inserted yet. And also make sure to remove the
429349cc55cSDimitry Andric   // frame indices from `SGPRToVGPRSpills` data structure, otherwise, it could
430349cc55cSDimitry Andric   // result in an unexpected side effect and bug, in case of any re-mapping of
431349cc55cSDimitry Andric   // freed frame indices by later pass(es) like "stack slot coloring".
432349cc55cSDimitry Andric   for (auto &R : make_early_inc_range(SGPRToVGPRSpills)) {
433349cc55cSDimitry Andric     if (R.first != FramePointerSaveIndex && R.first != BasePointerSaveIndex) {
4340b57cec5SDimitry Andric       MFI.RemoveStackObject(R.first);
435349cc55cSDimitry Andric       SGPRToVGPRSpills.erase(R.first);
436349cc55cSDimitry Andric     }
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // All other SPGRs must be allocated on the default stack, so reset the stack
4400b57cec5SDimitry Andric   // ID.
4410b57cec5SDimitry Andric   for (int i = MFI.getObjectIndexBegin(), e = MFI.getObjectIndexEnd(); i != e;
4420b57cec5SDimitry Andric        ++i)
4435ffd83dbSDimitry Andric     if (i != FramePointerSaveIndex && i != BasePointerSaveIndex)
4440b57cec5SDimitry Andric       MFI.setStackID(i, TargetStackID::Default);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   for (auto &R : VGPRToAGPRSpills) {
447*0eae32dcSDimitry Andric     if (R.second.IsDead)
4480b57cec5SDimitry Andric       MFI.RemoveStackObject(R.first);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
452fe6060f1SDimitry Andric int SIMachineFunctionInfo::getScavengeFI(MachineFrameInfo &MFI,
453fe6060f1SDimitry Andric                                          const SIRegisterInfo &TRI) {
454fe6060f1SDimitry Andric   if (ScavengeFI)
455fe6060f1SDimitry Andric     return *ScavengeFI;
456fe6060f1SDimitry Andric   if (isEntryFunction()) {
457fe6060f1SDimitry Andric     ScavengeFI = MFI.CreateFixedObject(
458fe6060f1SDimitry Andric         TRI.getSpillSize(AMDGPU::SGPR_32RegClass), 0, false);
459fe6060f1SDimitry Andric   } else {
460fe6060f1SDimitry Andric     ScavengeFI = MFI.CreateStackObject(
461fe6060f1SDimitry Andric         TRI.getSpillSize(AMDGPU::SGPR_32RegClass),
462fe6060f1SDimitry Andric         TRI.getSpillAlign(AMDGPU::SGPR_32RegClass), false);
463fe6060f1SDimitry Andric   }
464fe6060f1SDimitry Andric   return *ScavengeFI;
465fe6060f1SDimitry Andric }
466fe6060f1SDimitry Andric 
4670b57cec5SDimitry Andric MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
4680b57cec5SDimitry Andric   assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
4690b57cec5SDimitry Andric   return AMDGPU::SGPR0 + NumUserSGPRs;
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
4730b57cec5SDimitry Andric   return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric 
4765ffd83dbSDimitry Andric Register
4775ffd83dbSDimitry Andric SIMachineFunctionInfo::getGITPtrLoReg(const MachineFunction &MF) const {
4785ffd83dbSDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
4795ffd83dbSDimitry Andric   if (!ST.isAmdPalOS())
4805ffd83dbSDimitry Andric     return Register();
4815ffd83dbSDimitry Andric   Register GitPtrLo = AMDGPU::SGPR0; // Low GIT address passed in
4825ffd83dbSDimitry Andric   if (ST.hasMergedShaders()) {
4835ffd83dbSDimitry Andric     switch (MF.getFunction().getCallingConv()) {
4845ffd83dbSDimitry Andric     case CallingConv::AMDGPU_HS:
4855ffd83dbSDimitry Andric     case CallingConv::AMDGPU_GS:
4865ffd83dbSDimitry Andric       // Low GIT address is passed in s8 rather than s0 for an LS+HS or
4875ffd83dbSDimitry Andric       // ES+GS merged shader on gfx9+.
4885ffd83dbSDimitry Andric       GitPtrLo = AMDGPU::SGPR8;
4895ffd83dbSDimitry Andric       return GitPtrLo;
4905ffd83dbSDimitry Andric     default:
4915ffd83dbSDimitry Andric       return GitPtrLo;
4925ffd83dbSDimitry Andric     }
4935ffd83dbSDimitry Andric   }
4945ffd83dbSDimitry Andric   return GitPtrLo;
4955ffd83dbSDimitry Andric }
4965ffd83dbSDimitry Andric 
4975ffd83dbSDimitry Andric static yaml::StringValue regToString(Register Reg,
4980b57cec5SDimitry Andric                                      const TargetRegisterInfo &TRI) {
4990b57cec5SDimitry Andric   yaml::StringValue Dest;
5000b57cec5SDimitry Andric   {
5010b57cec5SDimitry Andric     raw_string_ostream OS(Dest.Value);
5020b57cec5SDimitry Andric     OS << printReg(Reg, &TRI);
5030b57cec5SDimitry Andric   }
5040b57cec5SDimitry Andric   return Dest;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric static Optional<yaml::SIArgumentInfo>
5080b57cec5SDimitry Andric convertArgumentInfo(const AMDGPUFunctionArgInfo &ArgInfo,
5090b57cec5SDimitry Andric                     const TargetRegisterInfo &TRI) {
5100b57cec5SDimitry Andric   yaml::SIArgumentInfo AI;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   auto convertArg = [&](Optional<yaml::SIArgument> &A,
5130b57cec5SDimitry Andric                         const ArgDescriptor &Arg) {
5140b57cec5SDimitry Andric     if (!Arg)
5150b57cec5SDimitry Andric       return false;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric     // Create a register or stack argument.
5180b57cec5SDimitry Andric     yaml::SIArgument SA = yaml::SIArgument::createArgument(Arg.isRegister());
5190b57cec5SDimitry Andric     if (Arg.isRegister()) {
5200b57cec5SDimitry Andric       raw_string_ostream OS(SA.RegisterName.Value);
5210b57cec5SDimitry Andric       OS << printReg(Arg.getRegister(), &TRI);
5220b57cec5SDimitry Andric     } else
5230b57cec5SDimitry Andric       SA.StackOffset = Arg.getStackOffset();
5240b57cec5SDimitry Andric     // Check and update the optional mask.
5250b57cec5SDimitry Andric     if (Arg.isMasked())
5260b57cec5SDimitry Andric       SA.Mask = Arg.getMask();
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric     A = SA;
5290b57cec5SDimitry Andric     return true;
5300b57cec5SDimitry Andric   };
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   bool Any = false;
5330b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentBuffer, ArgInfo.PrivateSegmentBuffer);
5340b57cec5SDimitry Andric   Any |= convertArg(AI.DispatchPtr, ArgInfo.DispatchPtr);
5350b57cec5SDimitry Andric   Any |= convertArg(AI.QueuePtr, ArgInfo.QueuePtr);
5360b57cec5SDimitry Andric   Any |= convertArg(AI.KernargSegmentPtr, ArgInfo.KernargSegmentPtr);
5370b57cec5SDimitry Andric   Any |= convertArg(AI.DispatchID, ArgInfo.DispatchID);
5380b57cec5SDimitry Andric   Any |= convertArg(AI.FlatScratchInit, ArgInfo.FlatScratchInit);
5390b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentSize, ArgInfo.PrivateSegmentSize);
5400b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDX, ArgInfo.WorkGroupIDX);
5410b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDY, ArgInfo.WorkGroupIDY);
5420b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupIDZ, ArgInfo.WorkGroupIDZ);
5430b57cec5SDimitry Andric   Any |= convertArg(AI.WorkGroupInfo, ArgInfo.WorkGroupInfo);
5440b57cec5SDimitry Andric   Any |= convertArg(AI.PrivateSegmentWaveByteOffset,
5450b57cec5SDimitry Andric                     ArgInfo.PrivateSegmentWaveByteOffset);
5460b57cec5SDimitry Andric   Any |= convertArg(AI.ImplicitArgPtr, ArgInfo.ImplicitArgPtr);
5470b57cec5SDimitry Andric   Any |= convertArg(AI.ImplicitBufferPtr, ArgInfo.ImplicitBufferPtr);
5480b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDX, ArgInfo.WorkItemIDX);
5490b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDY, ArgInfo.WorkItemIDY);
5500b57cec5SDimitry Andric   Any |= convertArg(AI.WorkItemIDZ, ArgInfo.WorkItemIDZ);
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   if (Any)
5530b57cec5SDimitry Andric     return AI;
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   return None;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
559fe6060f1SDimitry Andric     const llvm::SIMachineFunctionInfo &MFI, const TargetRegisterInfo &TRI,
560fe6060f1SDimitry Andric     const llvm::MachineFunction &MF)
5610b57cec5SDimitry Andric     : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
562e8d8bef9SDimitry Andric       MaxKernArgAlign(MFI.getMaxKernArgAlign()), LDSSize(MFI.getLDSSize()),
563e8d8bef9SDimitry Andric       DynLDSAlign(MFI.getDynLDSAlign()), IsEntryFunction(MFI.isEntryFunction()),
5640b57cec5SDimitry Andric       NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
565e8d8bef9SDimitry Andric       MemoryBound(MFI.isMemoryBound()), WaveLimiter(MFI.needsWaveLimiter()),
566e8d8bef9SDimitry Andric       HasSpilledSGPRs(MFI.hasSpilledSGPRs()),
567e8d8bef9SDimitry Andric       HasSpilledVGPRs(MFI.hasSpilledVGPRs()),
5688bcb0991SDimitry Andric       HighBitsOf32BitAddress(MFI.get32BitAddressHighBits()),
569e8d8bef9SDimitry Andric       Occupancy(MFI.getOccupancy()),
5700b57cec5SDimitry Andric       ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
5710b57cec5SDimitry Andric       FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
5720b57cec5SDimitry Andric       StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)),
573e8d8bef9SDimitry Andric       ArgInfo(convertArgumentInfo(MFI.getArgInfo(), TRI)), Mode(MFI.getMode()) {
574fe6060f1SDimitry Andric   auto SFI = MFI.getOptionalScavengeFI();
575fe6060f1SDimitry Andric   if (SFI)
576fe6060f1SDimitry Andric     ScavengeFI = yaml::FrameIndex(*SFI, MF.getFrameInfo());
577e8d8bef9SDimitry Andric }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
5800b57cec5SDimitry Andric   MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric bool SIMachineFunctionInfo::initializeBaseYamlFields(
584fe6060f1SDimitry Andric     const yaml::SIMachineFunctionInfo &YamlMFI, const MachineFunction &MF,
585fe6060f1SDimitry Andric     PerFunctionMIParsingState &PFS, SMDiagnostic &Error, SMRange &SourceRange) {
5860b57cec5SDimitry Andric   ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
5878bcb0991SDimitry Andric   MaxKernArgAlign = assumeAligned(YamlMFI.MaxKernArgAlign);
5880b57cec5SDimitry Andric   LDSSize = YamlMFI.LDSSize;
589e8d8bef9SDimitry Andric   DynLDSAlign = YamlMFI.DynLDSAlign;
5908bcb0991SDimitry Andric   HighBitsOf32BitAddress = YamlMFI.HighBitsOf32BitAddress;
591e8d8bef9SDimitry Andric   Occupancy = YamlMFI.Occupancy;
5920b57cec5SDimitry Andric   IsEntryFunction = YamlMFI.IsEntryFunction;
5930b57cec5SDimitry Andric   NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
5940b57cec5SDimitry Andric   MemoryBound = YamlMFI.MemoryBound;
5950b57cec5SDimitry Andric   WaveLimiter = YamlMFI.WaveLimiter;
596e8d8bef9SDimitry Andric   HasSpilledSGPRs = YamlMFI.HasSpilledSGPRs;
597e8d8bef9SDimitry Andric   HasSpilledVGPRs = YamlMFI.HasSpilledVGPRs;
598fe6060f1SDimitry Andric 
599fe6060f1SDimitry Andric   if (YamlMFI.ScavengeFI) {
600fe6060f1SDimitry Andric     auto FIOrErr = YamlMFI.ScavengeFI->getFI(MF.getFrameInfo());
601fe6060f1SDimitry Andric     if (!FIOrErr) {
602fe6060f1SDimitry Andric       // Create a diagnostic for a the frame index.
603fe6060f1SDimitry Andric       const MemoryBuffer &Buffer =
604fe6060f1SDimitry Andric           *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
605fe6060f1SDimitry Andric 
606fe6060f1SDimitry Andric       Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1, 1,
607fe6060f1SDimitry Andric                            SourceMgr::DK_Error, toString(FIOrErr.takeError()),
608fe6060f1SDimitry Andric                            "", None, None);
609fe6060f1SDimitry Andric       SourceRange = YamlMFI.ScavengeFI->SourceRange;
610fe6060f1SDimitry Andric       return true;
611fe6060f1SDimitry Andric     }
612fe6060f1SDimitry Andric     ScavengeFI = *FIOrErr;
613fe6060f1SDimitry Andric   } else {
614fe6060f1SDimitry Andric     ScavengeFI = None;
615fe6060f1SDimitry Andric   }
6160b57cec5SDimitry Andric   return false;
6170b57cec5SDimitry Andric }
6185ffd83dbSDimitry Andric 
6195ffd83dbSDimitry Andric // Remove VGPR which was reserved for SGPR spills if there are no spilled SGPRs
6205ffd83dbSDimitry Andric bool SIMachineFunctionInfo::removeVGPRForSGPRSpill(Register ReservedVGPR,
6215ffd83dbSDimitry Andric                                                    MachineFunction &MF) {
6225ffd83dbSDimitry Andric   for (auto *i = SpillVGPRs.begin(); i < SpillVGPRs.end(); i++) {
6235ffd83dbSDimitry Andric     if (i->VGPR == ReservedVGPR) {
6245ffd83dbSDimitry Andric       SpillVGPRs.erase(i);
6255ffd83dbSDimitry Andric 
6265ffd83dbSDimitry Andric       for (MachineBasicBlock &MBB : MF) {
6275ffd83dbSDimitry Andric         MBB.removeLiveIn(ReservedVGPR);
6285ffd83dbSDimitry Andric         MBB.sortUniqueLiveIns();
6295ffd83dbSDimitry Andric       }
6305ffd83dbSDimitry Andric       this->VGPRReservedForSGPRSpill = AMDGPU::NoRegister;
6315ffd83dbSDimitry Andric       return true;
6325ffd83dbSDimitry Andric     }
6335ffd83dbSDimitry Andric   }
6345ffd83dbSDimitry Andric   return false;
6355ffd83dbSDimitry Andric }
636349cc55cSDimitry Andric 
637349cc55cSDimitry Andric bool SIMachineFunctionInfo::usesAGPRs(const MachineFunction &MF) const {
638349cc55cSDimitry Andric   if (UsesAGPRs)
639349cc55cSDimitry Andric     return *UsesAGPRs;
640349cc55cSDimitry Andric 
641349cc55cSDimitry Andric   if (!AMDGPU::isEntryFunctionCC(MF.getFunction().getCallingConv()) ||
642349cc55cSDimitry Andric       MF.getFrameInfo().hasCalls()) {
643349cc55cSDimitry Andric     UsesAGPRs = true;
644349cc55cSDimitry Andric     return true;
645349cc55cSDimitry Andric   }
646349cc55cSDimitry Andric 
647349cc55cSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
648349cc55cSDimitry Andric 
649349cc55cSDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
650349cc55cSDimitry Andric     const Register Reg = Register::index2VirtReg(I);
651349cc55cSDimitry Andric     const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
652349cc55cSDimitry Andric     if (RC && SIRegisterInfo::isAGPRClass(RC)) {
653349cc55cSDimitry Andric       UsesAGPRs = true;
654349cc55cSDimitry Andric       return true;
655349cc55cSDimitry Andric     } else if (!RC && !MRI.use_empty(Reg) && MRI.getType(Reg).isValid()) {
656349cc55cSDimitry Andric       // Defer caching UsesAGPRs, function might not yet been regbank selected.
657349cc55cSDimitry Andric       return true;
658349cc55cSDimitry Andric     }
659349cc55cSDimitry Andric   }
660349cc55cSDimitry Andric 
661349cc55cSDimitry Andric   for (MCRegister Reg : AMDGPU::AGPR_32RegClass) {
662349cc55cSDimitry Andric     if (MRI.isPhysRegUsed(Reg)) {
663349cc55cSDimitry Andric       UsesAGPRs = true;
664349cc55cSDimitry Andric       return true;
665349cc55cSDimitry Andric     }
666349cc55cSDimitry Andric   }
667349cc55cSDimitry Andric 
668349cc55cSDimitry Andric   UsesAGPRs = false;
669349cc55cSDimitry Andric   return false;
670349cc55cSDimitry Andric }
671