1235 lines · c
1//==- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface --*- C++ -*-==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H14#define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H15 16#include "AMDGPUArgumentUsageInfo.h"17#include "AMDGPUMachineFunction.h"18#include "AMDGPUTargetMachine.h"19#include "GCNSubtarget.h"20#include "MCTargetDesc/AMDGPUMCTargetDesc.h"21#include "SIInstrInfo.h"22#include "SIModeRegisterDefaults.h"23#include "llvm/ADT/SetVector.h"24#include "llvm/ADT/SmallVector.h"25#include "llvm/CodeGen/MIRYamlMapping.h"26#include "llvm/CodeGen/PseudoSourceValue.h"27#include "llvm/Support/raw_ostream.h"28#include <optional>29 30namespace llvm {31 32class MachineFrameInfo;33class MachineFunction;34class SIMachineFunctionInfo;35class SIRegisterInfo;36class TargetRegisterClass;37 38class AMDGPUPseudoSourceValue : public PseudoSourceValue {39public:40 enum AMDGPUPSVKind : unsigned {41 PSVImage = PseudoSourceValue::TargetCustom,42 GWSResource43 };44 45protected:46 AMDGPUPseudoSourceValue(unsigned Kind, const AMDGPUTargetMachine &TM)47 : PseudoSourceValue(Kind, TM) {}48 49public:50 bool isConstant(const MachineFrameInfo *) const override {51 // This should probably be true for most images, but we will start by being52 // conservative.53 return false;54 }55 56 bool isAliased(const MachineFrameInfo *) const override {57 return true;58 }59 60 bool mayAlias(const MachineFrameInfo *) const override {61 return true;62 }63};64 65class AMDGPUGWSResourcePseudoSourceValue final : public AMDGPUPseudoSourceValue {66public:67 explicit AMDGPUGWSResourcePseudoSourceValue(const AMDGPUTargetMachine &TM)68 : AMDGPUPseudoSourceValue(GWSResource, TM) {}69 70 static bool classof(const PseudoSourceValue *V) {71 return V->kind() == GWSResource;72 }73 74 // These are inaccessible memory from IR.75 bool isAliased(const MachineFrameInfo *) const override {76 return false;77 }78 79 // These are inaccessible memory from IR.80 bool mayAlias(const MachineFrameInfo *) const override {81 return false;82 }83 84 void printCustom(raw_ostream &OS) const override {85 OS << "GWSResource";86 }87};88 89namespace yaml {90 91struct SIArgument {92 bool IsRegister;93 union {94 StringValue RegisterName;95 unsigned StackOffset;96 };97 std::optional<unsigned> Mask;98 99 // Default constructor, which creates a stack argument.100 SIArgument() : IsRegister(false), StackOffset(0) {}101 SIArgument(const SIArgument &Other) {102 IsRegister = Other.IsRegister;103 if (IsRegister)104 new (&RegisterName) StringValue(Other.RegisterName);105 else106 StackOffset = Other.StackOffset;107 Mask = Other.Mask;108 }109 SIArgument &operator=(const SIArgument &Other) {110 // Default-construct or destruct the old RegisterName in case of switching111 // union members112 if (IsRegister != Other.IsRegister) {113 if (Other.IsRegister)114 new (&RegisterName) StringValue();115 else116 RegisterName.~StringValue();117 }118 IsRegister = Other.IsRegister;119 if (IsRegister)120 RegisterName = Other.RegisterName;121 else122 StackOffset = Other.StackOffset;123 Mask = Other.Mask;124 return *this;125 }126 ~SIArgument() {127 if (IsRegister)128 RegisterName.~StringValue();129 }130 131 // Helper to create a register or stack argument.132 static inline SIArgument createArgument(bool IsReg) {133 if (IsReg)134 return SIArgument(IsReg);135 return SIArgument();136 }137 138private:139 // Construct a register argument.140 SIArgument(bool) : IsRegister(true), RegisterName() {}141};142 143template <> struct MappingTraits<SIArgument> {144 static void mapping(IO &YamlIO, SIArgument &A) {145 if (YamlIO.outputting()) {146 if (A.IsRegister)147 YamlIO.mapRequired("reg", A.RegisterName);148 else149 YamlIO.mapRequired("offset", A.StackOffset);150 } else {151 auto Keys = YamlIO.keys();152 if (is_contained(Keys, "reg")) {153 A = SIArgument::createArgument(true);154 YamlIO.mapRequired("reg", A.RegisterName);155 } else if (is_contained(Keys, "offset"))156 YamlIO.mapRequired("offset", A.StackOffset);157 else158 YamlIO.setError("missing required key 'reg' or 'offset'");159 }160 YamlIO.mapOptional("mask", A.Mask);161 }162 static const bool flow = true;163};164 165struct SIArgumentInfo {166 std::optional<SIArgument> PrivateSegmentBuffer;167 std::optional<SIArgument> DispatchPtr;168 std::optional<SIArgument> QueuePtr;169 std::optional<SIArgument> KernargSegmentPtr;170 std::optional<SIArgument> DispatchID;171 std::optional<SIArgument> FlatScratchInit;172 std::optional<SIArgument> PrivateSegmentSize;173 std::optional<SIArgument> FirstKernArgPreloadReg;174 175 std::optional<SIArgument> WorkGroupIDX;176 std::optional<SIArgument> WorkGroupIDY;177 std::optional<SIArgument> WorkGroupIDZ;178 std::optional<SIArgument> WorkGroupInfo;179 std::optional<SIArgument> LDSKernelId;180 std::optional<SIArgument> PrivateSegmentWaveByteOffset;181 182 std::optional<SIArgument> ImplicitArgPtr;183 std::optional<SIArgument> ImplicitBufferPtr;184 185 std::optional<SIArgument> WorkItemIDX;186 std::optional<SIArgument> WorkItemIDY;187 std::optional<SIArgument> WorkItemIDZ;188};189 190template <> struct MappingTraits<SIArgumentInfo> {191 static void mapping(IO &YamlIO, SIArgumentInfo &AI) {192 YamlIO.mapOptional("privateSegmentBuffer", AI.PrivateSegmentBuffer);193 YamlIO.mapOptional("dispatchPtr", AI.DispatchPtr);194 YamlIO.mapOptional("queuePtr", AI.QueuePtr);195 YamlIO.mapOptional("kernargSegmentPtr", AI.KernargSegmentPtr);196 YamlIO.mapOptional("dispatchID", AI.DispatchID);197 YamlIO.mapOptional("flatScratchInit", AI.FlatScratchInit);198 YamlIO.mapOptional("privateSegmentSize", AI.PrivateSegmentSize);199 YamlIO.mapOptional("firstKernArgPreloadReg", AI.FirstKernArgPreloadReg);200 201 YamlIO.mapOptional("workGroupIDX", AI.WorkGroupIDX);202 YamlIO.mapOptional("workGroupIDY", AI.WorkGroupIDY);203 YamlIO.mapOptional("workGroupIDZ", AI.WorkGroupIDZ);204 YamlIO.mapOptional("workGroupInfo", AI.WorkGroupInfo);205 YamlIO.mapOptional("LDSKernelId", AI.LDSKernelId);206 YamlIO.mapOptional("privateSegmentWaveByteOffset",207 AI.PrivateSegmentWaveByteOffset);208 209 YamlIO.mapOptional("implicitArgPtr", AI.ImplicitArgPtr);210 YamlIO.mapOptional("implicitBufferPtr", AI.ImplicitBufferPtr);211 212 YamlIO.mapOptional("workItemIDX", AI.WorkItemIDX);213 YamlIO.mapOptional("workItemIDY", AI.WorkItemIDY);214 YamlIO.mapOptional("workItemIDZ", AI.WorkItemIDZ);215 }216};217 218// Default to default mode for default calling convention.219struct SIMode {220 bool IEEE = true;221 bool DX10Clamp = true;222 bool FP32InputDenormals = true;223 bool FP32OutputDenormals = true;224 bool FP64FP16InputDenormals = true;225 bool FP64FP16OutputDenormals = true;226 227 SIMode() = default;228 229 SIMode(const SIModeRegisterDefaults &Mode) {230 IEEE = Mode.IEEE;231 DX10Clamp = Mode.DX10Clamp;232 FP32InputDenormals = Mode.FP32Denormals.Input != DenormalMode::PreserveSign;233 FP32OutputDenormals =234 Mode.FP32Denormals.Output != DenormalMode::PreserveSign;235 FP64FP16InputDenormals =236 Mode.FP64FP16Denormals.Input != DenormalMode::PreserveSign;237 FP64FP16OutputDenormals =238 Mode.FP64FP16Denormals.Output != DenormalMode::PreserveSign;239 }240 241 bool operator ==(const SIMode Other) const {242 return IEEE == Other.IEEE &&243 DX10Clamp == Other.DX10Clamp &&244 FP32InputDenormals == Other.FP32InputDenormals &&245 FP32OutputDenormals == Other.FP32OutputDenormals &&246 FP64FP16InputDenormals == Other.FP64FP16InputDenormals &&247 FP64FP16OutputDenormals == Other.FP64FP16OutputDenormals;248 }249};250 251template <> struct MappingTraits<SIMode> {252 static void mapping(IO &YamlIO, SIMode &Mode) {253 YamlIO.mapOptional("ieee", Mode.IEEE, true);254 YamlIO.mapOptional("dx10-clamp", Mode.DX10Clamp, true);255 YamlIO.mapOptional("fp32-input-denormals", Mode.FP32InputDenormals, true);256 YamlIO.mapOptional("fp32-output-denormals", Mode.FP32OutputDenormals, true);257 YamlIO.mapOptional("fp64-fp16-input-denormals", Mode.FP64FP16InputDenormals, true);258 YamlIO.mapOptional("fp64-fp16-output-denormals", Mode.FP64FP16OutputDenormals, true);259 }260};261 262struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo {263 uint64_t ExplicitKernArgSize = 0;264 Align MaxKernArgAlign;265 uint32_t LDSSize = 0;266 uint32_t GDSSize = 0;267 Align DynLDSAlign;268 bool IsEntryFunction = false;269 bool IsChainFunction = false;270 bool NoSignedZerosFPMath = false;271 bool MemoryBound = false;272 bool WaveLimiter = false;273 bool HasSpilledSGPRs = false;274 bool HasSpilledVGPRs = false;275 uint16_t NumWaveDispatchSGPRs = 0;276 uint16_t NumWaveDispatchVGPRs = 0;277 uint32_t HighBitsOf32BitAddress = 0;278 279 // TODO: 10 may be a better default since it's the maximum.280 unsigned Occupancy = 0;281 282 SmallVector<StringValue, 2> SpillPhysVGPRS;283 SmallVector<StringValue> WWMReservedRegs;284 285 StringValue ScratchRSrcReg = "$private_rsrc_reg";286 StringValue FrameOffsetReg = "$fp_reg";287 StringValue StackPtrOffsetReg = "$sp_reg";288 289 unsigned BytesInStackArgArea = 0;290 bool ReturnsVoid = true;291 292 std::optional<SIArgumentInfo> ArgInfo;293 294 unsigned PSInputAddr = 0;295 unsigned PSInputEnable = 0;296 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;297 298 SIMode Mode;299 std::optional<FrameIndex> ScavengeFI;300 StringValue VGPRForAGPRCopy;301 StringValue SGPRForEXECCopy;302 StringValue LongBranchReservedReg;303 304 bool HasInitWholeWave = false;305 bool IsWholeWaveFunction = false;306 307 unsigned DynamicVGPRBlockSize = 0;308 unsigned ScratchReservedForDynamicVGPRs = 0;309 310 unsigned NumKernargPreloadSGPRs = 0;311 312 SIMachineFunctionInfo() = default;313 SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &,314 const TargetRegisterInfo &TRI,315 const llvm::MachineFunction &MF);316 317 void mappingImpl(yaml::IO &YamlIO) override;318 ~SIMachineFunctionInfo() override = default;319};320 321template <> struct MappingTraits<SIMachineFunctionInfo> {322 static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) {323 YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize,324 UINT64_C(0));325 YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign);326 YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u);327 YamlIO.mapOptional("gdsSize", MFI.GDSSize, 0u);328 YamlIO.mapOptional("dynLDSAlign", MFI.DynLDSAlign, Align());329 YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false);330 YamlIO.mapOptional("isChainFunction", MFI.IsChainFunction, false);331 YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false);332 YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false);333 YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false);334 YamlIO.mapOptional("hasSpilledSGPRs", MFI.HasSpilledSGPRs, false);335 YamlIO.mapOptional("hasSpilledVGPRs", MFI.HasSpilledVGPRs, false);336 YamlIO.mapOptional("numWaveDispatchSGPRs", MFI.NumWaveDispatchSGPRs, false);337 YamlIO.mapOptional("numWaveDispatchVGPRs", MFI.NumWaveDispatchVGPRs, false);338 YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg,339 StringValue("$private_rsrc_reg"));340 YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg,341 StringValue("$fp_reg"));342 YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg,343 StringValue("$sp_reg"));344 YamlIO.mapOptional("bytesInStackArgArea", MFI.BytesInStackArgArea, 0u);345 YamlIO.mapOptional("returnsVoid", MFI.ReturnsVoid, true);346 YamlIO.mapOptional("argumentInfo", MFI.ArgInfo);347 YamlIO.mapOptional("psInputAddr", MFI.PSInputAddr, 0u);348 YamlIO.mapOptional("psInputEnable", MFI.PSInputEnable, 0u);349 YamlIO.mapOptional("maxMemoryClusterDWords", MFI.MaxMemoryClusterDWords,350 DefaultMemoryClusterDWordsLimit);351 YamlIO.mapOptional("mode", MFI.Mode, SIMode());352 YamlIO.mapOptional("highBitsOf32BitAddress",353 MFI.HighBitsOf32BitAddress, 0u);354 YamlIO.mapOptional("occupancy", MFI.Occupancy, 0);355 YamlIO.mapOptional("spillPhysVGPRs", MFI.SpillPhysVGPRS);356 YamlIO.mapOptional("wwmReservedRegs", MFI.WWMReservedRegs);357 YamlIO.mapOptional("scavengeFI", MFI.ScavengeFI);358 YamlIO.mapOptional("vgprForAGPRCopy", MFI.VGPRForAGPRCopy,359 StringValue()); // Don't print out when it's empty.360 YamlIO.mapOptional("sgprForEXECCopy", MFI.SGPRForEXECCopy,361 StringValue()); // Don't print out when it's empty.362 YamlIO.mapOptional("longBranchReservedReg", MFI.LongBranchReservedReg,363 StringValue());364 YamlIO.mapOptional("hasInitWholeWave", MFI.HasInitWholeWave, false);365 YamlIO.mapOptional("dynamicVGPRBlockSize", MFI.DynamicVGPRBlockSize, false);366 YamlIO.mapOptional("scratchReservedForDynamicVGPRs",367 MFI.ScratchReservedForDynamicVGPRs, 0);368 YamlIO.mapOptional("numKernargPreloadSGPRs", MFI.NumKernargPreloadSGPRs, 0);369 YamlIO.mapOptional("isWholeWaveFunction", MFI.IsWholeWaveFunction, false);370 }371};372 373} // end namespace yaml374 375// A CSR SGPR value can be preserved inside a callee using one of the following376// methods.377// 1. Copy to an unused scratch SGPR.378// 2. Spill to a VGPR lane.379// 3. Spill to memory via. a scratch VGPR.380// class PrologEpilogSGPRSaveRestoreInfo represents the save/restore method used381// for an SGPR at function prolog/epilog.382enum class SGPRSaveKind : uint8_t {383 COPY_TO_SCRATCH_SGPR,384 SPILL_TO_VGPR_LANE,385 SPILL_TO_MEM386};387 388class PrologEpilogSGPRSaveRestoreInfo {389 SGPRSaveKind Kind;390 union {391 int Index;392 Register Reg;393 };394 395public:396 PrologEpilogSGPRSaveRestoreInfo(SGPRSaveKind K, int I) : Kind(K), Index(I) {}397 PrologEpilogSGPRSaveRestoreInfo(SGPRSaveKind K, Register R)398 : Kind(K), Reg(R) {}399 Register getReg() const { return Reg; }400 int getIndex() const { return Index; }401 SGPRSaveKind getKind() const { return Kind; }402};403 404struct VGPRBlock2IndexFunctor {405 using argument_type = Register;406 unsigned operator()(Register Reg) const {407 assert(AMDGPU::VReg_1024RegClass.contains(Reg) && "Expecting a VGPR block");408 409 const MCRegister FirstVGPRBlock = AMDGPU::VReg_1024RegClass.getRegister(0);410 return Reg - FirstVGPRBlock;411 }412};413 414/// This class keeps track of the SPI_SP_INPUT_ADDR config register, which415/// tells the hardware which interpolation parameters to load.416class SIMachineFunctionInfo final : public AMDGPUMachineFunction,417 private MachineRegisterInfo::Delegate {418 friend class GCNTargetMachine;419 420 // State of MODE register, assumed FP mode.421 SIModeRegisterDefaults Mode;422 423 // Registers that may be reserved for spilling purposes. These may be the same424 // as the input registers.425 Register ScratchRSrcReg = AMDGPU::PRIVATE_RSRC_REG;426 427 // This is the unswizzled offset from the current dispatch's scratch wave428 // base to the beginning of the current function's frame.429 Register FrameOffsetReg = AMDGPU::FP_REG;430 431 // This is an ABI register used in the non-entry calling convention to432 // communicate the unswizzled offset from the current dispatch's scratch wave433 // base to the beginning of the new function's frame.434 Register StackPtrOffsetReg = AMDGPU::SP_REG;435 436 // Registers that may be reserved when RA doesn't allocate enough437 // registers to plan for the case where an indirect branch ends up438 // being needed during branch relaxation.439 Register LongBranchReservedReg;440 441 AMDGPUFunctionArgInfo ArgInfo;442 443 // Graphics info.444 unsigned PSInputAddr = 0;445 unsigned PSInputEnable = 0;446 447 /// Number of bytes of arguments this function has on the stack. If the callee448 /// is expected to restore the argument stack this should be a multiple of 16,449 /// all usable during a tail call.450 ///451 /// The alternative would forbid tail call optimisation in some cases: if we452 /// want to transfer control from a function with 8-bytes of stack-argument453 /// space to a function with 16-bytes then misalignment of this value would454 /// make a stack adjustment necessary, which could not be undone by the455 /// callee.456 unsigned BytesInStackArgArea = 0;457 458 bool ReturnsVoid = true;459 460 // A pair of default/requested minimum/maximum flat work group sizes.461 // Minimum - first, maximum - second.462 std::pair<unsigned, unsigned> FlatWorkGroupSizes = {0, 0};463 464 // A pair of default/requested minimum/maximum number of waves per execution465 // unit. Minimum - first, maximum - second.466 std::pair<unsigned, unsigned> WavesPerEU = {0, 0};467 468 const AMDGPUGWSResourcePseudoSourceValue GWSResourcePSV;469 470 // Default/requested number of work groups for the function.471 SmallVector<unsigned> MaxNumWorkGroups = {0, 0, 0};472 473 // Requested cluster dimensions.474 AMDGPU::ClusterDimsAttr ClusterDims;475 476private:477 unsigned NumUserSGPRs = 0;478 unsigned NumSystemSGPRs = 0;479 480 unsigned NumWaveDispatchSGPRs = 0;481 unsigned NumWaveDispatchVGPRs = 0;482 483 bool HasSpilledSGPRs = false;484 bool HasSpilledVGPRs = false;485 bool HasNonSpillStackObjects = false;486 bool IsStackRealigned = false;487 488 unsigned NumSpilledSGPRs = 0;489 unsigned NumSpilledVGPRs = 0;490 491 unsigned DynamicVGPRBlockSize = 0;492 493 // The size in bytes of the scratch space reserved for the CWSR trap handler494 // to spill some of the dynamic VGPRs.495 unsigned ScratchReservedForDynamicVGPRs = 0;496 497 // Tracks information about user SGPRs that will be setup by hardware which498 // will apply to all wavefronts of the grid.499 GCNUserSGPRUsageInfo UserSGPRInfo;500 501 // Feature bits required for inputs passed in system SGPRs.502 bool WorkGroupIDX : 1; // Always initialized.503 bool WorkGroupIDY : 1;504 bool WorkGroupIDZ : 1;505 bool WorkGroupInfo : 1;506 bool LDSKernelId : 1;507 bool PrivateSegmentWaveByteOffset : 1;508 509 bool WorkItemIDX : 1; // Always initialized.510 bool WorkItemIDY : 1;511 bool WorkItemIDZ : 1;512 513 // Pointer to where the ABI inserts special kernel arguments separate from the514 // user arguments. This is an offset from the KernargSegmentPtr.515 bool ImplicitArgPtr : 1;516 517 /// Minimum number of AGPRs required to allocate in the function. Only518 /// relevant for gfx90a-gfx950. For gfx908, this should be infinite.519 unsigned MinNumAGPRs = ~0u;520 521 // The hard-wired high half of the address of the global information table522 // for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since523 // current hardware only allows a 16 bit value.524 unsigned GITPtrHigh;525 526 unsigned HighBitsOf32BitAddress;527 528 // Flags associated with the virtual registers.529 IndexedMap<uint8_t, VirtReg2IndexFunctor> VRegFlags;530 531 // Current recorded maximum possible occupancy.532 unsigned Occupancy;533 534 // Maximum number of dwords that can be clusterred during instruction535 // scheduler stage.536 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;537 538 MCPhysReg getNextUserSGPR() const;539 540 MCPhysReg getNextSystemSGPR() const;541 542 // MachineRegisterInfo callback functions to notify events.543 void MRI_NoteNewVirtualRegister(Register Reg) override;544 void MRI_NoteCloneVirtualRegister(Register NewReg, Register SrcReg) override;545 546public:547 static bool MFMAVGPRForm;548 549 struct VGPRSpillToAGPR {550 SmallVector<MCPhysReg, 32> Lanes;551 bool FullyAllocated = false;552 bool IsDead = false;553 };554 555private:556 // To track virtual VGPR + lane index for each subregister of the SGPR spilled557 // to frameindex key during SILowerSGPRSpills pass.558 DenseMap<int, std::vector<SIRegisterInfo::SpilledReg>>559 SGPRSpillsToVirtualVGPRLanes;560 // To track physical VGPR + lane index for CSR SGPR spills and special SGPRs561 // like Frame Pointer identified during PrologEpilogInserter.562 DenseMap<int, std::vector<SIRegisterInfo::SpilledReg>>563 SGPRSpillsToPhysicalVGPRLanes;564 unsigned NumVirtualVGPRSpillLanes = 0;565 unsigned NumPhysicalVGPRSpillLanes = 0;566 SmallVector<Register, 2> SpillVGPRs;567 SmallVector<Register, 2> SpillPhysVGPRs;568 using WWMSpillsMap = MapVector<Register, int>;569 // To track the registers used in instructions that can potentially modify the570 // inactive lanes. The WWM instructions and the writelane instructions for571 // spilling SGPRs to VGPRs fall under such category of operations. The VGPRs572 // modified by them should be spilled/restored at function prolog/epilog to573 // avoid any undesired outcome. Each entry in this map holds a pair of values,574 // the VGPR and its stack slot index.575 WWMSpillsMap WWMSpills;576 577 // Before allocation, the VGPR registers are partitioned into two distinct578 // sets, the first one for WWM-values and the second set for non-WWM values.579 // The latter set should be reserved during WWM-regalloc.580 BitVector NonWWMRegMask;581 582 using ReservedRegSet = SmallSetVector<Register, 8>;583 // To track the VGPRs reserved for WWM instructions. They get stack slots584 // later during PrologEpilogInserter and get added into the superset WWMSpills585 // for actual spilling. A separate set makes the register reserved part and586 // the serialization easier.587 ReservedRegSet WWMReservedRegs;588 589 bool IsWholeWaveFunction = false;590 591 using PrologEpilogSGPRSpill =592 std::pair<Register, PrologEpilogSGPRSaveRestoreInfo>;593 // To track the SGPR spill method used for a CSR SGPR register during594 // frame lowering. Even though the SGPR spills are handled during595 // SILowerSGPRSpills pass, some special handling needed later during the596 // PrologEpilogInserter.597 SmallVector<PrologEpilogSGPRSpill, 3> PrologEpilogSGPRSpills;598 599 // To save/restore EXEC MASK around WWM spills and copies.600 Register SGPRForEXECCopy;601 602 DenseMap<int, VGPRSpillToAGPR> VGPRToAGPRSpills;603 604 // AGPRs used for VGPR spills.605 SmallVector<MCPhysReg, 32> SpillAGPR;606 607 // VGPRs used for AGPR spills.608 SmallVector<MCPhysReg, 32> SpillVGPR;609 610 // Emergency stack slot. Sometimes, we create this before finalizing the stack611 // frame, so save it here and add it to the RegScavenger later.612 std::optional<int> ScavengeFI;613 614 // Map each VGPR CSR to the mask needed to save and restore it using block615 // load/store instructions. Only used if the subtarget feature for VGPR block616 // load/store is enabled.617 IndexedMap<uint32_t, VGPRBlock2IndexFunctor> MaskForVGPRBlockOps;618 619private:620 Register VGPRForAGPRCopy;621 622 bool allocateVirtualVGPRForSGPRSpills(MachineFunction &MF, int FI,623 unsigned LaneIndex);624 bool allocatePhysicalVGPRForSGPRSpills(MachineFunction &MF, int FI,625 unsigned LaneIndex,626 bool IsPrologEpilog);627 628public:629 Register getVGPRForAGPRCopy() const {630 return VGPRForAGPRCopy;631 }632 633 void setVGPRForAGPRCopy(Register NewVGPRForAGPRCopy) {634 VGPRForAGPRCopy = NewVGPRForAGPRCopy;635 }636 637 bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg) const;638 639 void setMaskForVGPRBlockOps(Register RegisterBlock, uint32_t Mask) {640 MaskForVGPRBlockOps.grow(RegisterBlock);641 MaskForVGPRBlockOps[RegisterBlock] = Mask;642 }643 644 uint32_t getMaskForVGPRBlockOps(Register RegisterBlock) const {645 return MaskForVGPRBlockOps[RegisterBlock];646 }647 648 bool hasMaskForVGPRBlockOps(Register RegisterBlock) const {649 return MaskForVGPRBlockOps.inBounds(RegisterBlock);650 }651 652public:653 SIMachineFunctionInfo(const SIMachineFunctionInfo &MFI) = default;654 SIMachineFunctionInfo(const Function &F, const GCNSubtarget *STI);655 656 MachineFunctionInfo *657 clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,658 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)659 const override;660 661 bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI,662 const MachineFunction &MF,663 PerFunctionMIParsingState &PFS,664 SMDiagnostic &Error, SMRange &SourceRange);665 666 void reserveWWMRegister(Register Reg) { WWMReservedRegs.insert(Reg); }667 bool isWWMReg(Register Reg) const {668 return Reg.isVirtual() ? checkFlag(Reg, AMDGPU::VirtRegFlag::WWM_REG)669 : WWMReservedRegs.contains(Reg);670 }671 672 void updateNonWWMRegMask(BitVector &RegMask) { NonWWMRegMask = RegMask; }673 BitVector getNonWWMRegMask() const { return NonWWMRegMask; }674 void clearNonWWMRegAllocMask() { NonWWMRegMask.clear(); }675 676 SIModeRegisterDefaults getMode() const { return Mode; }677 678 ArrayRef<SIRegisterInfo::SpilledReg>679 getSGPRSpillToVirtualVGPRLanes(int FrameIndex) const {680 auto I = SGPRSpillsToVirtualVGPRLanes.find(FrameIndex);681 return (I == SGPRSpillsToVirtualVGPRLanes.end())682 ? ArrayRef<SIRegisterInfo::SpilledReg>()683 : ArrayRef(I->second);684 }685 686 ArrayRef<Register> getSGPRSpillVGPRs() const { return SpillVGPRs; }687 ArrayRef<Register> getSGPRSpillPhysVGPRs() const { return SpillPhysVGPRs; }688 689 const WWMSpillsMap &getWWMSpills() const { return WWMSpills; }690 const ReservedRegSet &getWWMReservedRegs() const { return WWMReservedRegs; }691 692 bool isWWMReservedRegister(Register Reg) const {693 return WWMReservedRegs.contains(Reg);694 }695 696 bool isWholeWaveFunction() const { return IsWholeWaveFunction; }697 698 ArrayRef<PrologEpilogSGPRSpill> getPrologEpilogSGPRSpills() const {699 assert(is_sorted(PrologEpilogSGPRSpills, llvm::less_first()));700 return PrologEpilogSGPRSpills;701 }702 703 GCNUserSGPRUsageInfo &getUserSGPRInfo() { return UserSGPRInfo; }704 705 const GCNUserSGPRUsageInfo &getUserSGPRInfo() const { return UserSGPRInfo; }706 707 void addToPrologEpilogSGPRSpills(Register Reg,708 PrologEpilogSGPRSaveRestoreInfo SI) {709 assert(!hasPrologEpilogSGPRSpillEntry(Reg));710 711 // Insert a new entry in the right place to keep the vector in sorted order.712 // This should be cheap since the vector is expected to be very short.713 PrologEpilogSGPRSpills.insert(714 upper_bound(715 PrologEpilogSGPRSpills, Reg,716 [](const auto &LHS, const auto &RHS) { return LHS < RHS.first; }),717 std::make_pair(Reg, SI));718 }719 720 // Check if an entry created for \p Reg in PrologEpilogSGPRSpills. Return true721 // on success and false otherwise.722 bool hasPrologEpilogSGPRSpillEntry(Register Reg) const {723 const auto *I = find_if(PrologEpilogSGPRSpills, [&Reg](const auto &Spill) {724 return Spill.first == Reg;725 });726 return I != PrologEpilogSGPRSpills.end();727 }728 729 // Get the scratch SGPR if allocated to save/restore \p Reg.730 Register getScratchSGPRCopyDstReg(Register Reg) const {731 const auto *I = find_if(PrologEpilogSGPRSpills, [&Reg](const auto &Spill) {732 return Spill.first == Reg;733 });734 if (I != PrologEpilogSGPRSpills.end() &&735 I->second.getKind() == SGPRSaveKind::COPY_TO_SCRATCH_SGPR)736 return I->second.getReg();737 738 return AMDGPU::NoRegister;739 }740 741 // Get all scratch SGPRs allocated to copy/restore the SGPR spills.742 void getAllScratchSGPRCopyDstRegs(SmallVectorImpl<Register> &Regs) const {743 for (const auto &SI : PrologEpilogSGPRSpills) {744 if (SI.second.getKind() == SGPRSaveKind::COPY_TO_SCRATCH_SGPR)745 Regs.push_back(SI.second.getReg());746 }747 }748 749 // Check if \p FI is allocated for any SGPR spill to a VGPR lane during PEI.750 bool checkIndexInPrologEpilogSGPRSpills(int FI) const {751 return find_if(PrologEpilogSGPRSpills,752 [FI](const std::pair<Register,753 PrologEpilogSGPRSaveRestoreInfo> &SI) {754 return SI.second.getKind() ==755 SGPRSaveKind::SPILL_TO_VGPR_LANE &&756 SI.second.getIndex() == FI;757 }) != PrologEpilogSGPRSpills.end();758 }759 760 const PrologEpilogSGPRSaveRestoreInfo &761 getPrologEpilogSGPRSaveRestoreInfo(Register Reg) const {762 const auto *I = find_if(PrologEpilogSGPRSpills, [&Reg](const auto &Spill) {763 return Spill.first == Reg;764 });765 assert(I != PrologEpilogSGPRSpills.end());766 767 return I->second;768 }769 770 ArrayRef<SIRegisterInfo::SpilledReg>771 getSGPRSpillToPhysicalVGPRLanes(int FrameIndex) const {772 auto I = SGPRSpillsToPhysicalVGPRLanes.find(FrameIndex);773 return (I == SGPRSpillsToPhysicalVGPRLanes.end())774 ? ArrayRef<SIRegisterInfo::SpilledReg>()775 : ArrayRef(I->second);776 }777 778 void setFlag(Register Reg, uint8_t Flag) {779 assert(Reg.isVirtual());780 if (VRegFlags.inBounds(Reg))781 VRegFlags[Reg] |= Flag;782 }783 784 bool checkFlag(Register Reg, uint8_t Flag) const {785 if (Reg.isPhysical())786 return false;787 788 return VRegFlags.inBounds(Reg) && VRegFlags[Reg] & Flag;789 }790 791 bool hasVRegFlags() { return VRegFlags.size(); }792 793 void allocateWWMSpill(MachineFunction &MF, Register VGPR, uint64_t Size = 4,794 Align Alignment = Align(4));795 796 void splitWWMSpillRegisters(797 MachineFunction &MF,798 SmallVectorImpl<std::pair<Register, int>> &CalleeSavedRegs,799 SmallVectorImpl<std::pair<Register, int>> &ScratchRegs) const;800 801 ArrayRef<MCPhysReg> getAGPRSpillVGPRs() const {802 return SpillAGPR;803 }804 805 Register getSGPRForEXECCopy() const { return SGPRForEXECCopy; }806 807 void setSGPRForEXECCopy(Register Reg) { SGPRForEXECCopy = Reg; }808 809 ArrayRef<MCPhysReg> getVGPRSpillAGPRs() const {810 return SpillVGPR;811 }812 813 MCPhysReg getVGPRToAGPRSpill(int FrameIndex, unsigned Lane) const {814 auto I = VGPRToAGPRSpills.find(FrameIndex);815 return (I == VGPRToAGPRSpills.end()) ? (MCPhysReg)AMDGPU::NoRegister816 : I->second.Lanes[Lane];817 }818 819 void setVGPRToAGPRSpillDead(int FrameIndex) {820 auto I = VGPRToAGPRSpills.find(FrameIndex);821 if (I != VGPRToAGPRSpills.end())822 I->second.IsDead = true;823 }824 825 // To bring the allocated WWM registers in \p WWMVGPRs to the lowest available826 // range.827 void shiftWwmVGPRsToLowestRange(MachineFunction &MF,828 SmallVectorImpl<Register> &WWMVGPRs,829 BitVector &SavedVGPRs);830 831 bool allocateSGPRSpillToVGPRLane(MachineFunction &MF, int FI,832 bool SpillToPhysVGPRLane = false,833 bool IsPrologEpilog = false);834 bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR);835 836 /// If \p ResetSGPRSpillStackIDs is true, reset the stack ID from sgpr-spill837 /// to the default stack.838 bool removeDeadFrameIndices(MachineFrameInfo &MFI,839 bool ResetSGPRSpillStackIDs);840 841 int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI);842 std::optional<int> getOptionalScavengeFI() const { return ScavengeFI; }843 844 unsigned getBytesInStackArgArea() const {845 return BytesInStackArgArea;846 }847 848 void setBytesInStackArgArea(unsigned Bytes) {849 BytesInStackArgArea = Bytes;850 }851 852 bool isDynamicVGPREnabled() const { return DynamicVGPRBlockSize != 0; }853 unsigned getDynamicVGPRBlockSize() const { return DynamicVGPRBlockSize; }854 855 // This is only used if we need to save any dynamic VGPRs in scratch.856 unsigned getScratchReservedForDynamicVGPRs() const {857 return ScratchReservedForDynamicVGPRs;858 }859 860 void setScratchReservedForDynamicVGPRs(unsigned SizeInBytes) {861 ScratchReservedForDynamicVGPRs = SizeInBytes;862 }863 864 // Add user SGPRs.865 Register addPrivateSegmentBuffer(const SIRegisterInfo &TRI);866 Register addDispatchPtr(const SIRegisterInfo &TRI);867 Register addQueuePtr(const SIRegisterInfo &TRI);868 Register addKernargSegmentPtr(const SIRegisterInfo &TRI);869 Register addDispatchID(const SIRegisterInfo &TRI);870 Register addFlatScratchInit(const SIRegisterInfo &TRI);871 Register addPrivateSegmentSize(const SIRegisterInfo &TRI);872 Register addImplicitBufferPtr(const SIRegisterInfo &TRI);873 Register addLDSKernelId();874 SmallVectorImpl<MCRegister> *875 addPreloadedKernArg(const SIRegisterInfo &TRI, const TargetRegisterClass *RC,876 unsigned AllocSizeDWord, int KernArgIdx,877 int PaddingSGPRs);878 879 /// Increment user SGPRs used for padding the argument list only.880 Register addReservedUserSGPR() {881 Register Next = getNextUserSGPR();882 ++NumUserSGPRs;883 return Next;884 }885 886 // Add system SGPRs.887 Register addWorkGroupIDX() {888 ArgInfo.WorkGroupIDX = ArgDescriptor::createRegister(getNextSystemSGPR());889 NumSystemSGPRs += 1;890 return ArgInfo.WorkGroupIDX.getRegister();891 }892 893 Register addWorkGroupIDY() {894 ArgInfo.WorkGroupIDY = ArgDescriptor::createRegister(getNextSystemSGPR());895 NumSystemSGPRs += 1;896 return ArgInfo.WorkGroupIDY.getRegister();897 }898 899 Register addWorkGroupIDZ() {900 ArgInfo.WorkGroupIDZ = ArgDescriptor::createRegister(getNextSystemSGPR());901 NumSystemSGPRs += 1;902 return ArgInfo.WorkGroupIDZ.getRegister();903 }904 905 Register addWorkGroupInfo() {906 ArgInfo.WorkGroupInfo = ArgDescriptor::createRegister(getNextSystemSGPR());907 NumSystemSGPRs += 1;908 return ArgInfo.WorkGroupInfo.getRegister();909 }910 911 bool hasLDSKernelId() const { return LDSKernelId; }912 913 // Add special VGPR inputs914 void setWorkItemIDX(ArgDescriptor Arg) {915 ArgInfo.WorkItemIDX = Arg;916 }917 918 void setWorkItemIDY(ArgDescriptor Arg) {919 ArgInfo.WorkItemIDY = Arg;920 }921 922 void setWorkItemIDZ(ArgDescriptor Arg) {923 ArgInfo.WorkItemIDZ = Arg;924 }925 926 Register addPrivateSegmentWaveByteOffset() {927 ArgInfo.PrivateSegmentWaveByteOffset928 = ArgDescriptor::createRegister(getNextSystemSGPR());929 NumSystemSGPRs += 1;930 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister();931 }932 933 void setPrivateSegmentWaveByteOffset(Register Reg) {934 ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg);935 }936 937 bool hasWorkGroupIDX() const {938 return WorkGroupIDX;939 }940 941 bool hasWorkGroupIDY() const {942 return WorkGroupIDY;943 }944 945 bool hasWorkGroupIDZ() const {946 return WorkGroupIDZ;947 }948 949 bool hasWorkGroupInfo() const {950 return WorkGroupInfo;951 }952 953 bool hasPrivateSegmentWaveByteOffset() const {954 return PrivateSegmentWaveByteOffset;955 }956 957 bool hasWorkItemIDX() const {958 return WorkItemIDX;959 }960 961 bool hasWorkItemIDY() const {962 return WorkItemIDY;963 }964 965 bool hasWorkItemIDZ() const {966 return WorkItemIDZ;967 }968 969 bool hasImplicitArgPtr() const {970 return ImplicitArgPtr;971 }972 973 AMDGPUFunctionArgInfo &getArgInfo() {974 return ArgInfo;975 }976 977 const AMDGPUFunctionArgInfo &getArgInfo() const {978 return ArgInfo;979 }980 981 std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT>982 getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const {983 return ArgInfo.getPreloadedValue(Value);984 }985 986 MCRegister getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const {987 const auto *Arg = std::get<0>(ArgInfo.getPreloadedValue(Value));988 return Arg ? Arg->getRegister() : MCRegister();989 }990 991 unsigned getGITPtrHigh() const {992 return GITPtrHigh;993 }994 995 Register getGITPtrLoReg(const MachineFunction &MF) const;996 997 uint32_t get32BitAddressHighBits() const {998 return HighBitsOf32BitAddress;999 }1000 1001 unsigned getNumUserSGPRs() const {1002 return NumUserSGPRs;1003 }1004 1005 unsigned getNumPreloadedSGPRs() const {1006 return NumUserSGPRs + NumSystemSGPRs;1007 }1008 1009 unsigned getNumKernargPreloadedSGPRs() const {1010 return UserSGPRInfo.getNumKernargPreloadSGPRs();1011 }1012 1013 unsigned getNumWaveDispatchSGPRs() const { return NumWaveDispatchSGPRs; }1014 1015 void setNumWaveDispatchSGPRs(unsigned Count) { NumWaveDispatchSGPRs = Count; }1016 1017 unsigned getNumWaveDispatchVGPRs() const { return NumWaveDispatchVGPRs; }1018 1019 void setNumWaveDispatchVGPRs(unsigned Count) { NumWaveDispatchVGPRs = Count; }1020 1021 Register getPrivateSegmentWaveByteOffsetSystemSGPR() const {1022 if (ArgInfo.PrivateSegmentWaveByteOffset)1023 return ArgInfo.PrivateSegmentWaveByteOffset.getRegister();1024 return MCRegister();1025 }1026 1027 /// Returns the physical register reserved for use as the resource1028 /// descriptor for scratch accesses.1029 Register getScratchRSrcReg() const {1030 return ScratchRSrcReg;1031 }1032 1033 void setScratchRSrcReg(Register Reg) {1034 assert(Reg != 0 && "Should never be unset");1035 ScratchRSrcReg = Reg;1036 }1037 1038 Register getFrameOffsetReg() const {1039 return FrameOffsetReg;1040 }1041 1042 void setFrameOffsetReg(Register Reg) {1043 assert(Reg != 0 && "Should never be unset");1044 FrameOffsetReg = Reg;1045 }1046 1047 void setStackPtrOffsetReg(Register Reg) {1048 assert(Reg != 0 && "Should never be unset");1049 StackPtrOffsetReg = Reg;1050 }1051 1052 void setLongBranchReservedReg(Register Reg) { LongBranchReservedReg = Reg; }1053 1054 // Note the unset value for this is AMDGPU::SP_REG rather than1055 // NoRegister. This is mostly a workaround for MIR tests where state that1056 // can't be directly computed from the function is not preserved in serialized1057 // MIR.1058 Register getStackPtrOffsetReg() const {1059 return StackPtrOffsetReg;1060 }1061 1062 Register getLongBranchReservedReg() const { return LongBranchReservedReg; }1063 1064 Register getQueuePtrUserSGPR() const {1065 return ArgInfo.QueuePtr.getRegister();1066 }1067 1068 Register getImplicitBufferPtrUserSGPR() const {1069 return ArgInfo.ImplicitBufferPtr.getRegister();1070 }1071 1072 bool hasSpilledSGPRs() const {1073 return HasSpilledSGPRs;1074 }1075 1076 void setHasSpilledSGPRs(bool Spill = true) {1077 HasSpilledSGPRs = Spill;1078 }1079 1080 bool hasSpilledVGPRs() const {1081 return HasSpilledVGPRs;1082 }1083 1084 void setHasSpilledVGPRs(bool Spill = true) {1085 HasSpilledVGPRs = Spill;1086 }1087 1088 bool hasNonSpillStackObjects() const {1089 return HasNonSpillStackObjects;1090 }1091 1092 void setHasNonSpillStackObjects(bool StackObject = true) {1093 HasNonSpillStackObjects = StackObject;1094 }1095 1096 bool isStackRealigned() const {1097 return IsStackRealigned;1098 }1099 1100 void setIsStackRealigned(bool Realigned = true) {1101 IsStackRealigned = Realigned;1102 }1103 1104 unsigned getNumSpilledSGPRs() const {1105 return NumSpilledSGPRs;1106 }1107 1108 unsigned getNumSpilledVGPRs() const {1109 return NumSpilledVGPRs;1110 }1111 1112 void addToSpilledSGPRs(unsigned num) {1113 NumSpilledSGPRs += num;1114 }1115 1116 void addToSpilledVGPRs(unsigned num) {1117 NumSpilledVGPRs += num;1118 }1119 1120 unsigned getPSInputAddr() const {1121 return PSInputAddr;1122 }1123 1124 unsigned getPSInputEnable() const {1125 return PSInputEnable;1126 }1127 1128 bool isPSInputAllocated(unsigned Index) const {1129 return PSInputAddr & (1 << Index);1130 }1131 1132 void markPSInputAllocated(unsigned Index) {1133 PSInputAddr |= 1 << Index;1134 }1135 1136 void markPSInputEnabled(unsigned Index) {1137 PSInputEnable |= 1 << Index;1138 }1139 1140 bool returnsVoid() const {1141 return ReturnsVoid;1142 }1143 1144 void setIfReturnsVoid(bool Value) {1145 ReturnsVoid = Value;1146 }1147 1148 /// \returns A pair of default/requested minimum/maximum flat work group sizes1149 /// for this function.1150 std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const {1151 return FlatWorkGroupSizes;1152 }1153 1154 /// \returns Default/requested minimum flat work group size for this function.1155 unsigned getMinFlatWorkGroupSize() const {1156 return FlatWorkGroupSizes.first;1157 }1158 1159 /// \returns Default/requested maximum flat work group size for this function.1160 unsigned getMaxFlatWorkGroupSize() const {1161 return FlatWorkGroupSizes.second;1162 }1163 1164 /// \returns A pair of default/requested minimum/maximum number of waves per1165 /// execution unit.1166 std::pair<unsigned, unsigned> getWavesPerEU() const {1167 return WavesPerEU;1168 }1169 1170 /// \returns Default/requested minimum number of waves per execution unit.1171 unsigned getMinWavesPerEU() const {1172 return WavesPerEU.first;1173 }1174 1175 /// \returns Default/requested maximum number of waves per execution unit.1176 unsigned getMaxWavesPerEU() const {1177 return WavesPerEU.second;1178 }1179 1180 const AMDGPUGWSResourcePseudoSourceValue *1181 getGWSPSV(const AMDGPUTargetMachine &TM) {1182 return &GWSResourcePSV;1183 }1184 1185 unsigned getOccupancy() const {1186 return Occupancy;1187 }1188 1189 unsigned getMinAllowedOccupancy() const {1190 if (!isMemoryBound() && !needsWaveLimiter())1191 return Occupancy;1192 return (Occupancy < 4) ? Occupancy : 4;1193 }1194 1195 void limitOccupancy(const MachineFunction &MF);1196 1197 void limitOccupancy(unsigned Limit) {1198 if (Occupancy > Limit)1199 Occupancy = Limit;1200 }1201 1202 void increaseOccupancy(const MachineFunction &MF, unsigned Limit) {1203 if (Occupancy < Limit)1204 Occupancy = Limit;1205 limitOccupancy(MF);1206 }1207 1208 unsigned getMaxMemoryClusterDWords() const { return MaxMemoryClusterDWords; }1209 1210 unsigned getMinNumAGPRs() const { return MinNumAGPRs; }1211 1212 /// Return true if an MFMA that requires at least \p NumRegs should select to1213 /// the AGPR form, instead of the VGPR form.1214 bool selectAGPRFormMFMA(unsigned NumRegs) const {1215 return !MFMAVGPRForm && getMinNumAGPRs() >= NumRegs;1216 }1217 1218 // \returns true if a function has a use of AGPRs via inline asm or1219 // has a call which may use it.1220 bool mayUseAGPRs(const Function &F) const;1221 1222 /// \returns Default/requested number of work groups for this function.1223 SmallVector<unsigned> getMaxNumWorkGroups() const { return MaxNumWorkGroups; }1224 1225 unsigned getMaxNumWorkGroupsX() const { return MaxNumWorkGroups[0]; }1226 unsigned getMaxNumWorkGroupsY() const { return MaxNumWorkGroups[1]; }1227 unsigned getMaxNumWorkGroupsZ() const { return MaxNumWorkGroups[2]; }1228 1229 AMDGPU::ClusterDimsAttr getClusterDims() const { return ClusterDims; }1230};1231 1232} // end namespace llvm1233 1234#endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H1235