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*5f7ddb14SDimitry Andric #include "AMDGPUSubtarget.h"
12*5f7ddb14SDimitry Andric #include "SIRegisterInfo.h"
13*5f7ddb14SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
14*5f7ddb14SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
15*5f7ddb14SDimitry Andric #include "llvm/ADT/Optional.h"
16*5f7ddb14SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
17*5f7ddb14SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
18*5f7ddb14SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19*5f7ddb14SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
20*5f7ddb14SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21*5f7ddb14SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
22*5f7ddb14SDimitry Andric #include "llvm/IR/CallingConv.h"
23*5f7ddb14SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
24*5f7ddb14SDimitry Andric #include "llvm/IR/Function.h"
25*5f7ddb14SDimitry Andric #include <cassert>
26*5f7ddb14SDimitry Andric #include <vector>
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric #define MAX_LANES 64
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric
SIMachineFunctionInfo(const MachineFunction & MF)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*5f7ddb14SDimitry 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*5f7ddb14SDimitry Andric if (UseFixedABI)
82*5f7ddb14SDimitry Andric ArgInfo = AMDGPUArgumentUsageInfo::FixedABIFunctionInfo;
83*5f7ddb14SDimitry 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
88af732203SDimitry Andric if (!ST.enableFlatScratch()) {
89af732203SDimitry Andric // Non-entry functions have no special inputs for now, other registers
90af732203SDimitry Andric // required for scratch access.
91af732203SDimitry Andric ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
92af732203SDimitry Andric
930b57cec5SDimitry Andric ArgInfo.PrivateSegmentBuffer =
940b57cec5SDimitry Andric ArgDescriptor::createRegister(ScratchRSrcReg);
95af732203SDimitry 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*5f7ddb14SDimitry 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*5f7ddb14SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric bool isAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
1540b57cec5SDimitry Andric if (isAmdHsaOrMesa) {
155af732203SDimitry 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*5f7ddb14SDimitry Andric if (ST.hasFlatAddressSpace() && isEntryFunction() &&
185*5f7ddb14SDimitry Andric (isAmdHsaOrMesa || ST.enableFlatScratch()) &&
186*5f7ddb14SDimitry Andric (HasCalls || HasStackObjects || ST.enableFlatScratch()) &&
187*5f7ddb14SDimitry 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
limitOccupancy(const MachineFunction & MF)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
addPrivateSegmentBuffer(const SIRegisterInfo & TRI)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
addDispatchPtr(const SIRegisterInfo & TRI)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
addQueuePtr(const SIRegisterInfo & TRI)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
addKernargSegmentPtr(const SIRegisterInfo & TRI)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
addDispatchID(const SIRegisterInfo & TRI)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
addFlatScratchInit(const SIRegisterInfo & TRI)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
addImplicitBufferPtr(const SIRegisterInfo & TRI)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
isCalleeSavedReg(const MCPhysReg * CSRegs,MCPhysReg Reg)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
haveFreeLanesForSGPRSpill(const MachineFunction & MF,unsigned NumNeed) const2790b57cec5SDimitry 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.
allocateSGPRSpillToVGPR(MachineFunction & MF,int 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*5f7ddb14SDimitry Andric
334*5f7ddb14SDimitry Andric #if 0
335*5f7ddb14SDimitry Andric DiagnosticInfoResourceLimit DiagOutOfRegs(MF.getFunction(),
336*5f7ddb14SDimitry Andric "VGPRs for SGPR spilling",
337*5f7ddb14SDimitry Andric 0, DS_Error);
338*5f7ddb14SDimitry Andric MF.getFunction().getContext().diagnose(DiagOutOfRegs);
339*5f7ddb14SDimitry Andric #endif
3400b57cec5SDimitry Andric return false;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric
343*5f7ddb14SDimitry Andric Optional<int> SpillFI;
344*5f7ddb14SDimitry Andric // We need to preserve inactive lanes, so always save, even caller-save
345*5f7ddb14SDimitry Andric // registers.
346*5f7ddb14SDimitry Andric if (!isEntryFunction()) {
347*5f7ddb14SDimitry Andric SpillFI = FrameInfo.CreateSpillStackObject(4, Align(4));
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric
350*5f7ddb14SDimitry 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
reserveVGPRforSGPRSpills(MachineFunction & MF)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);
374af732203SDimitry Andric if (LaneVGPR == Register())
375af732203SDimitry Andric return false;
376*5f7ddb14SDimitry 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.
allocateVGPRSpillToAGPR(MachineFunction & MF,int FI,bool isAGPRtoVGPR)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
removeDeadFrameIndices(MachineFrameInfo & MFI)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
getScavengeFI(MachineFrameInfo & MFI,const SIRegisterInfo & TRI)469*5f7ddb14SDimitry Andric int SIMachineFunctionInfo::getScavengeFI(MachineFrameInfo &MFI,
470*5f7ddb14SDimitry Andric const SIRegisterInfo &TRI) {
471*5f7ddb14SDimitry Andric if (ScavengeFI)
472*5f7ddb14SDimitry Andric return *ScavengeFI;
473*5f7ddb14SDimitry Andric if (isEntryFunction()) {
474*5f7ddb14SDimitry Andric ScavengeFI = MFI.CreateFixedObject(
475*5f7ddb14SDimitry Andric TRI.getSpillSize(AMDGPU::SGPR_32RegClass), 0, false);
476*5f7ddb14SDimitry Andric } else {
477*5f7ddb14SDimitry Andric ScavengeFI = MFI.CreateStackObject(
478*5f7ddb14SDimitry Andric TRI.getSpillSize(AMDGPU::SGPR_32RegClass),
479*5f7ddb14SDimitry Andric TRI.getSpillAlign(AMDGPU::SGPR_32RegClass), false);
480*5f7ddb14SDimitry Andric }
481*5f7ddb14SDimitry Andric return *ScavengeFI;
482*5f7ddb14SDimitry Andric }
483*5f7ddb14SDimitry Andric
getNextUserSGPR() const4840b57cec5SDimitry 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
getNextSystemSGPR() const4890b57cec5SDimitry Andric MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
4900b57cec5SDimitry Andric return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric
4935ffd83dbSDimitry Andric Register
getGITPtrLoReg(const MachineFunction & MF) const4945ffd83dbSDimitry 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
regToString(Register Reg,const TargetRegisterInfo & TRI)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>
convertArgumentInfo(const AMDGPUFunctionArgInfo & ArgInfo,const TargetRegisterInfo & TRI)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
SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo & MFI,const TargetRegisterInfo & TRI,const llvm::MachineFunction & MF)5750b57cec5SDimitry Andric yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
576*5f7ddb14SDimitry Andric const llvm::SIMachineFunctionInfo &MFI, const TargetRegisterInfo &TRI,
577*5f7ddb14SDimitry Andric const llvm::MachineFunction &MF)
5780b57cec5SDimitry Andric : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
579af732203SDimitry Andric MaxKernArgAlign(MFI.getMaxKernArgAlign()), LDSSize(MFI.getLDSSize()),
580af732203SDimitry Andric DynLDSAlign(MFI.getDynLDSAlign()), IsEntryFunction(MFI.isEntryFunction()),
5810b57cec5SDimitry Andric NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
582af732203SDimitry Andric MemoryBound(MFI.isMemoryBound()), WaveLimiter(MFI.needsWaveLimiter()),
583af732203SDimitry Andric HasSpilledSGPRs(MFI.hasSpilledSGPRs()),
584af732203SDimitry Andric HasSpilledVGPRs(MFI.hasSpilledVGPRs()),
5858bcb0991SDimitry Andric HighBitsOf32BitAddress(MFI.get32BitAddressHighBits()),
586af732203SDimitry 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)),
590af732203SDimitry Andric ArgInfo(convertArgumentInfo(MFI.getArgInfo(), TRI)), Mode(MFI.getMode()) {
591*5f7ddb14SDimitry Andric auto SFI = MFI.getOptionalScavengeFI();
592*5f7ddb14SDimitry Andric if (SFI)
593*5f7ddb14SDimitry Andric ScavengeFI = yaml::FrameIndex(*SFI, MF.getFrameInfo());
594af732203SDimitry Andric }
5950b57cec5SDimitry Andric
mappingImpl(yaml::IO & YamlIO)5960b57cec5SDimitry Andric void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
5970b57cec5SDimitry Andric MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric
initializeBaseYamlFields(const yaml::SIMachineFunctionInfo & YamlMFI,const MachineFunction & MF,PerFunctionMIParsingState & PFS,SMDiagnostic & Error,SMRange & SourceRange)6000b57cec5SDimitry Andric bool SIMachineFunctionInfo::initializeBaseYamlFields(
601*5f7ddb14SDimitry Andric const yaml::SIMachineFunctionInfo &YamlMFI, const MachineFunction &MF,
602*5f7ddb14SDimitry Andric PerFunctionMIParsingState &PFS, SMDiagnostic &Error, SMRange &SourceRange) {
6030b57cec5SDimitry Andric ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
6048bcb0991SDimitry Andric MaxKernArgAlign = assumeAligned(YamlMFI.MaxKernArgAlign);
6050b57cec5SDimitry Andric LDSSize = YamlMFI.LDSSize;
606af732203SDimitry Andric DynLDSAlign = YamlMFI.DynLDSAlign;
6078bcb0991SDimitry Andric HighBitsOf32BitAddress = YamlMFI.HighBitsOf32BitAddress;
608af732203SDimitry Andric Occupancy = YamlMFI.Occupancy;
6090b57cec5SDimitry Andric IsEntryFunction = YamlMFI.IsEntryFunction;
6100b57cec5SDimitry Andric NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
6110b57cec5SDimitry Andric MemoryBound = YamlMFI.MemoryBound;
6120b57cec5SDimitry Andric WaveLimiter = YamlMFI.WaveLimiter;
613af732203SDimitry Andric HasSpilledSGPRs = YamlMFI.HasSpilledSGPRs;
614af732203SDimitry Andric HasSpilledVGPRs = YamlMFI.HasSpilledVGPRs;
615*5f7ddb14SDimitry Andric
616*5f7ddb14SDimitry Andric if (YamlMFI.ScavengeFI) {
617*5f7ddb14SDimitry Andric auto FIOrErr = YamlMFI.ScavengeFI->getFI(MF.getFrameInfo());
618*5f7ddb14SDimitry Andric if (!FIOrErr) {
619*5f7ddb14SDimitry Andric // Create a diagnostic for a the frame index.
620*5f7ddb14SDimitry Andric const MemoryBuffer &Buffer =
621*5f7ddb14SDimitry Andric *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
622*5f7ddb14SDimitry Andric
623*5f7ddb14SDimitry Andric Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1, 1,
624*5f7ddb14SDimitry Andric SourceMgr::DK_Error, toString(FIOrErr.takeError()),
625*5f7ddb14SDimitry Andric "", None, None);
626*5f7ddb14SDimitry Andric SourceRange = YamlMFI.ScavengeFI->SourceRange;
627*5f7ddb14SDimitry Andric return true;
628*5f7ddb14SDimitry Andric }
629*5f7ddb14SDimitry Andric ScavengeFI = *FIOrErr;
630*5f7ddb14SDimitry Andric } else {
631*5f7ddb14SDimitry Andric ScavengeFI = None;
632*5f7ddb14SDimitry 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
removeVGPRForSGPRSpill(Register ReservedVGPR,MachineFunction & MF)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