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