brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.4 KiB · d901f4c Raw
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