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