brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.3 KiB · ed03ef2 Raw
413 lines · c
1//=====-- AMDGPUSubtarget.h - Define Subtarget for AMDGPU -------*- 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/// Base class for AMDGPU specific classes of TargetSubtarget.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H15#define LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H16 17#include "llvm/ADT/SmallVector.h"18#include "llvm/IR/CallingConv.h"19#include "llvm/Support/Alignment.h"20#include "llvm/TargetParser/Triple.h"21 22namespace llvm {23 24enum AMDGPUDwarfFlavour : unsigned;25class Function;26class Instruction;27class MachineFunction;28class TargetMachine;29 30class AMDGPUSubtarget {31public:32  enum Generation {33    INVALID = 0,34    R600 = 1,35    R700 = 2,36    EVERGREEN = 3,37    NORTHERN_ISLANDS = 4,38    SOUTHERN_ISLANDS = 5,39    SEA_ISLANDS = 6,40    VOLCANIC_ISLANDS = 7,41    GFX9 = 8,42    GFX10 = 9,43    GFX11 = 10,44    GFX12 = 11,45  };46 47private:48  Triple TargetTriple;49 50protected:51  bool GCN3Encoding = false;52  bool Has16BitInsts = false;53  bool HasTrue16BitInsts = false;54  bool HasFP8ConversionScaleInsts = false;55  bool HasBF8ConversionScaleInsts = false;56  bool HasFP4ConversionScaleInsts = false;57  bool HasFP6BF6ConversionScaleInsts = false;58  bool HasF16BF16ToFP6BF6ConversionScaleInsts = false;59  bool HasCvtPkF16F32Inst = false;60  bool HasF32ToF16BF16ConversionSRInsts = false;61  bool EnableRealTrue16Insts = false;62  bool EnableD16Writes32BitVgpr = false;63  bool HasBF16TransInsts = false;64  bool HasBF16ConversionInsts = false;65  bool HasBF16PackedInsts = false;66  bool HasMadMixInsts = false;67  bool HasMadMacF32Insts = false;68  bool HasDsSrc2Insts = false;69  bool HasSDWA = false;70  bool HasVOP3PInsts = false;71  bool HasMulI24 = true;72  bool HasMulU24 = true;73  bool HasSMulHi = false;74  bool HasInv2PiInlineImm = false;75  bool HasFminFmaxLegacy = true;76  bool EnablePromoteAlloca = false;77  bool HasTrigReducedRange = false;78  bool FastFMAF32 = false;79  unsigned EUsPerCU = 4;80  unsigned MaxWavesPerEU = 10;81  unsigned LocalMemorySize = 0;82  unsigned AddressableLocalMemorySize = 0;83  char WavefrontSizeLog2 = 0;84 85public:86  AMDGPUSubtarget(Triple TT);87 88  static const AMDGPUSubtarget &get(const MachineFunction &MF);89  static const AMDGPUSubtarget &get(const TargetMachine &TM,90                                    const Function &F);91 92  /// \returns Default range flat work group size for a calling convention.93  std::pair<unsigned, unsigned> getDefaultFlatWorkGroupSize(CallingConv::ID CC) const;94 95  /// \returns Subtarget's default pair of minimum/maximum flat work group sizes96  /// for function \p F, or minimum/maximum flat work group sizes explicitly97  /// requested using "amdgpu-flat-work-group-size" attribute attached to98  /// function \p F.99  ///100  /// \returns Subtarget's default values if explicitly requested values cannot101  /// be converted to integer, or violate subtarget's specifications.102  std::pair<unsigned, unsigned> getFlatWorkGroupSizes(const Function &F) const;103 104  /// \returns The required size of workgroups that will be used to execute \p F105  /// in the \p Dim dimension, if it is known (from `!reqd_work_group_size`106  /// metadata. Otherwise, returns std::nullopt.107  std::optional<unsigned> getReqdWorkGroupSize(const Function &F,108                                               unsigned Dim) const;109 110  /// \returns true if \p F will execute in a manner that leaves the X111  /// dimensions of the workitem ID evenly tiling wavefronts - that is, if X /112  /// wavefrontsize is uniform. This is true if either the Y and Z block113  /// dimensions are known to always be 1 or if the X dimension will always be a114  /// power of 2. If \p RequireUniformYZ is true, it also ensures that the Y and115  /// Z workitem IDs will be uniform (so, while a (32, 2, 1) launch with116  /// wavesize64 would ordinarily pass this test, it won't with117  /// \pRequiresUniformYZ).118  ///119  /// This information is currently only gathered from the !reqd_work_group_size120  /// metadata on \p F, but this may be improved in the future.121  bool hasWavefrontsEvenlySplittingXDim(const Function &F,122                                        bool REquiresUniformYZ = false) const;123 124  /// \returns Subtarget's default pair of minimum/maximum number of waves per125  /// execution unit for function \p F, or minimum/maximum number of waves per126  /// execution unit explicitly requested using "amdgpu-waves-per-eu" attribute127  /// attached to function \p F.128  ///129  /// \returns Subtarget's default values if explicitly requested values cannot130  /// be converted to integer, violate subtarget's specifications, or are not131  /// compatible with minimum/maximum number of waves limited by flat work group132  /// size, register usage, and/or lds usage.133  std::pair<unsigned, unsigned> getWavesPerEU(const Function &F) const;134 135  /// Overload which uses the specified values for the flat work group sizes,136  /// rather than querying the function itself. \p FlatWorkGroupSizes Should137  /// correspond to the function's value for getFlatWorkGroupSizes.138  std::pair<unsigned, unsigned>139  getWavesPerEU(const Function &F,140                std::pair<unsigned, unsigned> FlatWorkGroupSizes) const;141 142  /// Overload which uses the specified values for the flat workgroup sizes and143  /// LDS space rather than querying the function itself. \p FlatWorkGroupSizes144  /// should correspond to the function's value for getFlatWorkGroupSizes and \p145  /// LDSBytes to the per-workgroup LDS allocation.146  std::pair<unsigned, unsigned>147  getWavesPerEU(std::pair<unsigned, unsigned> FlatWorkGroupSizes,148                unsigned LDSBytes, const Function &F) const;149 150  /// Returns the target minimum/maximum number of waves per EU. This is based151  /// on the minimum/maximum number of \p RequestedWavesPerEU and further152  /// limited by the maximum achievable occupancy derived from the range of \p153  /// FlatWorkGroupSizes and number of \p LDSBytes per workgroup.154  std::pair<unsigned, unsigned>155  getEffectiveWavesPerEU(std::pair<unsigned, unsigned> RequestedWavesPerEU,156                         std::pair<unsigned, unsigned> FlatWorkGroupSizes,157                         unsigned LDSBytes) const;158 159  /// Return the amount of LDS that can be used that will not restrict the160  /// occupancy lower than WaveCount.161  unsigned getMaxLocalMemSizeWithWaveCount(unsigned WaveCount,162                                           const Function &) const;163 164  /// Subtarget's minimum/maximum occupancy, in number of waves per EU, that can165  /// be achieved when the only function running on a CU is \p F and each166  /// workgroup running the function requires \p LDSBytes bytes of LDS space.167  /// This notably depends on the range of allowed flat group sizes for the168  /// function and hardware characteristics.169  std::pair<unsigned, unsigned>170  getOccupancyWithWorkGroupSizes(uint32_t LDSBytes, const Function &F) const {171    return getOccupancyWithWorkGroupSizes(LDSBytes, getFlatWorkGroupSizes(F));172  }173 174  /// Overload which uses the specified values for the flat work group sizes,175  /// rather than querying the function itself. \p FlatWorkGroupSizes should176  /// correspond to the function's value for getFlatWorkGroupSizes.177  std::pair<unsigned, unsigned> getOccupancyWithWorkGroupSizes(178      uint32_t LDSBytes,179      std::pair<unsigned, unsigned> FlatWorkGroupSizes) const;180 181  /// Subtarget's minimum/maximum occupancy, in number of waves per EU, that can182  /// be achieved when the only function running on a CU is \p MF. This notably183  /// depends on the range of allowed flat group sizes for the function, the184  /// amount of per-workgroup LDS space required by the function, and hardware185  /// characteristics.186  std::pair<unsigned, unsigned>187  getOccupancyWithWorkGroupSizes(const MachineFunction &MF) const;188 189  bool isAmdHsaOS() const {190    return TargetTriple.getOS() == Triple::AMDHSA;191  }192 193  bool isAmdPalOS() const {194    return TargetTriple.getOS() == Triple::AMDPAL;195  }196 197  bool isMesa3DOS() const {198    return TargetTriple.getOS() == Triple::Mesa3D;199  }200 201  bool isMesaKernel(const Function &F) const;202 203  bool isAmdHsaOrMesa(const Function &F) const {204    return isAmdHsaOS() || isMesaKernel(F);205  }206 207  bool isGCN() const { return TargetTriple.isAMDGCN(); }208 209  bool isGCN3Encoding() const {210    return GCN3Encoding;211  }212 213  bool has16BitInsts() const {214    return Has16BitInsts;215  }216 217  /// Return true if the subtarget supports True16 instructions.218  bool hasTrue16BitInsts() const { return HasTrue16BitInsts; }219 220  /// Return true if real (non-fake) variants of True16 instructions using221  /// 16-bit registers should be code-generated. Fake True16 instructions are222  /// identical to non-fake ones except that they take 32-bit registers as223  /// operands and always use their low halves.224  // TODO: Remove and use hasTrue16BitInsts() instead once True16 is fully225  // supported and the support for fake True16 instructions is removed.226  bool useRealTrue16Insts() const;227 228  bool hasD16Writes32BitVgpr() const;229 230  bool hasBF16TransInsts() const { return HasBF16TransInsts; }231 232  bool hasBF16ConversionInsts() const {233    return HasBF16ConversionInsts;234  }235 236  bool hasBF16PackedInsts() const { return HasBF16PackedInsts; }237 238  bool hasMadMixInsts() const {239    return HasMadMixInsts;240  }241 242  bool hasFP8ConversionScaleInsts() const { return HasFP8ConversionScaleInsts; }243 244  bool hasBF8ConversionScaleInsts() const { return HasBF8ConversionScaleInsts; }245 246  bool hasFP4ConversionScaleInsts() const { return HasFP4ConversionScaleInsts; }247 248  bool hasFP6BF6ConversionScaleInsts() const {249    return HasFP6BF6ConversionScaleInsts;250  }251 252  bool hasF16BF16ToFP6BF6ConversionScaleInsts() const {253    return HasF16BF16ToFP6BF6ConversionScaleInsts;254  }255 256  bool hasCvtPkF16F32Inst() const { return HasCvtPkF16F32Inst; }257 258  bool hasF32ToF16BF16ConversionSRInsts() const {259    return HasF32ToF16BF16ConversionSRInsts;260  }261 262  bool hasMadMacF32Insts() const {263    return HasMadMacF32Insts || !isGCN();264  }265 266  bool hasDsSrc2Insts() const {267    return HasDsSrc2Insts;268  }269 270  bool hasSDWA() const {271    return HasSDWA;272  }273 274  bool hasVOP3PInsts() const {275    return HasVOP3PInsts;276  }277 278  bool hasMulI24() const {279    return HasMulI24;280  }281 282  bool hasMulU24() const {283    return HasMulU24;284  }285 286  bool hasSMulHi() const {287    return HasSMulHi;288  }289 290  bool hasInv2PiInlineImm() const {291    return HasInv2PiInlineImm;292  }293 294  bool hasFminFmaxLegacy() const {295    return HasFminFmaxLegacy;296  }297 298  bool hasTrigReducedRange() const {299    return HasTrigReducedRange;300  }301 302  bool hasFastFMAF32() const {303    return FastFMAF32;304  }305 306  bool isPromoteAllocaEnabled() const {307    return EnablePromoteAlloca;308  }309 310  unsigned getWavefrontSize() const {311    return 1 << WavefrontSizeLog2;312  }313 314  unsigned getWavefrontSizeLog2() const {315    return WavefrontSizeLog2;316  }317 318  /// Return the maximum number of bytes of LDS available for all workgroups319  /// running on the same WGP or CU.320  /// For GFX10-GFX12 in WGP mode this is 128k even though each workgroup is321  /// limited to 64k.322  unsigned getLocalMemorySize() const {323    return LocalMemorySize;324  }325 326  /// Return the maximum number of bytes of LDS that can be allocated to a327  /// single workgroup.328  /// For GFX10-GFX12 in WGP mode this is limited to 64k even though the WGP has329  /// 128k in total.330  unsigned getAddressableLocalMemorySize() const {331    return AddressableLocalMemorySize;332  }333 334  /// Number of SIMDs/EUs (execution units) per "CU" ("compute unit"), where the335  /// "CU" is the unit onto which workgroups are mapped. This takes WGP mode vs.336  /// CU mode into account.337  unsigned getEUsPerCU() const { return EUsPerCU; }338 339  Align getAlignmentForImplicitArgPtr() const {340    return isAmdHsaOS() ? Align(8) : Align(4);341  }342 343  /// Returns the offset in bytes from the start of the input buffer344  ///        of the first explicit kernel argument.345  unsigned getExplicitKernelArgOffset() const {346    switch (TargetTriple.getOS()) {347    case Triple::AMDHSA:348    case Triple::AMDPAL:349    case Triple::Mesa3D:350      return 0;351    case Triple::UnknownOS:352    default:353      // For legacy reasons unknown/other is treated as a different version of354      // mesa.355      return 36;356    }357 358    llvm_unreachable("invalid triple OS");359  }360 361  /// \returns Maximum number of work groups per compute unit supported by the362  /// subtarget and limited by given \p FlatWorkGroupSize.363  virtual unsigned getMaxWorkGroupsPerCU(unsigned FlatWorkGroupSize) const = 0;364 365  /// \returns Minimum flat work group size supported by the subtarget.366  virtual unsigned getMinFlatWorkGroupSize() const = 0;367 368  /// \returns Maximum flat work group size supported by the subtarget.369  virtual unsigned getMaxFlatWorkGroupSize() const = 0;370 371  /// \returns Number of waves per execution unit required to support the given372  /// \p FlatWorkGroupSize.373  virtual unsigned374  getWavesPerEUForWorkGroup(unsigned FlatWorkGroupSize) const = 0;375 376  /// \returns Minimum number of waves per execution unit supported by the377  /// subtarget.378  virtual unsigned getMinWavesPerEU() const = 0;379 380  /// \returns Maximum number of waves per execution unit supported by the381  /// subtarget without any kind of limitation.382  unsigned getMaxWavesPerEU() const { return MaxWavesPerEU; }383 384  /// Return the maximum workitem ID value in the function, for the given (0, 1,385  /// 2) dimension.386  unsigned getMaxWorkitemID(const Function &Kernel, unsigned Dimension) const;387 388  /// Return the number of work groups for the function.389  SmallVector<unsigned> getMaxNumWorkGroups(const Function &F) const;390 391  /// Return true if only a single workitem can be active in a wave.392  bool isSingleLaneExecution(const Function &Kernel) const;393 394  /// Creates value range metadata on an workitemid.* intrinsic call or load.395  bool makeLIDRangeMetadata(Instruction *I) const;396 397  /// \returns Number of bytes of arguments that are passed to a shader or398  /// kernel in addition to the explicit ones declared for the function.399  unsigned getImplicitArgNumBytes(const Function &F) const;400  uint64_t getExplicitKernArgSize(const Function &F, Align &MaxAlign) const;401  unsigned getKernArgSegmentSize(const Function &F, Align &MaxAlign) const;402 403  /// \returns Corresponding DWARF register number mapping flavour for the404  /// \p WavefrontSize.405  AMDGPUDwarfFlavour getAMDGPUDwarfFlavour() const;406 407  virtual ~AMDGPUSubtarget() = default;408};409 410} // end namespace llvm411 412#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H413