10b57cec5SDimitry Andric //===- AMDGPUBaseInfo.h - Top level definitions for AMDGPU ------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H 100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H 110b57cec5SDimitry Andric 12*0fca6ea1SDimitry Andric #include "AMDGPUSubtarget.h" 130b57cec5SDimitry Andric #include "SIDefines.h" 140b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 1506c3fb27SDimitry Andric #include "llvm/IR/InstrTypes.h" 1606c3fb27SDimitry Andric #include "llvm/IR/Module.h" 175ffd83dbSDimitry Andric #include "llvm/Support/Alignment.h" 18bdd1243dSDimitry Andric #include <array> 19bdd1243dSDimitry Andric #include <functional> 20bdd1243dSDimitry Andric #include <utility> 21e8d8bef9SDimitry Andric 22e8d8bef9SDimitry Andric struct amd_kernel_code_t; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 26e8d8bef9SDimitry Andric struct Align; 270b57cec5SDimitry Andric class Argument; 280b57cec5SDimitry Andric class Function; 290b57cec5SDimitry Andric class GlobalValue; 30bdd1243dSDimitry Andric class MCInstrInfo; 310b57cec5SDimitry Andric class MCRegisterClass; 320b57cec5SDimitry Andric class MCRegisterInfo; 330b57cec5SDimitry Andric class MCSubtargetInfo; 345ffd83dbSDimitry Andric class StringRef; 350b57cec5SDimitry Andric class Triple; 36bdd1243dSDimitry Andric class raw_ostream; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace AMDGPU { 390b57cec5SDimitry Andric 40*0fca6ea1SDimitry Andric struct AMDGPUMCKernelCodeT; 41e8d8bef9SDimitry Andric struct IsaVersion; 42e8d8bef9SDimitry Andric 43*0fca6ea1SDimitry Andric /// Generic target versions emitted by this version of LLVM. 44*0fca6ea1SDimitry Andric /// 45*0fca6ea1SDimitry Andric /// These numbers are incremented every time a codegen breaking change occurs 46*0fca6ea1SDimitry Andric /// within a generic family. 47*0fca6ea1SDimitry Andric namespace GenericVersion { 48*0fca6ea1SDimitry Andric static constexpr unsigned GFX9 = 1; 49*0fca6ea1SDimitry Andric static constexpr unsigned GFX10_1 = 1; 50*0fca6ea1SDimitry Andric static constexpr unsigned GFX10_3 = 1; 51*0fca6ea1SDimitry Andric static constexpr unsigned GFX11 = 1; 52*0fca6ea1SDimitry Andric static constexpr unsigned GFX12 = 1; 53*0fca6ea1SDimitry Andric } // namespace GenericVersion 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric enum { AMDHSA_COV4 = 4, AMDHSA_COV5 = 5, AMDHSA_COV6 = 6 }; 5606c3fb27SDimitry Andric 575f757f3fSDimitry Andric /// \returns True if \p STI is AMDHSA. 585f757f3fSDimitry Andric bool isHsaAbi(const MCSubtargetInfo &STI); 597a6dacacSDimitry Andric 607a6dacacSDimitry Andric /// \returns Code object version from the IR module flag. 617a6dacacSDimitry Andric unsigned getAMDHSACodeObjectVersion(const Module &M); 627a6dacacSDimitry Andric 63*0fca6ea1SDimitry Andric /// \returns Code object version from ELF's e_ident[EI_ABIVERSION]. 64*0fca6ea1SDimitry Andric unsigned getAMDHSACodeObjectVersion(unsigned ABIVersion); 65*0fca6ea1SDimitry Andric 667a6dacacSDimitry Andric /// \returns The default HSA code object version. This should only be used when 677a6dacacSDimitry Andric /// we lack a more accurate CodeObjectVersion value (e.g. from the IR module 687a6dacacSDimitry Andric /// flag or a .amdhsa_code_object_version directive) 697a6dacacSDimitry Andric unsigned getDefaultAMDHSACodeObjectVersion(); 707a6dacacSDimitry Andric 71*0fca6ea1SDimitry Andric /// \returns ABIVersion suitable for use in ELF's e_ident[EI_ABIVERSION]. \param 727a6dacacSDimitry Andric /// CodeObjectVersion is a value returned by getAMDHSACodeObjectVersion(). 737a6dacacSDimitry Andric uint8_t getELFABIVersion(const Triple &OS, unsigned CodeObjectVersion); 74e8d8bef9SDimitry Andric 7581ad6265SDimitry Andric /// \returns The offset of the multigrid_sync_arg argument from implicitarg_ptr 7606c3fb27SDimitry Andric unsigned getMultigridSyncArgImplicitArgPosition(unsigned COV); 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric /// \returns The offset of the hostcall pointer argument from implicitarg_ptr 7906c3fb27SDimitry Andric unsigned getHostcallImplicitArgPosition(unsigned COV); 8081ad6265SDimitry Andric 8106c3fb27SDimitry Andric unsigned getDefaultQueueImplicitArgPosition(unsigned COV); 8206c3fb27SDimitry Andric unsigned getCompletionActionImplicitArgPosition(unsigned COV); 83bdd1243dSDimitry Andric 84480093f4SDimitry Andric struct GcnBufferFormatInfo { 85480093f4SDimitry Andric unsigned Format; 86480093f4SDimitry Andric unsigned BitsPerComp; 87480093f4SDimitry Andric unsigned NumComponents; 88480093f4SDimitry Andric unsigned NumFormat; 89480093f4SDimitry Andric unsigned DataFormat; 90480093f4SDimitry Andric }; 91480093f4SDimitry Andric 9281ad6265SDimitry Andric struct MAIInstInfo { 9381ad6265SDimitry Andric uint16_t Opcode; 9481ad6265SDimitry Andric bool is_dgemm; 9581ad6265SDimitry Andric bool is_gfx940_xdl; 9681ad6265SDimitry Andric }; 9781ad6265SDimitry Andric 980b57cec5SDimitry Andric #define GET_MIMGBaseOpcode_DECL 990b57cec5SDimitry Andric #define GET_MIMGDim_DECL 1000b57cec5SDimitry Andric #define GET_MIMGEncoding_DECL 1010b57cec5SDimitry Andric #define GET_MIMGLZMapping_DECL 1020b57cec5SDimitry Andric #define GET_MIMGMIPMapping_DECL 10304eeddc0SDimitry Andric #define GET_MIMGBiASMapping_DECL 10481ad6265SDimitry Andric #define GET_MAIInstInfoTable_DECL 1050b57cec5SDimitry Andric #include "AMDGPUGenSearchableTables.inc" 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric namespace IsaInfo { 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric enum { 1100b57cec5SDimitry Andric // The closed Vulkan driver sets 96, which limits the wave count to 8 but 1110b57cec5SDimitry Andric // doesn't spill SGPRs as much as when 80 is set. 1120b57cec5SDimitry Andric FIXED_NUM_SGPRS_FOR_INIT_BUG = 96, 1130b57cec5SDimitry Andric TRAP_NUM_SGPRS = 16 1140b57cec5SDimitry Andric }; 1150b57cec5SDimitry Andric 116e8d8bef9SDimitry Andric enum class TargetIDSetting { 117e8d8bef9SDimitry Andric Unsupported, 118e8d8bef9SDimitry Andric Any, 119e8d8bef9SDimitry Andric Off, 120e8d8bef9SDimitry Andric On 121e8d8bef9SDimitry Andric }; 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric class AMDGPUTargetID { 124e8d8bef9SDimitry Andric private: 125fe6060f1SDimitry Andric const MCSubtargetInfo &STI; 126e8d8bef9SDimitry Andric TargetIDSetting XnackSetting; 127e8d8bef9SDimitry Andric TargetIDSetting SramEccSetting; 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric public: 130e8d8bef9SDimitry Andric explicit AMDGPUTargetID(const MCSubtargetInfo &STI); 131e8d8bef9SDimitry Andric ~AMDGPUTargetID() = default; 132e8d8bef9SDimitry Andric 133e8d8bef9SDimitry Andric /// \return True if the current xnack setting is not "Unsupported". 134e8d8bef9SDimitry Andric bool isXnackSupported() const { 135e8d8bef9SDimitry Andric return XnackSetting != TargetIDSetting::Unsupported; 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric /// \returns True if the current xnack setting is "On" or "Any". 139e8d8bef9SDimitry Andric bool isXnackOnOrAny() const { 140e8d8bef9SDimitry Andric return XnackSetting == TargetIDSetting::On || 141e8d8bef9SDimitry Andric XnackSetting == TargetIDSetting::Any; 142e8d8bef9SDimitry Andric } 143e8d8bef9SDimitry Andric 144e8d8bef9SDimitry Andric /// \returns True if current xnack setting is "On" or "Off", 145e8d8bef9SDimitry Andric /// false otherwise. 146e8d8bef9SDimitry Andric bool isXnackOnOrOff() const { 147e8d8bef9SDimitry Andric return getXnackSetting() == TargetIDSetting::On || 148e8d8bef9SDimitry Andric getXnackSetting() == TargetIDSetting::Off; 149e8d8bef9SDimitry Andric } 150e8d8bef9SDimitry Andric 151e8d8bef9SDimitry Andric /// \returns The current xnack TargetIDSetting, possible options are 152e8d8bef9SDimitry Andric /// "Unsupported", "Any", "Off", and "On". 153e8d8bef9SDimitry Andric TargetIDSetting getXnackSetting() const { 154e8d8bef9SDimitry Andric return XnackSetting; 155e8d8bef9SDimitry Andric } 156e8d8bef9SDimitry Andric 157e8d8bef9SDimitry Andric /// Sets xnack setting to \p NewXnackSetting. 158e8d8bef9SDimitry Andric void setXnackSetting(TargetIDSetting NewXnackSetting) { 159e8d8bef9SDimitry Andric XnackSetting = NewXnackSetting; 160e8d8bef9SDimitry Andric } 161e8d8bef9SDimitry Andric 162e8d8bef9SDimitry Andric /// \return True if the current sramecc setting is not "Unsupported". 163e8d8bef9SDimitry Andric bool isSramEccSupported() const { 164e8d8bef9SDimitry Andric return SramEccSetting != TargetIDSetting::Unsupported; 165e8d8bef9SDimitry Andric } 166e8d8bef9SDimitry Andric 167e8d8bef9SDimitry Andric /// \returns True if the current sramecc setting is "On" or "Any". 168e8d8bef9SDimitry Andric bool isSramEccOnOrAny() const { 169e8d8bef9SDimitry Andric return SramEccSetting == TargetIDSetting::On || 170e8d8bef9SDimitry Andric SramEccSetting == TargetIDSetting::Any; 171e8d8bef9SDimitry Andric } 172e8d8bef9SDimitry Andric 173e8d8bef9SDimitry Andric /// \returns True if current sramecc setting is "On" or "Off", 174e8d8bef9SDimitry Andric /// false otherwise. 175e8d8bef9SDimitry Andric bool isSramEccOnOrOff() const { 176e8d8bef9SDimitry Andric return getSramEccSetting() == TargetIDSetting::On || 177e8d8bef9SDimitry Andric getSramEccSetting() == TargetIDSetting::Off; 178e8d8bef9SDimitry Andric } 179e8d8bef9SDimitry Andric 180e8d8bef9SDimitry Andric /// \returns The current sramecc TargetIDSetting, possible options are 181e8d8bef9SDimitry Andric /// "Unsupported", "Any", "Off", and "On". 182e8d8bef9SDimitry Andric TargetIDSetting getSramEccSetting() const { 183e8d8bef9SDimitry Andric return SramEccSetting; 184e8d8bef9SDimitry Andric } 185e8d8bef9SDimitry Andric 186e8d8bef9SDimitry Andric /// Sets sramecc setting to \p NewSramEccSetting. 187e8d8bef9SDimitry Andric void setSramEccSetting(TargetIDSetting NewSramEccSetting) { 188e8d8bef9SDimitry Andric SramEccSetting = NewSramEccSetting; 189e8d8bef9SDimitry Andric } 190e8d8bef9SDimitry Andric 191e8d8bef9SDimitry Andric void setTargetIDFromFeaturesString(StringRef FS); 192e8d8bef9SDimitry Andric void setTargetIDFromTargetIDStream(StringRef TargetID); 193e8d8bef9SDimitry Andric 194fe6060f1SDimitry Andric /// \returns String representation of an object. 195fe6060f1SDimitry Andric std::string toString() const; 196fe6060f1SDimitry Andric }; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric /// \returns Wavefront size for given subtarget \p STI. 1990b57cec5SDimitry Andric unsigned getWavefrontSize(const MCSubtargetInfo *STI); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric /// \returns Local memory size in bytes for given subtarget \p STI. 2020b57cec5SDimitry Andric unsigned getLocalMemorySize(const MCSubtargetInfo *STI); 2030b57cec5SDimitry Andric 204bdd1243dSDimitry Andric /// \returns Maximum addressable local memory size in bytes for given subtarget 205bdd1243dSDimitry Andric /// \p STI. 206bdd1243dSDimitry Andric unsigned getAddressableLocalMemorySize(const MCSubtargetInfo *STI); 207bdd1243dSDimitry Andric 2080b57cec5SDimitry Andric /// \returns Number of execution units per compute unit for given subtarget \p 2090b57cec5SDimitry Andric /// STI. 2100b57cec5SDimitry Andric unsigned getEUsPerCU(const MCSubtargetInfo *STI); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /// \returns Maximum number of work groups per compute unit for given subtarget 2130b57cec5SDimitry Andric /// \p STI and limited by given \p FlatWorkGroupSize. 2140b57cec5SDimitry Andric unsigned getMaxWorkGroupsPerCU(const MCSubtargetInfo *STI, 2150b57cec5SDimitry Andric unsigned FlatWorkGroupSize); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric /// \returns Minimum number of waves per execution unit for given subtarget \p 2180b57cec5SDimitry Andric /// STI. 2190b57cec5SDimitry Andric unsigned getMinWavesPerEU(const MCSubtargetInfo *STI); 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric /// \returns Maximum number of waves per execution unit for given subtarget \p 2220b57cec5SDimitry Andric /// STI without any kind of limitation. 2238bcb0991SDimitry Andric unsigned getMaxWavesPerEU(const MCSubtargetInfo *STI); 2240b57cec5SDimitry Andric 2255ffd83dbSDimitry Andric /// \returns Number of waves per execution unit required to support the given \p 2265ffd83dbSDimitry Andric /// FlatWorkGroupSize. 2275ffd83dbSDimitry Andric unsigned getWavesPerEUForWorkGroup(const MCSubtargetInfo *STI, 2280b57cec5SDimitry Andric unsigned FlatWorkGroupSize); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /// \returns Minimum flat work group size for given subtarget \p STI. 2310b57cec5SDimitry Andric unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo *STI); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric /// \returns Maximum flat work group size for given subtarget \p STI. 2340b57cec5SDimitry Andric unsigned getMaxFlatWorkGroupSize(const MCSubtargetInfo *STI); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric /// \returns Number of waves per work group for given subtarget \p STI and 2375ffd83dbSDimitry Andric /// \p FlatWorkGroupSize. 2380b57cec5SDimitry Andric unsigned getWavesPerWorkGroup(const MCSubtargetInfo *STI, 2390b57cec5SDimitry Andric unsigned FlatWorkGroupSize); 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric /// \returns SGPR allocation granularity for given subtarget \p STI. 2420b57cec5SDimitry Andric unsigned getSGPRAllocGranule(const MCSubtargetInfo *STI); 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric /// \returns SGPR encoding granularity for given subtarget \p STI. 2450b57cec5SDimitry Andric unsigned getSGPREncodingGranule(const MCSubtargetInfo *STI); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric /// \returns Total number of SGPRs for given subtarget \p STI. 2480b57cec5SDimitry Andric unsigned getTotalNumSGPRs(const MCSubtargetInfo *STI); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric /// \returns Addressable number of SGPRs for given subtarget \p STI. 2510b57cec5SDimitry Andric unsigned getAddressableNumSGPRs(const MCSubtargetInfo *STI); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric /// \returns Minimum number of SGPRs that meets the given number of waves per 2540b57cec5SDimitry Andric /// execution unit requirement for given subtarget \p STI. 2550b57cec5SDimitry Andric unsigned getMinNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// \returns Maximum number of SGPRs that meets the given number of waves per 2580b57cec5SDimitry Andric /// execution unit requirement for given subtarget \p STI. 2590b57cec5SDimitry Andric unsigned getMaxNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU, 2600b57cec5SDimitry Andric bool Addressable); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric /// \returns Number of extra SGPRs implicitly required by given subtarget \p 2630b57cec5SDimitry Andric /// STI when the given special registers are used. 2640b57cec5SDimitry Andric unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed, 2650b57cec5SDimitry Andric bool FlatScrUsed, bool XNACKUsed); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric /// \returns Number of extra SGPRs implicitly required by given subtarget \p 2680b57cec5SDimitry Andric /// STI when the given special registers are used. XNACK is inferred from 2690b57cec5SDimitry Andric /// \p STI. 2700b57cec5SDimitry Andric unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed, 2710b57cec5SDimitry Andric bool FlatScrUsed); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric /// \returns Number of SGPR blocks needed for given subtarget \p STI when 2740b57cec5SDimitry Andric /// \p NumSGPRs are used. \p NumSGPRs should already include any special 2750b57cec5SDimitry Andric /// register counts. 2760b57cec5SDimitry Andric unsigned getNumSGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric /// \returns VGPR allocation granularity for given subtarget \p STI. 2790b57cec5SDimitry Andric /// 2800b57cec5SDimitry Andric /// For subtargets which support it, \p EnableWavefrontSize32 should match 2810b57cec5SDimitry Andric /// the ENABLE_WAVEFRONT_SIZE32 kernel descriptor field. 282bdd1243dSDimitry Andric unsigned 283bdd1243dSDimitry Andric getVGPRAllocGranule(const MCSubtargetInfo *STI, 284bdd1243dSDimitry Andric std::optional<bool> EnableWavefrontSize32 = std::nullopt); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric /// \returns VGPR encoding granularity for given subtarget \p STI. 2870b57cec5SDimitry Andric /// 2880b57cec5SDimitry Andric /// For subtargets which support it, \p EnableWavefrontSize32 should match 2890b57cec5SDimitry Andric /// the ENABLE_WAVEFRONT_SIZE32 kernel descriptor field. 290bdd1243dSDimitry Andric unsigned getVGPREncodingGranule( 291bdd1243dSDimitry Andric const MCSubtargetInfo *STI, 292bdd1243dSDimitry Andric std::optional<bool> EnableWavefrontSize32 = std::nullopt); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric /// \returns Total number of VGPRs for given subtarget \p STI. 2950b57cec5SDimitry Andric unsigned getTotalNumVGPRs(const MCSubtargetInfo *STI); 2960b57cec5SDimitry Andric 297*0fca6ea1SDimitry Andric /// \returns Addressable number of architectural VGPRs for a given subtarget \p 298*0fca6ea1SDimitry Andric /// STI. 299*0fca6ea1SDimitry Andric unsigned getAddressableNumArchVGPRs(const MCSubtargetInfo *STI); 300*0fca6ea1SDimitry Andric 3010b57cec5SDimitry Andric /// \returns Addressable number of VGPRs for given subtarget \p STI. 3020b57cec5SDimitry Andric unsigned getAddressableNumVGPRs(const MCSubtargetInfo *STI); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric /// \returns Minimum number of VGPRs that meets given number of waves per 3050b57cec5SDimitry Andric /// execution unit requirement for given subtarget \p STI. 3060b57cec5SDimitry Andric unsigned getMinNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric /// \returns Maximum number of VGPRs that meets given number of waves per 3090b57cec5SDimitry Andric /// execution unit requirement for given subtarget \p STI. 3100b57cec5SDimitry Andric unsigned getMaxNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU); 3110b57cec5SDimitry Andric 312bdd1243dSDimitry Andric /// \returns Number of waves reachable for a given \p NumVGPRs usage for given 313bdd1243dSDimitry Andric /// subtarget \p STI. 314bdd1243dSDimitry Andric unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo *STI, 315bdd1243dSDimitry Andric unsigned NumVGPRs); 316bdd1243dSDimitry Andric 317*0fca6ea1SDimitry Andric /// \returns Number of waves reachable for a given \p NumVGPRs usage, \p Granule 318*0fca6ea1SDimitry Andric /// size, \p MaxWaves possible, and \p TotalNumVGPRs available. 319*0fca6ea1SDimitry Andric unsigned getNumWavesPerEUWithNumVGPRs(unsigned NumVGPRs, unsigned Granule, 320*0fca6ea1SDimitry Andric unsigned MaxWaves, 321*0fca6ea1SDimitry Andric unsigned TotalNumVGPRs); 322*0fca6ea1SDimitry Andric 323*0fca6ea1SDimitry Andric /// \returns Occupancy for a given \p SGPRs usage, \p MaxWaves possible, and \p 324*0fca6ea1SDimitry Andric /// Gen. 325*0fca6ea1SDimitry Andric unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves, 326*0fca6ea1SDimitry Andric AMDGPUSubtarget::Generation Gen); 327*0fca6ea1SDimitry Andric 3280b57cec5SDimitry Andric /// \returns Number of VGPR blocks needed for given subtarget \p STI when 329*0fca6ea1SDimitry Andric /// \p NumVGPRs are used. We actually return the number of blocks -1, since 330*0fca6ea1SDimitry Andric /// that's what we encode. 3310b57cec5SDimitry Andric /// 3320b57cec5SDimitry Andric /// For subtargets which support it, \p EnableWavefrontSize32 should match the 3330b57cec5SDimitry Andric /// ENABLE_WAVEFRONT_SIZE32 kernel descriptor field. 334*0fca6ea1SDimitry Andric unsigned getEncodedNumVGPRBlocks( 335*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI, unsigned NumVGPRs, 336*0fca6ea1SDimitry Andric std::optional<bool> EnableWavefrontSize32 = std::nullopt); 337*0fca6ea1SDimitry Andric 338*0fca6ea1SDimitry Andric /// \returns Number of VGPR blocks that need to be allocated for the given 339*0fca6ea1SDimitry Andric /// subtarget \p STI when \p NumVGPRs are used. 340*0fca6ea1SDimitry Andric unsigned getAllocatedNumVGPRBlocks( 341*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI, unsigned NumVGPRs, 342bdd1243dSDimitry Andric std::optional<bool> EnableWavefrontSize32 = std::nullopt); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric } // end namespace IsaInfo 3450b57cec5SDimitry Andric 346*0fca6ea1SDimitry Andric // Represents a field in an encoded value. 347*0fca6ea1SDimitry Andric template <unsigned HighBit, unsigned LowBit, unsigned D = 0> 348*0fca6ea1SDimitry Andric struct EncodingField { 349*0fca6ea1SDimitry Andric static_assert(HighBit >= LowBit, "Invalid bit range!"); 350*0fca6ea1SDimitry Andric static constexpr unsigned Offset = LowBit; 351*0fca6ea1SDimitry Andric static constexpr unsigned Width = HighBit - LowBit + 1; 352*0fca6ea1SDimitry Andric 353*0fca6ea1SDimitry Andric using ValueType = unsigned; 354*0fca6ea1SDimitry Andric static constexpr ValueType Default = D; 355*0fca6ea1SDimitry Andric 356*0fca6ea1SDimitry Andric ValueType Value; 357*0fca6ea1SDimitry Andric constexpr EncodingField(ValueType Value) : Value(Value) {} 358*0fca6ea1SDimitry Andric 359*0fca6ea1SDimitry Andric constexpr uint64_t encode() const { return Value; } 360*0fca6ea1SDimitry Andric static ValueType decode(uint64_t Encoded) { return Encoded; } 361*0fca6ea1SDimitry Andric }; 362*0fca6ea1SDimitry Andric 363*0fca6ea1SDimitry Andric // Represents a single bit in an encoded value. 364*0fca6ea1SDimitry Andric template <unsigned Bit, unsigned D = 0> 365*0fca6ea1SDimitry Andric using EncodingBit = EncodingField<Bit, Bit, D>; 366*0fca6ea1SDimitry Andric 367*0fca6ea1SDimitry Andric // A helper for encoding and decoding multiple fields. 368*0fca6ea1SDimitry Andric template <typename... Fields> struct EncodingFields { 369*0fca6ea1SDimitry Andric static constexpr uint64_t encode(Fields... Values) { 370*0fca6ea1SDimitry Andric return ((Values.encode() << Values.Offset) | ...); 371*0fca6ea1SDimitry Andric } 372*0fca6ea1SDimitry Andric 373*0fca6ea1SDimitry Andric static std::tuple<typename Fields::ValueType...> decode(uint64_t Encoded) { 374*0fca6ea1SDimitry Andric return {Fields::decode((Encoded >> Fields::Offset) & 375*0fca6ea1SDimitry Andric maxUIntN(Fields::Width))...}; 376*0fca6ea1SDimitry Andric } 377*0fca6ea1SDimitry Andric }; 378*0fca6ea1SDimitry Andric 3790b57cec5SDimitry Andric LLVM_READONLY 3800b57cec5SDimitry Andric int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric LLVM_READONLY 383bdd1243dSDimitry Andric inline bool hasNamedOperand(uint64_t Opcode, uint64_t NamedIdx) { 384bdd1243dSDimitry Andric return getNamedOperandIdx(Opcode, NamedIdx) != -1; 385bdd1243dSDimitry Andric } 386bdd1243dSDimitry Andric 387bdd1243dSDimitry Andric LLVM_READONLY 3880b57cec5SDimitry Andric int getSOPPWithRelaxation(uint16_t Opcode); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric struct MIMGBaseOpcodeInfo { 3910b57cec5SDimitry Andric MIMGBaseOpcode BaseOpcode; 3920b57cec5SDimitry Andric bool Store; 3930b57cec5SDimitry Andric bool Atomic; 3940b57cec5SDimitry Andric bool AtomicX2; 3950b57cec5SDimitry Andric bool Sampler; 3960b57cec5SDimitry Andric bool Gather4; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric uint8_t NumExtraArgs; 3990b57cec5SDimitry Andric bool Gradients; 4005ffd83dbSDimitry Andric bool G16; 4010b57cec5SDimitry Andric bool Coordinates; 4020b57cec5SDimitry Andric bool LodOrClampOrMip; 4030b57cec5SDimitry Andric bool HasD16; 404fe6060f1SDimitry Andric bool MSAA; 405349cc55cSDimitry Andric bool BVH; 40606c3fb27SDimitry Andric bool A16; 407*0fca6ea1SDimitry Andric bool NoReturn; 4080b57cec5SDimitry Andric }; 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric LLVM_READONLY 411349cc55cSDimitry Andric const MIMGBaseOpcodeInfo *getMIMGBaseOpcode(unsigned Opc); 412349cc55cSDimitry Andric 413349cc55cSDimitry Andric LLVM_READONLY 4140b57cec5SDimitry Andric const MIMGBaseOpcodeInfo *getMIMGBaseOpcodeInfo(unsigned BaseOpcode); 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric struct MIMGDimInfo { 4170b57cec5SDimitry Andric MIMGDim Dim; 4180b57cec5SDimitry Andric uint8_t NumCoords; 4190b57cec5SDimitry Andric uint8_t NumGradients; 420fe6060f1SDimitry Andric bool MSAA; 4210b57cec5SDimitry Andric bool DA; 4220b57cec5SDimitry Andric uint8_t Encoding; 4230b57cec5SDimitry Andric const char *AsmSuffix; 4240b57cec5SDimitry Andric }; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric LLVM_READONLY 4270b57cec5SDimitry Andric const MIMGDimInfo *getMIMGDimInfo(unsigned DimEnum); 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric LLVM_READONLY 4300b57cec5SDimitry Andric const MIMGDimInfo *getMIMGDimInfoByEncoding(uint8_t DimEnc); 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric LLVM_READONLY 4330b57cec5SDimitry Andric const MIMGDimInfo *getMIMGDimInfoByAsmSuffix(StringRef AsmSuffix); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric struct MIMGLZMappingInfo { 4360b57cec5SDimitry Andric MIMGBaseOpcode L; 4370b57cec5SDimitry Andric MIMGBaseOpcode LZ; 4380b57cec5SDimitry Andric }; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric struct MIMGMIPMappingInfo { 4410b57cec5SDimitry Andric MIMGBaseOpcode MIP; 4420b57cec5SDimitry Andric MIMGBaseOpcode NONMIP; 4430b57cec5SDimitry Andric }; 4440b57cec5SDimitry Andric 44504eeddc0SDimitry Andric struct MIMGBiasMappingInfo { 44604eeddc0SDimitry Andric MIMGBaseOpcode Bias; 44704eeddc0SDimitry Andric MIMGBaseOpcode NoBias; 44804eeddc0SDimitry Andric }; 44904eeddc0SDimitry Andric 45004eeddc0SDimitry Andric struct MIMGOffsetMappingInfo { 45104eeddc0SDimitry Andric MIMGBaseOpcode Offset; 45204eeddc0SDimitry Andric MIMGBaseOpcode NoOffset; 45304eeddc0SDimitry Andric }; 45404eeddc0SDimitry Andric 4555ffd83dbSDimitry Andric struct MIMGG16MappingInfo { 4565ffd83dbSDimitry Andric MIMGBaseOpcode G; 4575ffd83dbSDimitry Andric MIMGBaseOpcode G16; 4585ffd83dbSDimitry Andric }; 4595ffd83dbSDimitry Andric 4600b57cec5SDimitry Andric LLVM_READONLY 4610b57cec5SDimitry Andric const MIMGLZMappingInfo *getMIMGLZMappingInfo(unsigned L); 4620b57cec5SDimitry Andric 46381ad6265SDimitry Andric struct WMMAOpcodeMappingInfo { 46481ad6265SDimitry Andric unsigned Opcode2Addr; 46581ad6265SDimitry Andric unsigned Opcode3Addr; 46681ad6265SDimitry Andric }; 46781ad6265SDimitry Andric 4680b57cec5SDimitry Andric LLVM_READONLY 4695ffd83dbSDimitry Andric const MIMGMIPMappingInfo *getMIMGMIPMappingInfo(unsigned MIP); 4705ffd83dbSDimitry Andric 4715ffd83dbSDimitry Andric LLVM_READONLY 47204eeddc0SDimitry Andric const MIMGBiasMappingInfo *getMIMGBiasMappingInfo(unsigned Bias); 47304eeddc0SDimitry Andric 47404eeddc0SDimitry Andric LLVM_READONLY 47504eeddc0SDimitry Andric const MIMGOffsetMappingInfo *getMIMGOffsetMappingInfo(unsigned Offset); 47604eeddc0SDimitry Andric 47704eeddc0SDimitry Andric LLVM_READONLY 4785ffd83dbSDimitry Andric const MIMGG16MappingInfo *getMIMGG16MappingInfo(unsigned G); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric LLVM_READONLY 4810b57cec5SDimitry Andric int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, 4820b57cec5SDimitry Andric unsigned VDataDwords, unsigned VAddrDwords); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric LLVM_READONLY 4850b57cec5SDimitry Andric int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels); 4860b57cec5SDimitry Andric 487fe6060f1SDimitry Andric LLVM_READONLY 488fe6060f1SDimitry Andric unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, 489fe6060f1SDimitry Andric const MIMGDimInfo *Dim, bool IsA16, 490fe6060f1SDimitry Andric bool IsG16Supported); 491fe6060f1SDimitry Andric 4920b57cec5SDimitry Andric struct MIMGInfo { 4930b57cec5SDimitry Andric uint16_t Opcode; 4940b57cec5SDimitry Andric uint16_t BaseOpcode; 4950b57cec5SDimitry Andric uint8_t MIMGEncoding; 4960b57cec5SDimitry Andric uint8_t VDataDwords; 4970b57cec5SDimitry Andric uint8_t VAddrDwords; 49881ad6265SDimitry Andric uint8_t VAddrOperands; 4990b57cec5SDimitry Andric }; 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric LLVM_READONLY 5020b57cec5SDimitry Andric const MIMGInfo *getMIMGInfo(unsigned Opc); 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric LLVM_READONLY 5058bcb0991SDimitry Andric int getMTBUFBaseOpcode(unsigned Opc); 5068bcb0991SDimitry Andric 5078bcb0991SDimitry Andric LLVM_READONLY 5088bcb0991SDimitry Andric int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements); 5098bcb0991SDimitry Andric 5108bcb0991SDimitry Andric LLVM_READONLY 5118bcb0991SDimitry Andric int getMTBUFElements(unsigned Opc); 5128bcb0991SDimitry Andric 5138bcb0991SDimitry Andric LLVM_READONLY 5148bcb0991SDimitry Andric bool getMTBUFHasVAddr(unsigned Opc); 5158bcb0991SDimitry Andric 5168bcb0991SDimitry Andric LLVM_READONLY 5178bcb0991SDimitry Andric bool getMTBUFHasSrsrc(unsigned Opc); 5188bcb0991SDimitry Andric 5198bcb0991SDimitry Andric LLVM_READONLY 5208bcb0991SDimitry Andric bool getMTBUFHasSoffset(unsigned Opc); 5218bcb0991SDimitry Andric 5228bcb0991SDimitry Andric LLVM_READONLY 5230b57cec5SDimitry Andric int getMUBUFBaseOpcode(unsigned Opc); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric LLVM_READONLY 5268bcb0991SDimitry Andric int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements); 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric LLVM_READONLY 5298bcb0991SDimitry Andric int getMUBUFElements(unsigned Opc); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric LLVM_READONLY 5320b57cec5SDimitry Andric bool getMUBUFHasVAddr(unsigned Opc); 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric LLVM_READONLY 5350b57cec5SDimitry Andric bool getMUBUFHasSrsrc(unsigned Opc); 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric LLVM_READONLY 5380b57cec5SDimitry Andric bool getMUBUFHasSoffset(unsigned Opc); 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric LLVM_READONLY 541fe6060f1SDimitry Andric bool getMUBUFIsBufferInv(unsigned Opc); 542fe6060f1SDimitry Andric 543fe6060f1SDimitry Andric LLVM_READONLY 544*0fca6ea1SDimitry Andric bool getMUBUFTfe(unsigned Opc); 545*0fca6ea1SDimitry Andric 546*0fca6ea1SDimitry Andric LLVM_READONLY 5475ffd83dbSDimitry Andric bool getSMEMIsBuffer(unsigned Opc); 5485ffd83dbSDimitry Andric 5495ffd83dbSDimitry Andric LLVM_READONLY 550fe6060f1SDimitry Andric bool getVOP1IsSingle(unsigned Opc); 551fe6060f1SDimitry Andric 552fe6060f1SDimitry Andric LLVM_READONLY 553fe6060f1SDimitry Andric bool getVOP2IsSingle(unsigned Opc); 554fe6060f1SDimitry Andric 555fe6060f1SDimitry Andric LLVM_READONLY 556fe6060f1SDimitry Andric bool getVOP3IsSingle(unsigned Opc); 557fe6060f1SDimitry Andric 558fe6060f1SDimitry Andric LLVM_READONLY 55981ad6265SDimitry Andric bool isVOPC64DPP(unsigned Opc); 56081ad6265SDimitry Andric 561*0fca6ea1SDimitry Andric LLVM_READONLY 562*0fca6ea1SDimitry Andric bool isVOPCAsmOnly(unsigned Opc); 563*0fca6ea1SDimitry Andric 56481ad6265SDimitry Andric /// Returns true if MAI operation is a double precision GEMM. 56581ad6265SDimitry Andric LLVM_READONLY 56681ad6265SDimitry Andric bool getMAIIsDGEMM(unsigned Opc); 56781ad6265SDimitry Andric 56881ad6265SDimitry Andric LLVM_READONLY 56981ad6265SDimitry Andric bool getMAIIsGFX940XDL(unsigned Opc); 57081ad6265SDimitry Andric 571753f127fSDimitry Andric struct CanBeVOPD { 572753f127fSDimitry Andric bool X; 573753f127fSDimitry Andric bool Y; 574753f127fSDimitry Andric }; 575753f127fSDimitry Andric 5765f757f3fSDimitry Andric /// \returns SIEncodingFamily used for VOPD encoding on a \p ST. 5775f757f3fSDimitry Andric LLVM_READONLY 5785f757f3fSDimitry Andric unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST); 5795f757f3fSDimitry Andric 580753f127fSDimitry Andric LLVM_READONLY 581753f127fSDimitry Andric CanBeVOPD getCanBeVOPD(unsigned Opc); 582753f127fSDimitry Andric 58381ad6265SDimitry Andric LLVM_READONLY 584480093f4SDimitry Andric const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t BitsPerComp, 585480093f4SDimitry Andric uint8_t NumComponents, 586480093f4SDimitry Andric uint8_t NumFormat, 587480093f4SDimitry Andric const MCSubtargetInfo &STI); 588480093f4SDimitry Andric LLVM_READONLY 589480093f4SDimitry Andric const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t Format, 590480093f4SDimitry Andric const MCSubtargetInfo &STI); 591480093f4SDimitry Andric 592480093f4SDimitry Andric LLVM_READONLY 5930b57cec5SDimitry Andric int getMCOpcode(uint16_t Opcode, unsigned Gen); 5940b57cec5SDimitry Andric 59581ad6265SDimitry Andric LLVM_READONLY 596753f127fSDimitry Andric unsigned getVOPDOpcode(unsigned Opc); 597753f127fSDimitry Andric 598753f127fSDimitry Andric LLVM_READONLY 5995f757f3fSDimitry Andric int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily); 600753f127fSDimitry Andric 601753f127fSDimitry Andric LLVM_READONLY 602bdd1243dSDimitry Andric bool isVOPD(unsigned Opc); 603bdd1243dSDimitry Andric 604bdd1243dSDimitry Andric LLVM_READNONE 605bdd1243dSDimitry Andric bool isMAC(unsigned Opc); 606bdd1243dSDimitry Andric 607bdd1243dSDimitry Andric LLVM_READNONE 608bdd1243dSDimitry Andric bool isPermlane16(unsigned Opc); 609bdd1243dSDimitry Andric 6105f757f3fSDimitry Andric LLVM_READNONE 6115f757f3fSDimitry Andric bool isGenericAtomic(unsigned Opc); 6125f757f3fSDimitry Andric 613b3edf446SDimitry Andric LLVM_READNONE 614b3edf446SDimitry Andric bool isCvt_F32_Fp8_Bf8_e64(unsigned Opc); 615b3edf446SDimitry Andric 616bdd1243dSDimitry Andric namespace VOPD { 617bdd1243dSDimitry Andric 618bdd1243dSDimitry Andric enum Component : unsigned { 619bdd1243dSDimitry Andric DST = 0, 620bdd1243dSDimitry Andric SRC0, 621bdd1243dSDimitry Andric SRC1, 622bdd1243dSDimitry Andric SRC2, 623bdd1243dSDimitry Andric 624bdd1243dSDimitry Andric DST_NUM = 1, 625bdd1243dSDimitry Andric MAX_SRC_NUM = 3, 626bdd1243dSDimitry Andric MAX_OPR_NUM = DST_NUM + MAX_SRC_NUM 627bdd1243dSDimitry Andric }; 628bdd1243dSDimitry Andric 62906c3fb27SDimitry Andric // LSB mask for VGPR banks per VOPD component operand. 63006c3fb27SDimitry Andric // 4 banks result in a mask 3, setting 2 lower bits. 63106c3fb27SDimitry Andric constexpr unsigned VOPD_VGPR_BANK_MASKS[] = {1, 3, 3, 1}; 632bdd1243dSDimitry Andric 633bdd1243dSDimitry Andric enum ComponentIndex : unsigned { X = 0, Y = 1 }; 634bdd1243dSDimitry Andric constexpr unsigned COMPONENTS[] = {ComponentIndex::X, ComponentIndex::Y}; 635bdd1243dSDimitry Andric constexpr unsigned COMPONENTS_NUM = 2; 636bdd1243dSDimitry Andric 637bdd1243dSDimitry Andric // Properties of VOPD components. 638bdd1243dSDimitry Andric class ComponentProps { 639bdd1243dSDimitry Andric private: 640bdd1243dSDimitry Andric unsigned SrcOperandsNum = 0; 64106c3fb27SDimitry Andric unsigned MandatoryLiteralIdx = ~0u; 642bdd1243dSDimitry Andric bool HasSrc2Acc = false; 643bdd1243dSDimitry Andric 644bdd1243dSDimitry Andric public: 645bdd1243dSDimitry Andric ComponentProps() = default; 646bdd1243dSDimitry Andric ComponentProps(const MCInstrDesc &OpDesc); 647bdd1243dSDimitry Andric 648bdd1243dSDimitry Andric // Return the total number of src operands this component has. 649bdd1243dSDimitry Andric unsigned getCompSrcOperandsNum() const { return SrcOperandsNum; } 650bdd1243dSDimitry Andric 651bdd1243dSDimitry Andric // Return the number of src operands of this component visible to the parser. 652bdd1243dSDimitry Andric unsigned getCompParsedSrcOperandsNum() const { 653bdd1243dSDimitry Andric return SrcOperandsNum - HasSrc2Acc; 654bdd1243dSDimitry Andric } 655bdd1243dSDimitry Andric 656bdd1243dSDimitry Andric // Return true iif this component has a mandatory literal. 65706c3fb27SDimitry Andric bool hasMandatoryLiteral() const { return MandatoryLiteralIdx != ~0u; } 658bdd1243dSDimitry Andric 659bdd1243dSDimitry Andric // If this component has a mandatory literal, return component operand 660bdd1243dSDimitry Andric // index of this literal (i.e. either Component::SRC1 or Component::SRC2). 661bdd1243dSDimitry Andric unsigned getMandatoryLiteralCompOperandIndex() const { 662bdd1243dSDimitry Andric assert(hasMandatoryLiteral()); 66306c3fb27SDimitry Andric return MandatoryLiteralIdx; 664bdd1243dSDimitry Andric } 665bdd1243dSDimitry Andric 666bdd1243dSDimitry Andric // Return true iif this component has operand 667bdd1243dSDimitry Andric // with component index CompSrcIdx and this operand may be a register. 668bdd1243dSDimitry Andric bool hasRegSrcOperand(unsigned CompSrcIdx) const { 669bdd1243dSDimitry Andric assert(CompSrcIdx < Component::MAX_SRC_NUM); 670bdd1243dSDimitry Andric return SrcOperandsNum > CompSrcIdx && !hasMandatoryLiteralAt(CompSrcIdx); 671bdd1243dSDimitry Andric } 672bdd1243dSDimitry Andric 673bdd1243dSDimitry Andric // Return true iif this component has tied src2. 674bdd1243dSDimitry Andric bool hasSrc2Acc() const { return HasSrc2Acc; } 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric private: 677bdd1243dSDimitry Andric bool hasMandatoryLiteralAt(unsigned CompSrcIdx) const { 678bdd1243dSDimitry Andric assert(CompSrcIdx < Component::MAX_SRC_NUM); 67906c3fb27SDimitry Andric return MandatoryLiteralIdx == Component::DST_NUM + CompSrcIdx; 680bdd1243dSDimitry Andric } 681bdd1243dSDimitry Andric }; 682bdd1243dSDimitry Andric 683bdd1243dSDimitry Andric enum ComponentKind : unsigned { 684bdd1243dSDimitry Andric SINGLE = 0, // A single VOP1 or VOP2 instruction which may be used in VOPD. 685bdd1243dSDimitry Andric COMPONENT_X, // A VOPD instruction, X component. 686bdd1243dSDimitry Andric COMPONENT_Y, // A VOPD instruction, Y component. 687bdd1243dSDimitry Andric MAX = COMPONENT_Y 688bdd1243dSDimitry Andric }; 689bdd1243dSDimitry Andric 690bdd1243dSDimitry Andric // Interface functions of this class map VOPD component operand indices 691bdd1243dSDimitry Andric // to indices of operands in MachineInstr/MCInst or parsed operands array. 692bdd1243dSDimitry Andric // 693bdd1243dSDimitry Andric // Note that this class operates with 3 kinds of indices: 694bdd1243dSDimitry Andric // - VOPD component operand indices (Component::DST, Component::SRC0, etc.); 695bdd1243dSDimitry Andric // - MC operand indices (they refer operands in a MachineInstr/MCInst); 696bdd1243dSDimitry Andric // - parsed operand indices (they refer operands in parsed operands array). 697bdd1243dSDimitry Andric // 698bdd1243dSDimitry Andric // For SINGLE components mapping between these indices is trivial. 699bdd1243dSDimitry Andric // But things get more complicated for COMPONENT_X and 700bdd1243dSDimitry Andric // COMPONENT_Y because these components share the same 701bdd1243dSDimitry Andric // MachineInstr/MCInst and the same parsed operands array. 702bdd1243dSDimitry Andric // Below is an example of component operand to parsed operand 703bdd1243dSDimitry Andric // mapping for the following instruction: 704bdd1243dSDimitry Andric // 705bdd1243dSDimitry Andric // v_dual_add_f32 v255, v4, v5 :: v_dual_mov_b32 v6, v1 706bdd1243dSDimitry Andric // 707bdd1243dSDimitry Andric // PARSED COMPONENT PARSED 708bdd1243dSDimitry Andric // COMPONENT OPERANDS OPERAND INDEX OPERAND INDEX 709bdd1243dSDimitry Andric // ------------------------------------------------------------------- 710bdd1243dSDimitry Andric // "v_dual_add_f32" 0 711bdd1243dSDimitry Andric // v_dual_add_f32 v255 0 (DST) --> 1 712bdd1243dSDimitry Andric // v4 1 (SRC0) --> 2 713bdd1243dSDimitry Andric // v5 2 (SRC1) --> 3 714bdd1243dSDimitry Andric // "::" 4 715bdd1243dSDimitry Andric // "v_dual_mov_b32" 5 716bdd1243dSDimitry Andric // v_dual_mov_b32 v6 0 (DST) --> 6 717bdd1243dSDimitry Andric // v1 1 (SRC0) --> 7 718bdd1243dSDimitry Andric // ------------------------------------------------------------------- 719bdd1243dSDimitry Andric // 720bdd1243dSDimitry Andric class ComponentLayout { 721bdd1243dSDimitry Andric private: 722bdd1243dSDimitry Andric // Regular MachineInstr/MCInst operands are ordered as follows: 723bdd1243dSDimitry Andric // dst, src0 [, other src operands] 724bdd1243dSDimitry Andric // VOPD MachineInstr/MCInst operands are ordered as follows: 725bdd1243dSDimitry Andric // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands] 726bdd1243dSDimitry Andric // Each ComponentKind has operand indices defined below. 727bdd1243dSDimitry Andric static constexpr unsigned MC_DST_IDX[] = {0, 0, 1}; 728bdd1243dSDimitry Andric static constexpr unsigned FIRST_MC_SRC_IDX[] = {1, 2, 2 /* + OpX.MCSrcNum */}; 729bdd1243dSDimitry Andric 730bdd1243dSDimitry Andric // Parsed operands of regular instructions are ordered as follows: 731bdd1243dSDimitry Andric // Mnemo dst src0 [vsrc1 ...] 732bdd1243dSDimitry Andric // Parsed VOPD operands are ordered as follows: 733bdd1243dSDimitry Andric // OpXMnemo dstX src0X [vsrc1X|imm vsrc1X|vsrc1X imm] '::' 734bdd1243dSDimitry Andric // OpYMnemo dstY src0Y [vsrc1Y|imm vsrc1Y|vsrc1Y imm] 735bdd1243dSDimitry Andric // Each ComponentKind has operand indices defined below. 736bdd1243dSDimitry Andric static constexpr unsigned PARSED_DST_IDX[] = {1, 1, 737bdd1243dSDimitry Andric 4 /* + OpX.ParsedSrcNum */}; 738bdd1243dSDimitry Andric static constexpr unsigned FIRST_PARSED_SRC_IDX[] = { 739bdd1243dSDimitry Andric 2, 2, 5 /* + OpX.ParsedSrcNum */}; 740bdd1243dSDimitry Andric 741bdd1243dSDimitry Andric private: 742bdd1243dSDimitry Andric const ComponentKind Kind; 743bdd1243dSDimitry Andric const ComponentProps PrevComp; 744bdd1243dSDimitry Andric 745bdd1243dSDimitry Andric public: 746bdd1243dSDimitry Andric // Create layout for COMPONENT_X or SINGLE component. 747bdd1243dSDimitry Andric ComponentLayout(ComponentKind Kind) : Kind(Kind) { 748bdd1243dSDimitry Andric assert(Kind == ComponentKind::SINGLE || Kind == ComponentKind::COMPONENT_X); 749bdd1243dSDimitry Andric } 750bdd1243dSDimitry Andric 751bdd1243dSDimitry Andric // Create layout for COMPONENT_Y which depends on COMPONENT_X layout. 752bdd1243dSDimitry Andric ComponentLayout(const ComponentProps &OpXProps) 753bdd1243dSDimitry Andric : Kind(ComponentKind::COMPONENT_Y), PrevComp(OpXProps) {} 754bdd1243dSDimitry Andric 755bdd1243dSDimitry Andric public: 756bdd1243dSDimitry Andric // Return the index of dst operand in MCInst operands. 757bdd1243dSDimitry Andric unsigned getIndexOfDstInMCOperands() const { return MC_DST_IDX[Kind]; } 758bdd1243dSDimitry Andric 759bdd1243dSDimitry Andric // Return the index of the specified src operand in MCInst operands. 760bdd1243dSDimitry Andric unsigned getIndexOfSrcInMCOperands(unsigned CompSrcIdx) const { 761bdd1243dSDimitry Andric assert(CompSrcIdx < Component::MAX_SRC_NUM); 762bdd1243dSDimitry Andric return FIRST_MC_SRC_IDX[Kind] + getPrevCompSrcNum() + CompSrcIdx; 763bdd1243dSDimitry Andric } 764bdd1243dSDimitry Andric 765bdd1243dSDimitry Andric // Return the index of dst operand in the parsed operands array. 766bdd1243dSDimitry Andric unsigned getIndexOfDstInParsedOperands() const { 767bdd1243dSDimitry Andric return PARSED_DST_IDX[Kind] + getPrevCompParsedSrcNum(); 768bdd1243dSDimitry Andric } 769bdd1243dSDimitry Andric 770bdd1243dSDimitry Andric // Return the index of the specified src operand in the parsed operands array. 771bdd1243dSDimitry Andric unsigned getIndexOfSrcInParsedOperands(unsigned CompSrcIdx) const { 772bdd1243dSDimitry Andric assert(CompSrcIdx < Component::MAX_SRC_NUM); 773bdd1243dSDimitry Andric return FIRST_PARSED_SRC_IDX[Kind] + getPrevCompParsedSrcNum() + CompSrcIdx; 774bdd1243dSDimitry Andric } 775bdd1243dSDimitry Andric 776bdd1243dSDimitry Andric private: 777bdd1243dSDimitry Andric unsigned getPrevCompSrcNum() const { 778bdd1243dSDimitry Andric return PrevComp.getCompSrcOperandsNum(); 779bdd1243dSDimitry Andric } 780bdd1243dSDimitry Andric unsigned getPrevCompParsedSrcNum() const { 781bdd1243dSDimitry Andric return PrevComp.getCompParsedSrcOperandsNum(); 782bdd1243dSDimitry Andric } 783bdd1243dSDimitry Andric }; 784bdd1243dSDimitry Andric 785bdd1243dSDimitry Andric // Layout and properties of VOPD components. 786bdd1243dSDimitry Andric class ComponentInfo : public ComponentLayout, public ComponentProps { 787bdd1243dSDimitry Andric public: 788bdd1243dSDimitry Andric // Create ComponentInfo for COMPONENT_X or SINGLE component. 789bdd1243dSDimitry Andric ComponentInfo(const MCInstrDesc &OpDesc, 790bdd1243dSDimitry Andric ComponentKind Kind = ComponentKind::SINGLE) 791bdd1243dSDimitry Andric : ComponentLayout(Kind), ComponentProps(OpDesc) {} 792bdd1243dSDimitry Andric 793bdd1243dSDimitry Andric // Create ComponentInfo for COMPONENT_Y which depends on COMPONENT_X layout. 794bdd1243dSDimitry Andric ComponentInfo(const MCInstrDesc &OpDesc, const ComponentProps &OpXProps) 795bdd1243dSDimitry Andric : ComponentLayout(OpXProps), ComponentProps(OpDesc) {} 796bdd1243dSDimitry Andric 797bdd1243dSDimitry Andric // Map component operand index to parsed operand index. 798bdd1243dSDimitry Andric // Return 0 if the specified operand does not exist. 799bdd1243dSDimitry Andric unsigned getIndexInParsedOperands(unsigned CompOprIdx) const; 800bdd1243dSDimitry Andric }; 801bdd1243dSDimitry Andric 802bdd1243dSDimitry Andric // Properties of VOPD instructions. 803bdd1243dSDimitry Andric class InstInfo { 804bdd1243dSDimitry Andric private: 805bdd1243dSDimitry Andric const ComponentInfo CompInfo[COMPONENTS_NUM]; 806bdd1243dSDimitry Andric 807bdd1243dSDimitry Andric public: 808bdd1243dSDimitry Andric using RegIndices = std::array<unsigned, Component::MAX_OPR_NUM>; 809bdd1243dSDimitry Andric 810bdd1243dSDimitry Andric InstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY) 811bdd1243dSDimitry Andric : CompInfo{OpX, OpY} {} 812bdd1243dSDimitry Andric 813bdd1243dSDimitry Andric InstInfo(const ComponentInfo &OprInfoX, const ComponentInfo &OprInfoY) 814bdd1243dSDimitry Andric : CompInfo{OprInfoX, OprInfoY} {} 815bdd1243dSDimitry Andric 816bdd1243dSDimitry Andric const ComponentInfo &operator[](size_t ComponentIdx) const { 817bdd1243dSDimitry Andric assert(ComponentIdx < COMPONENTS_NUM); 818bdd1243dSDimitry Andric return CompInfo[ComponentIdx]; 819bdd1243dSDimitry Andric } 820bdd1243dSDimitry Andric 821bdd1243dSDimitry Andric // Check VOPD operands constraints. 822bdd1243dSDimitry Andric // GetRegIdx(Component, MCOperandIdx) must return a VGPR register index 823bdd1243dSDimitry Andric // for the specified component and MC operand. The callback must return 0 824bdd1243dSDimitry Andric // if the operand is not a register or not a VGPR. 8255f757f3fSDimitry Andric // If \p SkipSrc is set to true then constraints for source operands are not 8265f757f3fSDimitry Andric // checked. 8275f757f3fSDimitry Andric bool hasInvalidOperand(std::function<unsigned(unsigned, unsigned)> GetRegIdx, 8285f757f3fSDimitry Andric bool SkipSrc = false) const { 8295f757f3fSDimitry Andric return getInvalidCompOperandIndex(GetRegIdx, SkipSrc).has_value(); 830bdd1243dSDimitry Andric } 831bdd1243dSDimitry Andric 832bdd1243dSDimitry Andric // Check VOPD operands constraints. 833bdd1243dSDimitry Andric // Return the index of an invalid component operand, if any. 8345f757f3fSDimitry Andric // If \p SkipSrc is set to true then constraints for source operands are not 8355f757f3fSDimitry Andric // checked. 836bdd1243dSDimitry Andric std::optional<unsigned> getInvalidCompOperandIndex( 8375f757f3fSDimitry Andric std::function<unsigned(unsigned, unsigned)> GetRegIdx, 8385f757f3fSDimitry Andric bool SkipSrc = false) const; 839bdd1243dSDimitry Andric 840bdd1243dSDimitry Andric private: 841bdd1243dSDimitry Andric RegIndices 842bdd1243dSDimitry Andric getRegIndices(unsigned ComponentIdx, 843bdd1243dSDimitry Andric std::function<unsigned(unsigned, unsigned)> GetRegIdx) const; 844bdd1243dSDimitry Andric }; 845bdd1243dSDimitry Andric 846bdd1243dSDimitry Andric } // namespace VOPD 847bdd1243dSDimitry Andric 848bdd1243dSDimitry Andric LLVM_READONLY 849bdd1243dSDimitry Andric std::pair<unsigned, unsigned> getVOPDComponents(unsigned VOPDOpcode); 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric LLVM_READONLY 852bdd1243dSDimitry Andric // Get properties of 2 single VOP1/VOP2 instructions 853bdd1243dSDimitry Andric // used as components to create a VOPD instruction. 854bdd1243dSDimitry Andric VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY); 855bdd1243dSDimitry Andric 856bdd1243dSDimitry Andric LLVM_READONLY 857bdd1243dSDimitry Andric // Get properties of VOPD X and Y components. 858bdd1243dSDimitry Andric VOPD::InstInfo 859bdd1243dSDimitry Andric getVOPDInstInfo(unsigned VOPDOpcode, const MCInstrInfo *InstrInfo); 860bdd1243dSDimitry Andric 861bdd1243dSDimitry Andric LLVM_READONLY 862bdd1243dSDimitry Andric bool isTrue16Inst(unsigned Opc); 863bdd1243dSDimitry Andric 864bdd1243dSDimitry Andric LLVM_READONLY 865*0fca6ea1SDimitry Andric bool isInvalidSingleUseConsumerInst(unsigned Opc); 866*0fca6ea1SDimitry Andric 867*0fca6ea1SDimitry Andric LLVM_READONLY 868*0fca6ea1SDimitry Andric bool isInvalidSingleUseProducerInst(unsigned Opc); 869*0fca6ea1SDimitry Andric 870*0fca6ea1SDimitry Andric LLVM_READONLY 87181ad6265SDimitry Andric unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc); 87281ad6265SDimitry Andric 87381ad6265SDimitry Andric LLVM_READONLY 87481ad6265SDimitry Andric unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc); 87581ad6265SDimitry Andric 876*0fca6ea1SDimitry Andric void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &Header, 8770b57cec5SDimitry Andric const MCSubtargetInfo *STI); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric bool isGroupSegment(const GlobalValue *GV); 8800b57cec5SDimitry Andric bool isGlobalSegment(const GlobalValue *GV); 8810b57cec5SDimitry Andric bool isReadOnlySegment(const GlobalValue *GV); 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric /// \returns True if constants should be emitted to .text section for given 8840b57cec5SDimitry Andric /// target triple \p TT, false otherwise. 8850b57cec5SDimitry Andric bool shouldEmitConstantsToTextSection(const Triple &TT); 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric /// \returns Integer value requested using \p F's \p Name attribute. 8880b57cec5SDimitry Andric /// 8890b57cec5SDimitry Andric /// \returns \p Default if attribute is not present. 8900b57cec5SDimitry Andric /// 8910b57cec5SDimitry Andric /// \returns \p Default and emits error if requested value cannot be converted 8920b57cec5SDimitry Andric /// to integer. 8930b57cec5SDimitry Andric int getIntegerAttribute(const Function &F, StringRef Name, int Default); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric /// \returns A pair of integer values requested using \p F's \p Name attribute 8960b57cec5SDimitry Andric /// in "first[,second]" format ("second" is optional unless \p OnlyFirstRequired 8970b57cec5SDimitry Andric /// is false). 8980b57cec5SDimitry Andric /// 8990b57cec5SDimitry Andric /// \returns \p Default if attribute is not present. 9000b57cec5SDimitry Andric /// 9010b57cec5SDimitry Andric /// \returns \p Default and emits error if one of the requested values cannot be 9020b57cec5SDimitry Andric /// converted to integer, or \p OnlyFirstRequired is false and "second" value is 9030b57cec5SDimitry Andric /// not present. 90406c3fb27SDimitry Andric std::pair<unsigned, unsigned> 90506c3fb27SDimitry Andric getIntegerPairAttribute(const Function &F, StringRef Name, 90606c3fb27SDimitry Andric std::pair<unsigned, unsigned> Default, 9070b57cec5SDimitry Andric bool OnlyFirstRequired = false); 9080b57cec5SDimitry Andric 909*0fca6ea1SDimitry Andric /// \returns Generate a vector of integer values requested using \p F's \p Name 910*0fca6ea1SDimitry Andric /// attribute. 911*0fca6ea1SDimitry Andric /// 912*0fca6ea1SDimitry Andric /// \returns true if exactly Size (>2) number of integers are found in the 913*0fca6ea1SDimitry Andric /// attribute. 914*0fca6ea1SDimitry Andric /// 915*0fca6ea1SDimitry Andric /// \returns false if any error occurs. 916*0fca6ea1SDimitry Andric SmallVector<unsigned> getIntegerVecAttribute(const Function &F, StringRef Name, 917*0fca6ea1SDimitry Andric unsigned Size); 918*0fca6ea1SDimitry Andric 9190b57cec5SDimitry Andric /// Represents the counter values to wait for in an s_waitcnt instruction. 9200b57cec5SDimitry Andric /// 9210b57cec5SDimitry Andric /// Large values (including the maximum possible integer) can be used to 9220b57cec5SDimitry Andric /// represent "don't care" waits. 9230b57cec5SDimitry Andric struct Waitcnt { 9247a6dacacSDimitry Andric unsigned LoadCnt = ~0u; // Corresponds to Vmcnt prior to gfx12. 9250b57cec5SDimitry Andric unsigned ExpCnt = ~0u; 9267a6dacacSDimitry Andric unsigned DsCnt = ~0u; // Corresponds to LGKMcnt prior to gfx12. 9277a6dacacSDimitry Andric unsigned StoreCnt = ~0u; // Corresponds to VScnt on gfx10/gfx11. 9287a6dacacSDimitry Andric unsigned SampleCnt = ~0u; // gfx12+ only. 9297a6dacacSDimitry Andric unsigned BvhCnt = ~0u; // gfx12+ only. 9307a6dacacSDimitry Andric unsigned KmCnt = ~0u; // gfx12+ only. 9310b57cec5SDimitry Andric 93281ad6265SDimitry Andric Waitcnt() = default; 9337a6dacacSDimitry Andric // Pre-gfx12 constructor. 9340b57cec5SDimitry Andric Waitcnt(unsigned VmCnt, unsigned ExpCnt, unsigned LgkmCnt, unsigned VsCnt) 9357a6dacacSDimitry Andric : LoadCnt(VmCnt), ExpCnt(ExpCnt), DsCnt(LgkmCnt), StoreCnt(VsCnt), 9367a6dacacSDimitry Andric SampleCnt(~0u), BvhCnt(~0u), KmCnt(~0u) {} 9370b57cec5SDimitry Andric 9387a6dacacSDimitry Andric // gfx12+ constructor. 9397a6dacacSDimitry Andric Waitcnt(unsigned LoadCnt, unsigned ExpCnt, unsigned DsCnt, unsigned StoreCnt, 9407a6dacacSDimitry Andric unsigned SampleCnt, unsigned BvhCnt, unsigned KmCnt) 9417a6dacacSDimitry Andric : LoadCnt(LoadCnt), ExpCnt(ExpCnt), DsCnt(DsCnt), StoreCnt(StoreCnt), 9427a6dacacSDimitry Andric SampleCnt(SampleCnt), BvhCnt(BvhCnt), KmCnt(KmCnt) {} 9430b57cec5SDimitry Andric 9447a6dacacSDimitry Andric bool hasWait() const { return StoreCnt != ~0u || hasWaitExceptStoreCnt(); } 9457a6dacacSDimitry Andric 9467a6dacacSDimitry Andric bool hasWaitExceptStoreCnt() const { 9477a6dacacSDimitry Andric return LoadCnt != ~0u || ExpCnt != ~0u || DsCnt != ~0u || 9487a6dacacSDimitry Andric SampleCnt != ~0u || BvhCnt != ~0u || KmCnt != ~0u; 949fe6060f1SDimitry Andric } 950fe6060f1SDimitry Andric 9517a6dacacSDimitry Andric bool hasWaitStoreCnt() const { return StoreCnt != ~0u; } 9527a6dacacSDimitry Andric 9530b57cec5SDimitry Andric Waitcnt combined(const Waitcnt &Other) const { 9547a6dacacSDimitry Andric // Does the right thing provided self and Other are either both pre-gfx12 9557a6dacacSDimitry Andric // or both gfx12+. 9567a6dacacSDimitry Andric return Waitcnt( 9577a6dacacSDimitry Andric std::min(LoadCnt, Other.LoadCnt), std::min(ExpCnt, Other.ExpCnt), 9587a6dacacSDimitry Andric std::min(DsCnt, Other.DsCnt), std::min(StoreCnt, Other.StoreCnt), 9597a6dacacSDimitry Andric std::min(SampleCnt, Other.SampleCnt), std::min(BvhCnt, Other.BvhCnt), 9607a6dacacSDimitry Andric std::min(KmCnt, Other.KmCnt)); 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric }; 9630b57cec5SDimitry Andric 9647a6dacacSDimitry Andric // The following methods are only meaningful on targets that support 9657a6dacacSDimitry Andric // S_WAITCNT. 9667a6dacacSDimitry Andric 9670b57cec5SDimitry Andric /// \returns Vmcnt bit mask for given isa \p Version. 9680b57cec5SDimitry Andric unsigned getVmcntBitMask(const IsaVersion &Version); 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric /// \returns Expcnt bit mask for given isa \p Version. 9710b57cec5SDimitry Andric unsigned getExpcntBitMask(const IsaVersion &Version); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric /// \returns Lgkmcnt bit mask for given isa \p Version. 9740b57cec5SDimitry Andric unsigned getLgkmcntBitMask(const IsaVersion &Version); 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric /// \returns Waitcnt bit mask for given isa \p Version. 9770b57cec5SDimitry Andric unsigned getWaitcntBitMask(const IsaVersion &Version); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric /// \returns Decoded Vmcnt from given \p Waitcnt for given isa \p Version. 9800b57cec5SDimitry Andric unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt); 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric /// \returns Decoded Expcnt from given \p Waitcnt for given isa \p Version. 9830b57cec5SDimitry Andric unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt); 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric /// \returns Decoded Lgkmcnt from given \p Waitcnt for given isa \p Version. 9860b57cec5SDimitry Andric unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt); 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric /// Decodes Vmcnt, Expcnt and Lgkmcnt from given \p Waitcnt for given isa 9890b57cec5SDimitry Andric /// \p Version, and writes decoded values into \p Vmcnt, \p Expcnt and 9907a6dacacSDimitry Andric /// \p Lgkmcnt respectively. Should not be used on gfx12+, the instruction 9917a6dacacSDimitry Andric /// which needs it is deprecated 9920b57cec5SDimitry Andric /// 9930b57cec5SDimitry Andric /// \details \p Vmcnt, \p Expcnt and \p Lgkmcnt are decoded as follows: 99481ad6265SDimitry Andric /// \p Vmcnt = \p Waitcnt[3:0] (pre-gfx9) 99581ad6265SDimitry Andric /// \p Vmcnt = \p Waitcnt[15:14,3:0] (gfx9,10) 9967a6dacacSDimitry Andric /// \p Vmcnt = \p Waitcnt[15:10] (gfx11) 99781ad6265SDimitry Andric /// \p Expcnt = \p Waitcnt[6:4] (pre-gfx11) 9987a6dacacSDimitry Andric /// \p Expcnt = \p Waitcnt[2:0] (gfx11) 99981ad6265SDimitry Andric /// \p Lgkmcnt = \p Waitcnt[11:8] (pre-gfx10) 100081ad6265SDimitry Andric /// \p Lgkmcnt = \p Waitcnt[13:8] (gfx10) 10017a6dacacSDimitry Andric /// \p Lgkmcnt = \p Waitcnt[9:4] (gfx11) 10027a6dacacSDimitry Andric /// 10030b57cec5SDimitry Andric void decodeWaitcnt(const IsaVersion &Version, unsigned Waitcnt, 10040b57cec5SDimitry Andric unsigned &Vmcnt, unsigned &Expcnt, unsigned &Lgkmcnt); 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric Waitcnt decodeWaitcnt(const IsaVersion &Version, unsigned Encoded); 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric /// \returns \p Waitcnt with encoded \p Vmcnt for given isa \p Version. 10090b57cec5SDimitry Andric unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt, 10100b57cec5SDimitry Andric unsigned Vmcnt); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric /// \returns \p Waitcnt with encoded \p Expcnt for given isa \p Version. 10130b57cec5SDimitry Andric unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt, 10140b57cec5SDimitry Andric unsigned Expcnt); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric /// \returns \p Waitcnt with encoded \p Lgkmcnt for given isa \p Version. 10170b57cec5SDimitry Andric unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt, 10180b57cec5SDimitry Andric unsigned Lgkmcnt); 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric /// Encodes \p Vmcnt, \p Expcnt and \p Lgkmcnt into Waitcnt for given isa 10217a6dacacSDimitry Andric /// \p Version. Should not be used on gfx12+, the instruction which needs 10227a6dacacSDimitry Andric /// it is deprecated 10230b57cec5SDimitry Andric /// 10240b57cec5SDimitry Andric /// \details \p Vmcnt, \p Expcnt and \p Lgkmcnt are encoded as follows: 102581ad6265SDimitry Andric /// Waitcnt[2:0] = \p Expcnt (gfx11+) 102681ad6265SDimitry Andric /// Waitcnt[3:0] = \p Vmcnt (pre-gfx9) 102781ad6265SDimitry Andric /// Waitcnt[3:0] = \p Vmcnt[3:0] (gfx9,10) 102881ad6265SDimitry Andric /// Waitcnt[6:4] = \p Expcnt (pre-gfx11) 10297a6dacacSDimitry Andric /// Waitcnt[9:4] = \p Lgkmcnt (gfx11) 103081ad6265SDimitry Andric /// Waitcnt[11:8] = \p Lgkmcnt (pre-gfx10) 103181ad6265SDimitry Andric /// Waitcnt[13:8] = \p Lgkmcnt (gfx10) 10327a6dacacSDimitry Andric /// Waitcnt[15:10] = \p Vmcnt (gfx11) 103381ad6265SDimitry Andric /// Waitcnt[15:14] = \p Vmcnt[5:4] (gfx9,10) 10340b57cec5SDimitry Andric /// 10350b57cec5SDimitry Andric /// \returns Waitcnt with encoded \p Vmcnt, \p Expcnt and \p Lgkmcnt for given 10360b57cec5SDimitry Andric /// isa \p Version. 10377a6dacacSDimitry Andric /// 10380b57cec5SDimitry Andric unsigned encodeWaitcnt(const IsaVersion &Version, 10390b57cec5SDimitry Andric unsigned Vmcnt, unsigned Expcnt, unsigned Lgkmcnt); 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric unsigned encodeWaitcnt(const IsaVersion &Version, const Waitcnt &Decoded); 10420b57cec5SDimitry Andric 10437a6dacacSDimitry Andric // The following methods are only meaningful on targets that support 10447a6dacacSDimitry Andric // S_WAIT_*CNT, introduced with gfx12. 10457a6dacacSDimitry Andric 10467a6dacacSDimitry Andric /// \returns Loadcnt bit mask for given isa \p Version. 10477a6dacacSDimitry Andric /// Returns 0 for versions that do not support LOADcnt 10487a6dacacSDimitry Andric unsigned getLoadcntBitMask(const IsaVersion &Version); 10497a6dacacSDimitry Andric 10507a6dacacSDimitry Andric /// \returns Samplecnt bit mask for given isa \p Version. 10517a6dacacSDimitry Andric /// Returns 0 for versions that do not support SAMPLEcnt 10527a6dacacSDimitry Andric unsigned getSamplecntBitMask(const IsaVersion &Version); 10537a6dacacSDimitry Andric 10547a6dacacSDimitry Andric /// \returns Bvhcnt bit mask for given isa \p Version. 10557a6dacacSDimitry Andric /// Returns 0 for versions that do not support BVHcnt 10567a6dacacSDimitry Andric unsigned getBvhcntBitMask(const IsaVersion &Version); 10577a6dacacSDimitry Andric 10587a6dacacSDimitry Andric /// \returns Dscnt bit mask for given isa \p Version. 10597a6dacacSDimitry Andric /// Returns 0 for versions that do not support DScnt 10607a6dacacSDimitry Andric unsigned getDscntBitMask(const IsaVersion &Version); 10617a6dacacSDimitry Andric 10627a6dacacSDimitry Andric /// \returns Dscnt bit mask for given isa \p Version. 10637a6dacacSDimitry Andric /// Returns 0 for versions that do not support KMcnt 10647a6dacacSDimitry Andric unsigned getKmcntBitMask(const IsaVersion &Version); 10657a6dacacSDimitry Andric 10667a6dacacSDimitry Andric /// \return STOREcnt or VScnt bit mask for given isa \p Version. 10677a6dacacSDimitry Andric /// returns 0 for versions that do not support STOREcnt or VScnt. 10687a6dacacSDimitry Andric /// STOREcnt and VScnt are the same counter, the name used 10697a6dacacSDimitry Andric /// depends on the ISA version. 10707a6dacacSDimitry Andric unsigned getStorecntBitMask(const IsaVersion &Version); 10717a6dacacSDimitry Andric 10727a6dacacSDimitry Andric // The following are only meaningful on targets that support 10737a6dacacSDimitry Andric // S_WAIT_LOADCNT_DSCNT and S_WAIT_STORECNT_DSCNT. 10747a6dacacSDimitry Andric 10757a6dacacSDimitry Andric /// \returns Decoded Waitcnt structure from given \p LoadcntDscnt for given 10767a6dacacSDimitry Andric /// isa \p Version. 10777a6dacacSDimitry Andric Waitcnt decodeLoadcntDscnt(const IsaVersion &Version, unsigned LoadcntDscnt); 10787a6dacacSDimitry Andric 10797a6dacacSDimitry Andric /// \returns Decoded Waitcnt structure from given \p StorecntDscnt for given 10807a6dacacSDimitry Andric /// isa \p Version. 10817a6dacacSDimitry Andric Waitcnt decodeStorecntDscnt(const IsaVersion &Version, unsigned StorecntDscnt); 10827a6dacacSDimitry Andric 10837a6dacacSDimitry Andric /// \returns \p Loadcnt and \p Dscnt components of \p Decoded encoded as an 10847a6dacacSDimitry Andric /// immediate that can be used with S_WAIT_LOADCNT_DSCNT for given isa 10857a6dacacSDimitry Andric /// \p Version. 10867a6dacacSDimitry Andric unsigned encodeLoadcntDscnt(const IsaVersion &Version, const Waitcnt &Decoded); 10877a6dacacSDimitry Andric 10887a6dacacSDimitry Andric /// \returns \p Storecnt and \p Dscnt components of \p Decoded encoded as an 10897a6dacacSDimitry Andric /// immediate that can be used with S_WAIT_STORECNT_DSCNT for given isa 10907a6dacacSDimitry Andric /// \p Version. 10917a6dacacSDimitry Andric unsigned encodeStorecntDscnt(const IsaVersion &Version, const Waitcnt &Decoded); 10927a6dacacSDimitry Andric 10930b57cec5SDimitry Andric namespace Hwreg { 10940b57cec5SDimitry Andric 1095*0fca6ea1SDimitry Andric using HwregId = EncodingField<5, 0>; 1096*0fca6ea1SDimitry Andric using HwregOffset = EncodingField<10, 6>; 10970b57cec5SDimitry Andric 1098*0fca6ea1SDimitry Andric struct HwregSize : EncodingField<15, 11, 32> { 1099*0fca6ea1SDimitry Andric using EncodingField::EncodingField; 1100*0fca6ea1SDimitry Andric constexpr uint64_t encode() const { return Value - 1; } 1101*0fca6ea1SDimitry Andric static ValueType decode(uint64_t Encoded) { return Encoded + 1; } 1102*0fca6ea1SDimitry Andric }; 11030b57cec5SDimitry Andric 1104*0fca6ea1SDimitry Andric using HwregEncoding = EncodingFields<HwregId, HwregOffset, HwregSize>; 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric } // namespace Hwreg 11070b57cec5SDimitry Andric 110881ad6265SDimitry Andric namespace DepCtr { 110981ad6265SDimitry Andric 111081ad6265SDimitry Andric int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI); 111181ad6265SDimitry Andric int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask, 111281ad6265SDimitry Andric const MCSubtargetInfo &STI); 111381ad6265SDimitry Andric bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal, 111481ad6265SDimitry Andric const MCSubtargetInfo &STI); 111581ad6265SDimitry Andric bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val, 111681ad6265SDimitry Andric bool &IsDefault, const MCSubtargetInfo &STI); 111781ad6265SDimitry Andric 111806c3fb27SDimitry Andric /// \returns Decoded VaVdst from given immediate \p Encoded. 111906c3fb27SDimitry Andric unsigned decodeFieldVaVdst(unsigned Encoded); 112006c3fb27SDimitry Andric 112106c3fb27SDimitry Andric /// \returns Decoded VmVsrc from given immediate \p Encoded. 112206c3fb27SDimitry Andric unsigned decodeFieldVmVsrc(unsigned Encoded); 112306c3fb27SDimitry Andric 112406c3fb27SDimitry Andric /// \returns Decoded SaSdst from given immediate \p Encoded. 112506c3fb27SDimitry Andric unsigned decodeFieldSaSdst(unsigned Encoded); 112606c3fb27SDimitry Andric 112706c3fb27SDimitry Andric /// \returns \p VmVsrc as an encoded Depctr immediate. 112806c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned VmVsrc); 112906c3fb27SDimitry Andric 113006c3fb27SDimitry Andric /// \returns \p Encoded combined with encoded \p VmVsrc. 113106c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned Encoded, unsigned VmVsrc); 113206c3fb27SDimitry Andric 113306c3fb27SDimitry Andric /// \returns \p VaVdst as an encoded Depctr immediate. 113406c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned VaVdst); 113506c3fb27SDimitry Andric 113606c3fb27SDimitry Andric /// \returns \p Encoded combined with encoded \p VaVdst. 113706c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned Encoded, unsigned VaVdst); 113806c3fb27SDimitry Andric 113906c3fb27SDimitry Andric /// \returns \p SaSdst as an encoded Depctr immediate. 114006c3fb27SDimitry Andric unsigned encodeFieldSaSdst(unsigned SaSdst); 114106c3fb27SDimitry Andric 114206c3fb27SDimitry Andric /// \returns \p Encoded combined with encoded \p SaSdst. 114306c3fb27SDimitry Andric unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst); 114406c3fb27SDimitry Andric 114581ad6265SDimitry Andric } // namespace DepCtr 114681ad6265SDimitry Andric 1147e8d8bef9SDimitry Andric namespace Exp { 1148e8d8bef9SDimitry Andric 1149e8d8bef9SDimitry Andric bool getTgtName(unsigned Id, StringRef &Name, int &Index); 1150e8d8bef9SDimitry Andric 1151e8d8bef9SDimitry Andric LLVM_READONLY 1152e8d8bef9SDimitry Andric unsigned getTgtId(const StringRef Name); 1153e8d8bef9SDimitry Andric 1154e8d8bef9SDimitry Andric LLVM_READNONE 1155e8d8bef9SDimitry Andric bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI); 1156e8d8bef9SDimitry Andric 1157e8d8bef9SDimitry Andric } // namespace Exp 1158e8d8bef9SDimitry Andric 1159e8d8bef9SDimitry Andric namespace MTBUFFormat { 1160e8d8bef9SDimitry Andric 1161e8d8bef9SDimitry Andric LLVM_READNONE 1162e8d8bef9SDimitry Andric int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt); 1163e8d8bef9SDimitry Andric 1164e8d8bef9SDimitry Andric void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt); 1165e8d8bef9SDimitry Andric 1166e8d8bef9SDimitry Andric int64_t getDfmt(const StringRef Name); 1167e8d8bef9SDimitry Andric 1168e8d8bef9SDimitry Andric StringRef getDfmtName(unsigned Id); 1169e8d8bef9SDimitry Andric 1170e8d8bef9SDimitry Andric int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI); 1171e8d8bef9SDimitry Andric 1172e8d8bef9SDimitry Andric StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI); 1173e8d8bef9SDimitry Andric 1174e8d8bef9SDimitry Andric bool isValidDfmtNfmt(unsigned Val, const MCSubtargetInfo &STI); 1175e8d8bef9SDimitry Andric 1176e8d8bef9SDimitry Andric bool isValidNfmt(unsigned Val, const MCSubtargetInfo &STI); 1177e8d8bef9SDimitry Andric 117881ad6265SDimitry Andric int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI); 1179e8d8bef9SDimitry Andric 118081ad6265SDimitry Andric StringRef getUnifiedFormatName(unsigned Id, const MCSubtargetInfo &STI); 1181e8d8bef9SDimitry Andric 118281ad6265SDimitry Andric bool isValidUnifiedFormat(unsigned Val, const MCSubtargetInfo &STI); 1183e8d8bef9SDimitry Andric 118481ad6265SDimitry Andric int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt, 118581ad6265SDimitry Andric const MCSubtargetInfo &STI); 1186e8d8bef9SDimitry Andric 1187e8d8bef9SDimitry Andric bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI); 1188e8d8bef9SDimitry Andric 1189e8d8bef9SDimitry Andric unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI); 1190e8d8bef9SDimitry Andric 1191e8d8bef9SDimitry Andric } // namespace MTBUFFormat 1192e8d8bef9SDimitry Andric 11930b57cec5SDimitry Andric namespace SendMsg { 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric LLVM_READNONE 119681ad6265SDimitry Andric bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI); 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric LLVM_READNONE 1199fe6060f1SDimitry Andric bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI, 1200fe6060f1SDimitry Andric bool Strict = true); 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric LLVM_READNONE 1203fe6060f1SDimitry Andric bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, 1204fe6060f1SDimitry Andric const MCSubtargetInfo &STI, bool Strict = true); 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric LLVM_READNONE 120781ad6265SDimitry Andric bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric LLVM_READNONE 121081ad6265SDimitry Andric bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI); 12110b57cec5SDimitry Andric 121281ad6265SDimitry Andric void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId, 121381ad6265SDimitry Andric uint16_t &StreamId, const MCSubtargetInfo &STI); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric LLVM_READNONE 12160b57cec5SDimitry Andric uint64_t encodeMsg(uint64_t MsgId, 12170b57cec5SDimitry Andric uint64_t OpId, 12180b57cec5SDimitry Andric uint64_t StreamId); 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric } // namespace SendMsg 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric unsigned getInitialPSInputAddr(const Function &F); 12240b57cec5SDimitry Andric 1225fe6060f1SDimitry Andric bool getHasColorExport(const Function &F); 1226fe6060f1SDimitry Andric 1227fe6060f1SDimitry Andric bool getHasDepthExport(const Function &F); 1228fe6060f1SDimitry Andric 12290b57cec5SDimitry Andric LLVM_READNONE 12300b57cec5SDimitry Andric bool isShader(CallingConv::ID CC); 12310b57cec5SDimitry Andric 12320b57cec5SDimitry Andric LLVM_READNONE 1233e8d8bef9SDimitry Andric bool isGraphics(CallingConv::ID CC); 1234e8d8bef9SDimitry Andric 1235e8d8bef9SDimitry Andric LLVM_READNONE 12360b57cec5SDimitry Andric bool isCompute(CallingConv::ID CC); 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric LLVM_READNONE 12390b57cec5SDimitry Andric bool isEntryFunctionCC(CallingConv::ID CC); 12400b57cec5SDimitry Andric 1241e8d8bef9SDimitry Andric // These functions are considered entrypoints into the current module, i.e. they 1242e8d8bef9SDimitry Andric // are allowed to be called from outside the current module. This is different 1243e8d8bef9SDimitry Andric // from isEntryFunctionCC, which is only true for functions that are entered by 1244e8d8bef9SDimitry Andric // the hardware. Module entry points include all entry functions but also 1245e8d8bef9SDimitry Andric // include functions that can be called from other functions inside or outside 1246e8d8bef9SDimitry Andric // the current module. Module entry functions are allowed to allocate LDS. 1247e8d8bef9SDimitry Andric LLVM_READNONE 1248e8d8bef9SDimitry Andric bool isModuleEntryFunctionCC(CallingConv::ID CC); 1249e8d8bef9SDimitry Andric 12505f757f3fSDimitry Andric LLVM_READNONE 12515f757f3fSDimitry Andric bool isChainCC(CallingConv::ID CC); 12525f757f3fSDimitry Andric 125381ad6265SDimitry Andric bool isKernelCC(const Function *Func); 125481ad6265SDimitry Andric 12550b57cec5SDimitry Andric // FIXME: Remove this when calling conventions cleaned up 12560b57cec5SDimitry Andric LLVM_READNONE 12570b57cec5SDimitry Andric inline bool isKernel(CallingConv::ID CC) { 12580b57cec5SDimitry Andric switch (CC) { 12590b57cec5SDimitry Andric case CallingConv::AMDGPU_KERNEL: 12600b57cec5SDimitry Andric case CallingConv::SPIR_KERNEL: 12610b57cec5SDimitry Andric return true; 12620b57cec5SDimitry Andric default: 12630b57cec5SDimitry Andric return false; 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric bool hasXNACK(const MCSubtargetInfo &STI); 12680b57cec5SDimitry Andric bool hasSRAMECC(const MCSubtargetInfo &STI); 12690b57cec5SDimitry Andric bool hasMIMG_R128(const MCSubtargetInfo &STI); 1270bdd1243dSDimitry Andric bool hasA16(const MCSubtargetInfo &STI); 12715ffd83dbSDimitry Andric bool hasG16(const MCSubtargetInfo &STI); 12720b57cec5SDimitry Andric bool hasPackedD16(const MCSubtargetInfo &STI); 12735f757f3fSDimitry Andric bool hasGDS(const MCSubtargetInfo &STI); 12745f757f3fSDimitry Andric unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler = false); 12755f757f3fSDimitry Andric unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI); 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric bool isSI(const MCSubtargetInfo &STI); 12780b57cec5SDimitry Andric bool isCI(const MCSubtargetInfo &STI); 12790b57cec5SDimitry Andric bool isVI(const MCSubtargetInfo &STI); 12800b57cec5SDimitry Andric bool isGFX9(const MCSubtargetInfo &STI); 128181ad6265SDimitry Andric bool isGFX9_GFX10(const MCSubtargetInfo &STI); 12825f757f3fSDimitry Andric bool isGFX9_GFX10_GFX11(const MCSubtargetInfo &STI); 128381ad6265SDimitry Andric bool isGFX8_GFX9_GFX10(const MCSubtargetInfo &STI); 128481ad6265SDimitry Andric bool isGFX8Plus(const MCSubtargetInfo &STI); 1285e8d8bef9SDimitry Andric bool isGFX9Plus(const MCSubtargetInfo &STI); 1286*0fca6ea1SDimitry Andric bool isNotGFX9Plus(const MCSubtargetInfo &STI); 12870b57cec5SDimitry Andric bool isGFX10(const MCSubtargetInfo &STI); 12885f757f3fSDimitry Andric bool isGFX10_GFX11(const MCSubtargetInfo &STI); 1289e8d8bef9SDimitry Andric bool isGFX10Plus(const MCSubtargetInfo &STI); 129081ad6265SDimitry Andric bool isNotGFX10Plus(const MCSubtargetInfo &STI); 129181ad6265SDimitry Andric bool isGFX10Before1030(const MCSubtargetInfo &STI); 129281ad6265SDimitry Andric bool isGFX11(const MCSubtargetInfo &STI); 129381ad6265SDimitry Andric bool isGFX11Plus(const MCSubtargetInfo &STI); 12945f757f3fSDimitry Andric bool isGFX12(const MCSubtargetInfo &STI); 12955f757f3fSDimitry Andric bool isGFX12Plus(const MCSubtargetInfo &STI); 12965f757f3fSDimitry Andric bool isNotGFX12Plus(const MCSubtargetInfo &STI); 129781ad6265SDimitry Andric bool isNotGFX11Plus(const MCSubtargetInfo &STI); 12985ffd83dbSDimitry Andric bool isGCN3Encoding(const MCSubtargetInfo &STI); 1299fe6060f1SDimitry Andric bool isGFX10_AEncoding(const MCSubtargetInfo &STI); 13005ffd83dbSDimitry Andric bool isGFX10_BEncoding(const MCSubtargetInfo &STI); 13015ffd83dbSDimitry Andric bool hasGFX10_3Insts(const MCSubtargetInfo &STI); 13025f757f3fSDimitry Andric bool isGFX10_3_GFX11(const MCSubtargetInfo &STI); 1303fe6060f1SDimitry Andric bool isGFX90A(const MCSubtargetInfo &STI); 130481ad6265SDimitry Andric bool isGFX940(const MCSubtargetInfo &STI); 1305fe6060f1SDimitry Andric bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI); 130681ad6265SDimitry Andric bool hasMAIInsts(const MCSubtargetInfo &STI); 130781ad6265SDimitry Andric bool hasVOPD(const MCSubtargetInfo &STI); 13085f757f3fSDimitry Andric bool hasDPPSrc1SGPR(const MCSubtargetInfo &STI); 130981ad6265SDimitry Andric int getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR, int32_t ArgNumVGPR); 13105f757f3fSDimitry Andric unsigned hasKernargPreload(const MCSubtargetInfo &STI); 1311*0fca6ea1SDimitry Andric bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST); 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric /// Is Reg - scalar register 13140b57cec5SDimitry Andric bool isSGPR(unsigned Reg, const MCRegisterInfo* TRI); 13150b57cec5SDimitry Andric 13165f757f3fSDimitry Andric /// \returns if \p Reg occupies the high 16-bits of a 32-bit register. 13175f757f3fSDimitry Andric /// The bit indicating isHi is the LSB of the encoding. 13185f757f3fSDimitry Andric bool isHi(unsigned Reg, const MCRegisterInfo &MRI); 13195f757f3fSDimitry Andric 13200b57cec5SDimitry Andric /// If \p Reg is a pseudo reg, return the correct hardware register given 13210b57cec5SDimitry Andric /// \p STI otherwise return \p Reg. 13220b57cec5SDimitry Andric unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI); 13230b57cec5SDimitry Andric 13240b57cec5SDimitry Andric /// Convert hardware register \p Reg to a pseudo register 13250b57cec5SDimitry Andric LLVM_READNONE 13260b57cec5SDimitry Andric unsigned mc2PseudoReg(unsigned Reg); 13270b57cec5SDimitry Andric 1328bdd1243dSDimitry Andric LLVM_READNONE 1329bdd1243dSDimitry Andric bool isInlineValue(unsigned Reg); 1330bdd1243dSDimitry Andric 1331bdd1243dSDimitry Andric /// Is this an AMDGPU specific source operand? These include registers, 1332bdd1243dSDimitry Andric /// inline constants, literals and mandatory literals (KImm). 13330b57cec5SDimitry Andric bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo); 13340b57cec5SDimitry Andric 1335bdd1243dSDimitry Andric /// Is this a KImm operand? 1336bdd1243dSDimitry Andric bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo); 1337bdd1243dSDimitry Andric 13380b57cec5SDimitry Andric /// Is this floating-point operand? 13390b57cec5SDimitry Andric bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo); 13400b57cec5SDimitry Andric 1341349cc55cSDimitry Andric /// Does this operand support only inlinable literals? 13420b57cec5SDimitry Andric bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo); 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric /// Get the size in bits of a register from the register class \p RC. 13450b57cec5SDimitry Andric unsigned getRegBitWidth(unsigned RCID); 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric /// Get the size in bits of a register from the register class \p RC. 13480b57cec5SDimitry Andric unsigned getRegBitWidth(const MCRegisterClass &RC); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric /// Get size of register operand 13510b57cec5SDimitry Andric unsigned getRegOperandSize(const MCRegisterInfo *MRI, const MCInstrDesc &Desc, 13520b57cec5SDimitry Andric unsigned OpNo); 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric LLVM_READNONE 13550b57cec5SDimitry Andric inline unsigned getOperandSize(const MCOperandInfo &OpInfo) { 13560b57cec5SDimitry Andric switch (OpInfo.OperandType) { 13570b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT32: 13580b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32: 1359349cc55cSDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED: 13600b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT32: 13610b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP32: 13620b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 13630b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1364fe6060f1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2INT32: 1365fe6060f1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2FP32: 1366fe6060f1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2INT32: 1367fe6060f1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2FP32: 1368349cc55cSDimitry Andric case AMDGPU::OPERAND_KIMM32: 1369349cc55cSDimitry Andric case AMDGPU::OPERAND_KIMM16: // mandatory literal is always size 4 13705f757f3fSDimitry Andric case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32: 13710b57cec5SDimitry Andric return 4; 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT64: 13740b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP64: 13750b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT64: 13760b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1377fe6060f1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP64: 13780b57cec5SDimitry Andric return 8; 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT16: 1381*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_BF16: 13820b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP16: 1383*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_BF16_DEFERRED: 1384349cc55cSDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED: 13850b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1386*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_BF16: 13870b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP16: 13880b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1389*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2BF16: 13900b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 13910b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1392*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_BF16: 13930b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 13940b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1395*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2BF16: 13960b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 13970b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2INT16: 1398*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2BF16: 13990b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2FP16: 14000b57cec5SDimitry Andric return 2; 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric default: 14030b57cec5SDimitry Andric llvm_unreachable("unhandled operand type"); 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric LLVM_READNONE 14080b57cec5SDimitry Andric inline unsigned getOperandSize(const MCInstrDesc &Desc, unsigned OpNo) { 1409bdd1243dSDimitry Andric return getOperandSize(Desc.operands()[OpNo]); 14100b57cec5SDimitry Andric } 14110b57cec5SDimitry Andric 14125ffd83dbSDimitry Andric /// Is this literal inlinable, and not one of the values intended for floating 14135ffd83dbSDimitry Andric /// point values. 14145ffd83dbSDimitry Andric LLVM_READNONE 14155ffd83dbSDimitry Andric inline bool isInlinableIntLiteral(int64_t Literal) { 14165ffd83dbSDimitry Andric return Literal >= -16 && Literal <= 64; 14175ffd83dbSDimitry Andric } 14185ffd83dbSDimitry Andric 14190b57cec5SDimitry Andric /// Is this literal inlinable 14200b57cec5SDimitry Andric LLVM_READNONE 14210b57cec5SDimitry Andric bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi); 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric LLVM_READNONE 14240b57cec5SDimitry Andric bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi); 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric LLVM_READNONE 1427*0fca6ea1SDimitry Andric bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi); 1428*0fca6ea1SDimitry Andric 1429*0fca6ea1SDimitry Andric LLVM_READNONE 1430*0fca6ea1SDimitry Andric bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi); 1431*0fca6ea1SDimitry Andric 1432*0fca6ea1SDimitry Andric LLVM_READNONE 1433*0fca6ea1SDimitry Andric bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi); 1434*0fca6ea1SDimitry Andric 1435*0fca6ea1SDimitry Andric LLVM_READNONE 1436*0fca6ea1SDimitry Andric bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric LLVM_READNONE 14391db9f3b2SDimitry Andric std::optional<unsigned> getInlineEncodingV2I16(uint32_t Literal); 14400b57cec5SDimitry Andric 14415ffd83dbSDimitry Andric LLVM_READNONE 1442*0fca6ea1SDimitry Andric std::optional<unsigned> getInlineEncodingV2BF16(uint32_t Literal); 1443*0fca6ea1SDimitry Andric 1444*0fca6ea1SDimitry Andric LLVM_READNONE 14451db9f3b2SDimitry Andric std::optional<unsigned> getInlineEncodingV2F16(uint32_t Literal); 14465ffd83dbSDimitry Andric 144716d6b3b3SDimitry Andric LLVM_READNONE 14481db9f3b2SDimitry Andric bool isInlinableLiteralV216(uint32_t Literal, uint8_t OpType); 14495f757f3fSDimitry Andric 14505f757f3fSDimitry Andric LLVM_READNONE 14511db9f3b2SDimitry Andric bool isInlinableLiteralV2I16(uint32_t Literal); 14521db9f3b2SDimitry Andric 14531db9f3b2SDimitry Andric LLVM_READNONE 1454*0fca6ea1SDimitry Andric bool isInlinableLiteralV2BF16(uint32_t Literal); 1455*0fca6ea1SDimitry Andric 1456*0fca6ea1SDimitry Andric LLVM_READNONE 14571db9f3b2SDimitry Andric bool isInlinableLiteralV2F16(uint32_t Literal); 145816d6b3b3SDimitry Andric 14595f757f3fSDimitry Andric LLVM_READNONE 14605f757f3fSDimitry Andric bool isValid32BitLiteral(uint64_t Val, bool IsFP64); 14615f757f3fSDimitry Andric 14620b57cec5SDimitry Andric bool isArgPassedInSGPR(const Argument *Arg); 14630b57cec5SDimitry Andric 146406c3fb27SDimitry Andric bool isArgPassedInSGPR(const CallBase *CB, unsigned ArgNo); 146506c3fb27SDimitry Andric 14665ffd83dbSDimitry Andric LLVM_READONLY 14675ffd83dbSDimitry Andric bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST, 14685ffd83dbSDimitry Andric int64_t EncodedOffset); 14695ffd83dbSDimitry Andric 14705ffd83dbSDimitry Andric LLVM_READONLY 14715ffd83dbSDimitry Andric bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST, 14725ffd83dbSDimitry Andric int64_t EncodedOffset, 14735ffd83dbSDimitry Andric bool IsBuffer); 14745ffd83dbSDimitry Andric 14755ffd83dbSDimitry Andric /// Convert \p ByteOffset to dwords if the subtarget uses dword SMRD immediate 14765ffd83dbSDimitry Andric /// offsets. 14775ffd83dbSDimitry Andric uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset); 14785ffd83dbSDimitry Andric 14795ffd83dbSDimitry Andric /// \returns The encoding that will be used for \p ByteOffset in the 1480bdd1243dSDimitry Andric /// SMRD offset field, or std::nullopt if it won't fit. On GFX9 and GFX10 14815ffd83dbSDimitry Andric /// S_LOAD instructions have a signed offset, on other subtargets it is 14825ffd83dbSDimitry Andric /// unsigned. S_BUFFER has an unsigned offset for all subtargets. 1483bdd1243dSDimitry Andric std::optional<int64_t> getSMRDEncodedOffset(const MCSubtargetInfo &ST, 1484*0fca6ea1SDimitry Andric int64_t ByteOffset, bool IsBuffer, 1485*0fca6ea1SDimitry Andric bool HasSOffset = false); 14865ffd83dbSDimitry Andric 14875ffd83dbSDimitry Andric /// \return The encoding that can be used for a 32-bit literal offset in an SMRD 14885ffd83dbSDimitry Andric /// instruction. This is only useful on CI.s 1489bdd1243dSDimitry Andric std::optional<int64_t> getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, 14905ffd83dbSDimitry Andric int64_t ByteOffset); 14910b57cec5SDimitry Andric 14925f757f3fSDimitry Andric /// For pre-GFX12 FLAT instructions the offset must be positive; 1493e8d8bef9SDimitry Andric /// MSB is ignored and forced to zero. 1494e8d8bef9SDimitry Andric /// 1495bdd1243dSDimitry Andric /// \return The number of bits available for the signed offset field in flat 1496bdd1243dSDimitry Andric /// instructions. Note that some forms of the instruction disallow negative 1497bdd1243dSDimitry Andric /// offsets. 1498bdd1243dSDimitry Andric unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST); 1499e8d8bef9SDimitry Andric 15000b57cec5SDimitry Andric /// \returns true if this offset is small enough to fit in the SMRD 15010b57cec5SDimitry Andric /// offset field. \p ByteOffset should be the offset in bytes and 15020b57cec5SDimitry Andric /// not the encoded offset. 15030b57cec5SDimitry Andric bool isLegalSMRDImmOffset(const MCSubtargetInfo &ST, int64_t ByteOffset); 15040b57cec5SDimitry Andric 1505fe6060f1SDimitry Andric LLVM_READNONE 15065f757f3fSDimitry Andric inline bool isLegalDPALU_DPPControl(unsigned DC) { 1507fe6060f1SDimitry Andric return DC >= DPP::ROW_NEWBCAST_FIRST && DC <= DPP::ROW_NEWBCAST_LAST; 1508fe6060f1SDimitry Andric } 1509fe6060f1SDimitry Andric 15105f757f3fSDimitry Andric /// \returns true if an instruction may have a 64-bit VGPR operand. 15115f757f3fSDimitry Andric bool hasAny64BitVGPROperands(const MCInstrDesc &OpDesc); 15125f757f3fSDimitry Andric 15135f757f3fSDimitry Andric /// \returns true if an instruction is a DP ALU DPP. 15145f757f3fSDimitry Andric bool isDPALU_DPP(const MCInstrDesc &OpDesc); 15155f757f3fSDimitry Andric 15160b57cec5SDimitry Andric /// \returns true if the intrinsic is divergent 15170b57cec5SDimitry Andric bool isIntrinsicSourceOfDivergence(unsigned IntrID); 15180b57cec5SDimitry Andric 151906c3fb27SDimitry Andric /// \returns true if the intrinsic is uniform 152006c3fb27SDimitry Andric bool isIntrinsicAlwaysUniform(unsigned IntrID); 15210b57cec5SDimitry Andric 1522*0fca6ea1SDimitry Andric /// \returns lds block size in terms of dwords. \p 1523*0fca6ea1SDimitry Andric /// This is used to calculate the lds size encoded for PAL metadata 3.0+ which 1524*0fca6ea1SDimitry Andric /// must be defined in terms of bytes. 1525*0fca6ea1SDimitry Andric unsigned getLdsDwGranularity(const MCSubtargetInfo &ST); 1526*0fca6ea1SDimitry Andric 15270b57cec5SDimitry Andric } // end namespace AMDGPU 1528e8d8bef9SDimitry Andric 1529e8d8bef9SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 1530e8d8bef9SDimitry Andric const AMDGPU::IsaInfo::TargetIDSetting S); 1531e8d8bef9SDimitry Andric 15320b57cec5SDimitry Andric } // end namespace llvm 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H 1535