109467b48Spatrick //===- AMDGPUBaseInfo.h - Top level definitions for AMDGPU ------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H
1009467b48Spatrick #define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H
1109467b48Spatrick 
1209467b48Spatrick #include "SIDefines.h"
13*d415bd75Srobert #include "llvm/ADT/FloatingPointMode.h"
1409467b48Spatrick #include "llvm/IR/CallingConv.h"
15097a140dSpatrick #include "llvm/Support/Alignment.h"
16*d415bd75Srobert #include <array>
17*d415bd75Srobert #include <functional>
18*d415bd75Srobert #include <utility>
1973471bf0Spatrick 
2073471bf0Spatrick struct amd_kernel_code_t;
2109467b48Spatrick 
2209467b48Spatrick namespace llvm {
2309467b48Spatrick 
2473471bf0Spatrick struct Align;
2509467b48Spatrick class Argument;
2609467b48Spatrick class Function;
2709467b48Spatrick class GCNSubtarget;
2809467b48Spatrick class GlobalValue;
29*d415bd75Srobert class MCInstrInfo;
3009467b48Spatrick class MCRegisterClass;
3109467b48Spatrick class MCRegisterInfo;
3209467b48Spatrick class MCSubtargetInfo;
33097a140dSpatrick class StringRef;
3409467b48Spatrick class Triple;
35*d415bd75Srobert class raw_ostream;
3609467b48Spatrick 
3773471bf0Spatrick namespace amdhsa {
3873471bf0Spatrick struct kernel_descriptor_t;
3973471bf0Spatrick }
4073471bf0Spatrick 
4109467b48Spatrick namespace AMDGPU {
4209467b48Spatrick 
4373471bf0Spatrick struct IsaVersion;
4473471bf0Spatrick 
4573471bf0Spatrick /// \returns HSA OS ABI Version identification.
46*d415bd75Srobert std::optional<uint8_t> getHsaAbiVersion(const MCSubtargetInfo *STI);
4773471bf0Spatrick /// \returns True if HSA OS ABI Version identification is 2,
4873471bf0Spatrick /// false otherwise.
4973471bf0Spatrick bool isHsaAbiVersion2(const MCSubtargetInfo *STI);
5073471bf0Spatrick /// \returns True if HSA OS ABI Version identification is 3,
5173471bf0Spatrick /// false otherwise.
5273471bf0Spatrick bool isHsaAbiVersion3(const MCSubtargetInfo *STI);
5373471bf0Spatrick /// \returns True if HSA OS ABI Version identification is 4,
5473471bf0Spatrick /// false otherwise.
5573471bf0Spatrick bool isHsaAbiVersion4(const MCSubtargetInfo *STI);
56*d415bd75Srobert /// \returns True if HSA OS ABI Version identification is 5,
5773471bf0Spatrick /// false otherwise.
58*d415bd75Srobert bool isHsaAbiVersion5(const MCSubtargetInfo *STI);
59*d415bd75Srobert /// \returns True if HSA OS ABI Version identification is 3 and above,
60*d415bd75Srobert /// false otherwise.
61*d415bd75Srobert bool isHsaAbiVersion3AndAbove(const MCSubtargetInfo *STI);
62*d415bd75Srobert 
63*d415bd75Srobert /// \returns The offset of the multigrid_sync_arg argument from implicitarg_ptr
64*d415bd75Srobert unsigned getMultigridSyncArgImplicitArgPosition();
65*d415bd75Srobert 
66*d415bd75Srobert /// \returns The offset of the hostcall pointer argument from implicitarg_ptr
67*d415bd75Srobert unsigned getHostcallImplicitArgPosition();
68*d415bd75Srobert 
69*d415bd75Srobert unsigned getDefaultQueueImplicitArgPosition();
70*d415bd75Srobert unsigned getCompletionActionImplicitArgPosition();
71*d415bd75Srobert 
72*d415bd75Srobert /// \returns Code object version.
73*d415bd75Srobert unsigned getAmdhsaCodeObjectVersion();
7473471bf0Spatrick 
7509467b48Spatrick struct GcnBufferFormatInfo {
7609467b48Spatrick   unsigned Format;
7709467b48Spatrick   unsigned BitsPerComp;
7809467b48Spatrick   unsigned NumComponents;
7909467b48Spatrick   unsigned NumFormat;
8009467b48Spatrick   unsigned DataFormat;
8109467b48Spatrick };
8209467b48Spatrick 
83*d415bd75Srobert struct MAIInstInfo {
84*d415bd75Srobert   uint16_t Opcode;
85*d415bd75Srobert   bool is_dgemm;
86*d415bd75Srobert   bool is_gfx940_xdl;
87*d415bd75Srobert };
88*d415bd75Srobert 
8909467b48Spatrick #define GET_MIMGBaseOpcode_DECL
9009467b48Spatrick #define GET_MIMGDim_DECL
9109467b48Spatrick #define GET_MIMGEncoding_DECL
9209467b48Spatrick #define GET_MIMGLZMapping_DECL
9309467b48Spatrick #define GET_MIMGMIPMapping_DECL
94*d415bd75Srobert #define GET_MIMGBiASMapping_DECL
95*d415bd75Srobert #define GET_MAIInstInfoTable_DECL
9609467b48Spatrick #include "AMDGPUGenSearchableTables.inc"
9709467b48Spatrick 
9809467b48Spatrick namespace IsaInfo {
9909467b48Spatrick 
10009467b48Spatrick enum {
10109467b48Spatrick   // The closed Vulkan driver sets 96, which limits the wave count to 8 but
10209467b48Spatrick   // doesn't spill SGPRs as much as when 80 is set.
10309467b48Spatrick   FIXED_NUM_SGPRS_FOR_INIT_BUG = 96,
10409467b48Spatrick   TRAP_NUM_SGPRS = 16
10509467b48Spatrick };
10609467b48Spatrick 
10773471bf0Spatrick enum class TargetIDSetting {
10873471bf0Spatrick   Unsupported,
10973471bf0Spatrick   Any,
11073471bf0Spatrick   Off,
11173471bf0Spatrick   On
11273471bf0Spatrick };
11309467b48Spatrick 
11473471bf0Spatrick class AMDGPUTargetID {
11573471bf0Spatrick private:
11673471bf0Spatrick   const MCSubtargetInfo &STI;
11773471bf0Spatrick   TargetIDSetting XnackSetting;
11873471bf0Spatrick   TargetIDSetting SramEccSetting;
11973471bf0Spatrick 
12073471bf0Spatrick public:
12173471bf0Spatrick   explicit AMDGPUTargetID(const MCSubtargetInfo &STI);
12273471bf0Spatrick   ~AMDGPUTargetID() = default;
12373471bf0Spatrick 
12473471bf0Spatrick   /// \return True if the current xnack setting is not "Unsupported".
isXnackSupported()12573471bf0Spatrick   bool isXnackSupported() const {
12673471bf0Spatrick     return XnackSetting != TargetIDSetting::Unsupported;
12773471bf0Spatrick   }
12873471bf0Spatrick 
12973471bf0Spatrick   /// \returns True if the current xnack setting is "On" or "Any".
isXnackOnOrAny()13073471bf0Spatrick   bool isXnackOnOrAny() const {
13173471bf0Spatrick     return XnackSetting == TargetIDSetting::On ||
13273471bf0Spatrick         XnackSetting == TargetIDSetting::Any;
13373471bf0Spatrick   }
13473471bf0Spatrick 
13573471bf0Spatrick   /// \returns True if current xnack setting is "On" or "Off",
13609467b48Spatrick   /// false otherwise.
isXnackOnOrOff()13773471bf0Spatrick   bool isXnackOnOrOff() const {
13873471bf0Spatrick     return getXnackSetting() == TargetIDSetting::On ||
13973471bf0Spatrick         getXnackSetting() == TargetIDSetting::Off;
14073471bf0Spatrick   }
14173471bf0Spatrick 
14273471bf0Spatrick   /// \returns The current xnack TargetIDSetting, possible options are
14373471bf0Spatrick   /// "Unsupported", "Any", "Off", and "On".
getXnackSetting()14473471bf0Spatrick   TargetIDSetting getXnackSetting() const {
14573471bf0Spatrick     return XnackSetting;
14673471bf0Spatrick   }
14773471bf0Spatrick 
14873471bf0Spatrick   /// Sets xnack setting to \p NewXnackSetting.
setXnackSetting(TargetIDSetting NewXnackSetting)14973471bf0Spatrick   void setXnackSetting(TargetIDSetting NewXnackSetting) {
15073471bf0Spatrick     XnackSetting = NewXnackSetting;
15173471bf0Spatrick   }
15273471bf0Spatrick 
15373471bf0Spatrick   /// \return True if the current sramecc setting is not "Unsupported".
isSramEccSupported()15473471bf0Spatrick   bool isSramEccSupported() const {
15573471bf0Spatrick     return SramEccSetting != TargetIDSetting::Unsupported;
15673471bf0Spatrick   }
15773471bf0Spatrick 
15873471bf0Spatrick   /// \returns True if the current sramecc setting is "On" or "Any".
isSramEccOnOrAny()15973471bf0Spatrick   bool isSramEccOnOrAny() const {
16073471bf0Spatrick   return SramEccSetting == TargetIDSetting::On ||
16173471bf0Spatrick       SramEccSetting == TargetIDSetting::Any;
16273471bf0Spatrick   }
16373471bf0Spatrick 
16473471bf0Spatrick   /// \returns True if current sramecc setting is "On" or "Off",
16573471bf0Spatrick   /// false otherwise.
isSramEccOnOrOff()16673471bf0Spatrick   bool isSramEccOnOrOff() const {
16773471bf0Spatrick     return getSramEccSetting() == TargetIDSetting::On ||
16873471bf0Spatrick         getSramEccSetting() == TargetIDSetting::Off;
16973471bf0Spatrick   }
17073471bf0Spatrick 
17173471bf0Spatrick   /// \returns The current sramecc TargetIDSetting, possible options are
17273471bf0Spatrick   /// "Unsupported", "Any", "Off", and "On".
getSramEccSetting()17373471bf0Spatrick   TargetIDSetting getSramEccSetting() const {
17473471bf0Spatrick     return SramEccSetting;
17573471bf0Spatrick   }
17673471bf0Spatrick 
17773471bf0Spatrick   /// Sets sramecc setting to \p NewSramEccSetting.
setSramEccSetting(TargetIDSetting NewSramEccSetting)17873471bf0Spatrick   void setSramEccSetting(TargetIDSetting NewSramEccSetting) {
17973471bf0Spatrick     SramEccSetting = NewSramEccSetting;
18073471bf0Spatrick   }
18173471bf0Spatrick 
18273471bf0Spatrick   void setTargetIDFromFeaturesString(StringRef FS);
18373471bf0Spatrick   void setTargetIDFromTargetIDStream(StringRef TargetID);
18473471bf0Spatrick 
18573471bf0Spatrick   /// \returns String representation of an object.
18673471bf0Spatrick   std::string toString() const;
18773471bf0Spatrick };
18809467b48Spatrick 
18909467b48Spatrick /// \returns Wavefront size for given subtarget \p STI.
19009467b48Spatrick unsigned getWavefrontSize(const MCSubtargetInfo *STI);
19109467b48Spatrick 
19209467b48Spatrick /// \returns Local memory size in bytes for given subtarget \p STI.
19309467b48Spatrick unsigned getLocalMemorySize(const MCSubtargetInfo *STI);
19409467b48Spatrick 
195*d415bd75Srobert /// \returns Maximum addressable local memory size in bytes for given subtarget
196*d415bd75Srobert /// \p STI.
197*d415bd75Srobert unsigned getAddressableLocalMemorySize(const MCSubtargetInfo *STI);
198*d415bd75Srobert 
19909467b48Spatrick /// \returns Number of execution units per compute unit for given subtarget \p
20009467b48Spatrick /// STI.
20109467b48Spatrick unsigned getEUsPerCU(const MCSubtargetInfo *STI);
20209467b48Spatrick 
20309467b48Spatrick /// \returns Maximum number of work groups per compute unit for given subtarget
20409467b48Spatrick /// \p STI and limited by given \p FlatWorkGroupSize.
20509467b48Spatrick unsigned getMaxWorkGroupsPerCU(const MCSubtargetInfo *STI,
20609467b48Spatrick                                unsigned FlatWorkGroupSize);
20709467b48Spatrick 
20809467b48Spatrick /// \returns Minimum number of waves per execution unit for given subtarget \p
20909467b48Spatrick /// STI.
21009467b48Spatrick unsigned getMinWavesPerEU(const MCSubtargetInfo *STI);
21109467b48Spatrick 
21209467b48Spatrick /// \returns Maximum number of waves per execution unit for given subtarget \p
21309467b48Spatrick /// STI without any kind of limitation.
21409467b48Spatrick unsigned getMaxWavesPerEU(const MCSubtargetInfo *STI);
21509467b48Spatrick 
216097a140dSpatrick /// \returns Number of waves per execution unit required to support the given \p
217097a140dSpatrick /// FlatWorkGroupSize.
218097a140dSpatrick unsigned getWavesPerEUForWorkGroup(const MCSubtargetInfo *STI,
21909467b48Spatrick                                    unsigned FlatWorkGroupSize);
22009467b48Spatrick 
22109467b48Spatrick /// \returns Minimum flat work group size for given subtarget \p STI.
22209467b48Spatrick unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo *STI);
22309467b48Spatrick 
22409467b48Spatrick /// \returns Maximum flat work group size for given subtarget \p STI.
22509467b48Spatrick unsigned getMaxFlatWorkGroupSize(const MCSubtargetInfo *STI);
22609467b48Spatrick 
22709467b48Spatrick /// \returns Number of waves per work group for given subtarget \p STI and
228097a140dSpatrick /// \p FlatWorkGroupSize.
22909467b48Spatrick unsigned getWavesPerWorkGroup(const MCSubtargetInfo *STI,
23009467b48Spatrick                               unsigned FlatWorkGroupSize);
23109467b48Spatrick 
23209467b48Spatrick /// \returns SGPR allocation granularity for given subtarget \p STI.
23309467b48Spatrick unsigned getSGPRAllocGranule(const MCSubtargetInfo *STI);
23409467b48Spatrick 
23509467b48Spatrick /// \returns SGPR encoding granularity for given subtarget \p STI.
23609467b48Spatrick unsigned getSGPREncodingGranule(const MCSubtargetInfo *STI);
23709467b48Spatrick 
23809467b48Spatrick /// \returns Total number of SGPRs for given subtarget \p STI.
23909467b48Spatrick unsigned getTotalNumSGPRs(const MCSubtargetInfo *STI);
24009467b48Spatrick 
24109467b48Spatrick /// \returns Addressable number of SGPRs for given subtarget \p STI.
24209467b48Spatrick unsigned getAddressableNumSGPRs(const MCSubtargetInfo *STI);
24309467b48Spatrick 
24409467b48Spatrick /// \returns Minimum number of SGPRs that meets the given number of waves per
24509467b48Spatrick /// execution unit requirement for given subtarget \p STI.
24609467b48Spatrick unsigned getMinNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU);
24709467b48Spatrick 
24809467b48Spatrick /// \returns Maximum number of SGPRs that meets the given number of waves per
24909467b48Spatrick /// execution unit requirement for given subtarget \p STI.
25009467b48Spatrick unsigned getMaxNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU,
25109467b48Spatrick                         bool Addressable);
25209467b48Spatrick 
25309467b48Spatrick /// \returns Number of extra SGPRs implicitly required by given subtarget \p
25409467b48Spatrick /// STI when the given special registers are used.
25509467b48Spatrick unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed,
25609467b48Spatrick                           bool FlatScrUsed, bool XNACKUsed);
25709467b48Spatrick 
25809467b48Spatrick /// \returns Number of extra SGPRs implicitly required by given subtarget \p
25909467b48Spatrick /// STI when the given special registers are used. XNACK is inferred from
26009467b48Spatrick /// \p STI.
26109467b48Spatrick unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed,
26209467b48Spatrick                           bool FlatScrUsed);
26309467b48Spatrick 
26409467b48Spatrick /// \returns Number of SGPR blocks needed for given subtarget \p STI when
26509467b48Spatrick /// \p NumSGPRs are used. \p NumSGPRs should already include any special
26609467b48Spatrick /// register counts.
26709467b48Spatrick unsigned getNumSGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs);
26809467b48Spatrick 
26909467b48Spatrick /// \returns VGPR allocation granularity for given subtarget \p STI.
27009467b48Spatrick ///
27109467b48Spatrick /// For subtargets which support it, \p EnableWavefrontSize32 should match
27209467b48Spatrick /// the ENABLE_WAVEFRONT_SIZE32 kernel descriptor field.
273*d415bd75Srobert unsigned
274*d415bd75Srobert getVGPRAllocGranule(const MCSubtargetInfo *STI,
275*d415bd75Srobert                     std::optional<bool> EnableWavefrontSize32 = std::nullopt);
27609467b48Spatrick 
27709467b48Spatrick /// \returns VGPR encoding granularity for given subtarget \p STI.
27809467b48Spatrick ///
27909467b48Spatrick /// For subtargets which support it, \p EnableWavefrontSize32 should match
28009467b48Spatrick /// the ENABLE_WAVEFRONT_SIZE32 kernel descriptor field.
281*d415bd75Srobert unsigned getVGPREncodingGranule(
282*d415bd75Srobert     const MCSubtargetInfo *STI,
283*d415bd75Srobert     std::optional<bool> EnableWavefrontSize32 = std::nullopt);
28409467b48Spatrick 
28509467b48Spatrick /// \returns Total number of VGPRs for given subtarget \p STI.
28609467b48Spatrick unsigned getTotalNumVGPRs(const MCSubtargetInfo *STI);
28709467b48Spatrick 
28809467b48Spatrick /// \returns Addressable number of VGPRs for given subtarget \p STI.
28909467b48Spatrick unsigned getAddressableNumVGPRs(const MCSubtargetInfo *STI);
29009467b48Spatrick 
29109467b48Spatrick /// \returns Minimum number of VGPRs that meets given number of waves per
29209467b48Spatrick /// execution unit requirement for given subtarget \p STI.
29309467b48Spatrick unsigned getMinNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU);
29409467b48Spatrick 
29509467b48Spatrick /// \returns Maximum number of VGPRs that meets given number of waves per
29609467b48Spatrick /// execution unit requirement for given subtarget \p STI.
29709467b48Spatrick unsigned getMaxNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU);
29809467b48Spatrick 
299*d415bd75Srobert /// \returns Number of waves reachable for a given \p NumVGPRs usage for given
300*d415bd75Srobert /// subtarget \p STI.
301*d415bd75Srobert unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo *STI,
302*d415bd75Srobert                                       unsigned NumVGPRs);
303*d415bd75Srobert 
30409467b48Spatrick /// \returns Number of VGPR blocks needed for given subtarget \p STI when
30509467b48Spatrick /// \p NumVGPRs are used.
30609467b48Spatrick ///
30709467b48Spatrick /// For subtargets which support it, \p EnableWavefrontSize32 should match the
30809467b48Spatrick /// ENABLE_WAVEFRONT_SIZE32 kernel descriptor field.
309*d415bd75Srobert unsigned
310*d415bd75Srobert getNumVGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs,
311*d415bd75Srobert                  std::optional<bool> EnableWavefrontSize32 = std::nullopt);
31209467b48Spatrick 
31309467b48Spatrick } // end namespace IsaInfo
31409467b48Spatrick 
31509467b48Spatrick LLVM_READONLY
31609467b48Spatrick int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx);
31709467b48Spatrick 
31809467b48Spatrick LLVM_READONLY
hasNamedOperand(uint64_t Opcode,uint64_t NamedIdx)319*d415bd75Srobert inline bool hasNamedOperand(uint64_t Opcode, uint64_t NamedIdx) {
320*d415bd75Srobert   return getNamedOperandIdx(Opcode, NamedIdx) != -1;
321*d415bd75Srobert }
322*d415bd75Srobert 
323*d415bd75Srobert LLVM_READONLY
32409467b48Spatrick int getSOPPWithRelaxation(uint16_t Opcode);
32509467b48Spatrick 
32609467b48Spatrick struct MIMGBaseOpcodeInfo {
32709467b48Spatrick   MIMGBaseOpcode BaseOpcode;
32809467b48Spatrick   bool Store;
32909467b48Spatrick   bool Atomic;
33009467b48Spatrick   bool AtomicX2;
33109467b48Spatrick   bool Sampler;
33209467b48Spatrick   bool Gather4;
33309467b48Spatrick 
33409467b48Spatrick   uint8_t NumExtraArgs;
33509467b48Spatrick   bool Gradients;
336097a140dSpatrick   bool G16;
33709467b48Spatrick   bool Coordinates;
33809467b48Spatrick   bool LodOrClampOrMip;
33909467b48Spatrick   bool HasD16;
34073471bf0Spatrick   bool MSAA;
341*d415bd75Srobert   bool BVH;
34209467b48Spatrick };
34309467b48Spatrick 
34409467b48Spatrick LLVM_READONLY
345*d415bd75Srobert const MIMGBaseOpcodeInfo *getMIMGBaseOpcode(unsigned Opc);
346*d415bd75Srobert 
347*d415bd75Srobert LLVM_READONLY
34809467b48Spatrick const MIMGBaseOpcodeInfo *getMIMGBaseOpcodeInfo(unsigned BaseOpcode);
34909467b48Spatrick 
35009467b48Spatrick struct MIMGDimInfo {
35109467b48Spatrick   MIMGDim Dim;
35209467b48Spatrick   uint8_t NumCoords;
35309467b48Spatrick   uint8_t NumGradients;
35473471bf0Spatrick   bool MSAA;
35509467b48Spatrick   bool DA;
35609467b48Spatrick   uint8_t Encoding;
35709467b48Spatrick   const char *AsmSuffix;
35809467b48Spatrick };
35909467b48Spatrick 
36009467b48Spatrick LLVM_READONLY
36109467b48Spatrick const MIMGDimInfo *getMIMGDimInfo(unsigned DimEnum);
36209467b48Spatrick 
36309467b48Spatrick LLVM_READONLY
36409467b48Spatrick const MIMGDimInfo *getMIMGDimInfoByEncoding(uint8_t DimEnc);
36509467b48Spatrick 
36609467b48Spatrick LLVM_READONLY
36709467b48Spatrick const MIMGDimInfo *getMIMGDimInfoByAsmSuffix(StringRef AsmSuffix);
36809467b48Spatrick 
36909467b48Spatrick struct MIMGLZMappingInfo {
37009467b48Spatrick   MIMGBaseOpcode L;
37109467b48Spatrick   MIMGBaseOpcode LZ;
37209467b48Spatrick };
37309467b48Spatrick 
37409467b48Spatrick struct MIMGMIPMappingInfo {
37509467b48Spatrick   MIMGBaseOpcode MIP;
37609467b48Spatrick   MIMGBaseOpcode NONMIP;
37709467b48Spatrick };
37809467b48Spatrick 
379*d415bd75Srobert struct MIMGBiasMappingInfo {
380*d415bd75Srobert   MIMGBaseOpcode Bias;
381*d415bd75Srobert   MIMGBaseOpcode NoBias;
382*d415bd75Srobert };
383*d415bd75Srobert 
384*d415bd75Srobert struct MIMGOffsetMappingInfo {
385*d415bd75Srobert   MIMGBaseOpcode Offset;
386*d415bd75Srobert   MIMGBaseOpcode NoOffset;
387*d415bd75Srobert };
388*d415bd75Srobert 
389097a140dSpatrick struct MIMGG16MappingInfo {
390097a140dSpatrick   MIMGBaseOpcode G;
391097a140dSpatrick   MIMGBaseOpcode G16;
392097a140dSpatrick };
393097a140dSpatrick 
39409467b48Spatrick LLVM_READONLY
39509467b48Spatrick const MIMGLZMappingInfo *getMIMGLZMappingInfo(unsigned L);
39609467b48Spatrick 
397*d415bd75Srobert struct WMMAOpcodeMappingInfo {
398*d415bd75Srobert   unsigned Opcode2Addr;
399*d415bd75Srobert   unsigned Opcode3Addr;
400*d415bd75Srobert };
401*d415bd75Srobert 
40209467b48Spatrick LLVM_READONLY
403097a140dSpatrick const MIMGMIPMappingInfo *getMIMGMIPMappingInfo(unsigned MIP);
404097a140dSpatrick 
405097a140dSpatrick LLVM_READONLY
406*d415bd75Srobert const MIMGBiasMappingInfo *getMIMGBiasMappingInfo(unsigned Bias);
407*d415bd75Srobert 
408*d415bd75Srobert LLVM_READONLY
409*d415bd75Srobert const MIMGOffsetMappingInfo *getMIMGOffsetMappingInfo(unsigned Offset);
410*d415bd75Srobert 
411*d415bd75Srobert LLVM_READONLY
412097a140dSpatrick const MIMGG16MappingInfo *getMIMGG16MappingInfo(unsigned G);
41309467b48Spatrick 
41409467b48Spatrick LLVM_READONLY
41509467b48Spatrick int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding,
41609467b48Spatrick                   unsigned VDataDwords, unsigned VAddrDwords);
41709467b48Spatrick 
41809467b48Spatrick LLVM_READONLY
41909467b48Spatrick int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels);
42009467b48Spatrick 
42173471bf0Spatrick LLVM_READONLY
42273471bf0Spatrick unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode,
42373471bf0Spatrick                            const MIMGDimInfo *Dim, bool IsA16,
42473471bf0Spatrick                            bool IsG16Supported);
42573471bf0Spatrick 
42609467b48Spatrick struct MIMGInfo {
42709467b48Spatrick   uint16_t Opcode;
42809467b48Spatrick   uint16_t BaseOpcode;
42909467b48Spatrick   uint8_t MIMGEncoding;
43009467b48Spatrick   uint8_t VDataDwords;
43109467b48Spatrick   uint8_t VAddrDwords;
432*d415bd75Srobert   uint8_t VAddrOperands;
43309467b48Spatrick };
43409467b48Spatrick 
43509467b48Spatrick LLVM_READONLY
43609467b48Spatrick const MIMGInfo *getMIMGInfo(unsigned Opc);
43709467b48Spatrick 
43809467b48Spatrick LLVM_READONLY
43909467b48Spatrick int getMTBUFBaseOpcode(unsigned Opc);
44009467b48Spatrick 
44109467b48Spatrick LLVM_READONLY
44209467b48Spatrick int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements);
44309467b48Spatrick 
44409467b48Spatrick LLVM_READONLY
44509467b48Spatrick int getMTBUFElements(unsigned Opc);
44609467b48Spatrick 
44709467b48Spatrick LLVM_READONLY
44809467b48Spatrick bool getMTBUFHasVAddr(unsigned Opc);
44909467b48Spatrick 
45009467b48Spatrick LLVM_READONLY
45109467b48Spatrick bool getMTBUFHasSrsrc(unsigned Opc);
45209467b48Spatrick 
45309467b48Spatrick LLVM_READONLY
45409467b48Spatrick bool getMTBUFHasSoffset(unsigned Opc);
45509467b48Spatrick 
45609467b48Spatrick LLVM_READONLY
45709467b48Spatrick int getMUBUFBaseOpcode(unsigned Opc);
45809467b48Spatrick 
45909467b48Spatrick LLVM_READONLY
46009467b48Spatrick int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements);
46109467b48Spatrick 
46209467b48Spatrick LLVM_READONLY
46309467b48Spatrick int getMUBUFElements(unsigned Opc);
46409467b48Spatrick 
46509467b48Spatrick LLVM_READONLY
46609467b48Spatrick bool getMUBUFHasVAddr(unsigned Opc);
46709467b48Spatrick 
46809467b48Spatrick LLVM_READONLY
46909467b48Spatrick bool getMUBUFHasSrsrc(unsigned Opc);
47009467b48Spatrick 
47109467b48Spatrick LLVM_READONLY
47209467b48Spatrick bool getMUBUFHasSoffset(unsigned Opc);
47309467b48Spatrick 
47409467b48Spatrick LLVM_READONLY
47573471bf0Spatrick bool getMUBUFIsBufferInv(unsigned Opc);
47673471bf0Spatrick 
47773471bf0Spatrick LLVM_READONLY
478097a140dSpatrick bool getSMEMIsBuffer(unsigned Opc);
479097a140dSpatrick 
480097a140dSpatrick LLVM_READONLY
48173471bf0Spatrick bool getVOP1IsSingle(unsigned Opc);
48273471bf0Spatrick 
48373471bf0Spatrick LLVM_READONLY
48473471bf0Spatrick bool getVOP2IsSingle(unsigned Opc);
48573471bf0Spatrick 
48673471bf0Spatrick LLVM_READONLY
48773471bf0Spatrick bool getVOP3IsSingle(unsigned Opc);
48873471bf0Spatrick 
48973471bf0Spatrick LLVM_READONLY
490*d415bd75Srobert bool isVOPC64DPP(unsigned Opc);
491*d415bd75Srobert 
492*d415bd75Srobert /// Returns true if MAI operation is a double precision GEMM.
493*d415bd75Srobert LLVM_READONLY
494*d415bd75Srobert bool getMAIIsDGEMM(unsigned Opc);
495*d415bd75Srobert 
496*d415bd75Srobert LLVM_READONLY
497*d415bd75Srobert bool getMAIIsGFX940XDL(unsigned Opc);
498*d415bd75Srobert 
499*d415bd75Srobert struct CanBeVOPD {
500*d415bd75Srobert   bool X;
501*d415bd75Srobert   bool Y;
502*d415bd75Srobert };
503*d415bd75Srobert 
504*d415bd75Srobert LLVM_READONLY
505*d415bd75Srobert CanBeVOPD getCanBeVOPD(unsigned Opc);
506*d415bd75Srobert 
507*d415bd75Srobert LLVM_READONLY
50809467b48Spatrick const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t BitsPerComp,
50909467b48Spatrick                                                   uint8_t NumComponents,
51009467b48Spatrick                                                   uint8_t NumFormat,
51109467b48Spatrick                                                   const MCSubtargetInfo &STI);
51209467b48Spatrick LLVM_READONLY
51309467b48Spatrick const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t Format,
51409467b48Spatrick                                                   const MCSubtargetInfo &STI);
51509467b48Spatrick 
51609467b48Spatrick LLVM_READONLY
51709467b48Spatrick int getMCOpcode(uint16_t Opcode, unsigned Gen);
51809467b48Spatrick 
519*d415bd75Srobert LLVM_READONLY
520*d415bd75Srobert unsigned getVOPDOpcode(unsigned Opc);
521*d415bd75Srobert 
522*d415bd75Srobert LLVM_READONLY
523*d415bd75Srobert int getVOPDFull(unsigned OpX, unsigned OpY);
524*d415bd75Srobert 
525*d415bd75Srobert LLVM_READONLY
526*d415bd75Srobert bool isVOPD(unsigned Opc);
527*d415bd75Srobert 
528*d415bd75Srobert LLVM_READNONE
529*d415bd75Srobert bool isMAC(unsigned Opc);
530*d415bd75Srobert 
531*d415bd75Srobert LLVM_READNONE
532*d415bd75Srobert bool isPermlane16(unsigned Opc);
533*d415bd75Srobert 
534*d415bd75Srobert namespace VOPD {
535*d415bd75Srobert 
536*d415bd75Srobert enum Component : unsigned {
537*d415bd75Srobert   DST = 0,
538*d415bd75Srobert   SRC0,
539*d415bd75Srobert   SRC1,
540*d415bd75Srobert   SRC2,
541*d415bd75Srobert 
542*d415bd75Srobert   DST_NUM = 1,
543*d415bd75Srobert   MAX_SRC_NUM = 3,
544*d415bd75Srobert   MAX_OPR_NUM = DST_NUM + MAX_SRC_NUM
545*d415bd75Srobert };
546*d415bd75Srobert 
547*d415bd75Srobert // Number of VGPR banks per VOPD component operand.
548*d415bd75Srobert constexpr unsigned BANKS_NUM[] = {2, 4, 4, 2};
549*d415bd75Srobert 
550*d415bd75Srobert enum ComponentIndex : unsigned { X = 0, Y = 1 };
551*d415bd75Srobert constexpr unsigned COMPONENTS[] = {ComponentIndex::X, ComponentIndex::Y};
552*d415bd75Srobert constexpr unsigned COMPONENTS_NUM = 2;
553*d415bd75Srobert 
554*d415bd75Srobert // Properties of VOPD components.
555*d415bd75Srobert class ComponentProps {
556*d415bd75Srobert private:
557*d415bd75Srobert   unsigned SrcOperandsNum = 0;
558*d415bd75Srobert   std::optional<unsigned> MandatoryLiteralIdx;
559*d415bd75Srobert   bool HasSrc2Acc = false;
560*d415bd75Srobert 
561*d415bd75Srobert public:
562*d415bd75Srobert   ComponentProps() = default;
563*d415bd75Srobert   ComponentProps(const MCInstrDesc &OpDesc);
564*d415bd75Srobert 
565*d415bd75Srobert   // Return the total number of src operands this component has.
getCompSrcOperandsNum()566*d415bd75Srobert   unsigned getCompSrcOperandsNum() const { return SrcOperandsNum; }
567*d415bd75Srobert 
568*d415bd75Srobert   // Return the number of src operands of this component visible to the parser.
getCompParsedSrcOperandsNum()569*d415bd75Srobert   unsigned getCompParsedSrcOperandsNum() const {
570*d415bd75Srobert     return SrcOperandsNum - HasSrc2Acc;
571*d415bd75Srobert   }
572*d415bd75Srobert 
573*d415bd75Srobert   // Return true iif this component has a mandatory literal.
hasMandatoryLiteral()574*d415bd75Srobert   bool hasMandatoryLiteral() const { return MandatoryLiteralIdx.has_value(); }
575*d415bd75Srobert 
576*d415bd75Srobert   // If this component has a mandatory literal, return component operand
577*d415bd75Srobert   // index of this literal (i.e. either Component::SRC1 or Component::SRC2).
getMandatoryLiteralCompOperandIndex()578*d415bd75Srobert   unsigned getMandatoryLiteralCompOperandIndex() const {
579*d415bd75Srobert     assert(hasMandatoryLiteral());
580*d415bd75Srobert     return *MandatoryLiteralIdx;
581*d415bd75Srobert   }
582*d415bd75Srobert 
583*d415bd75Srobert   // Return true iif this component has operand
584*d415bd75Srobert   // with component index CompSrcIdx and this operand may be a register.
hasRegSrcOperand(unsigned CompSrcIdx)585*d415bd75Srobert   bool hasRegSrcOperand(unsigned CompSrcIdx) const {
586*d415bd75Srobert     assert(CompSrcIdx < Component::MAX_SRC_NUM);
587*d415bd75Srobert     return SrcOperandsNum > CompSrcIdx && !hasMandatoryLiteralAt(CompSrcIdx);
588*d415bd75Srobert   }
589*d415bd75Srobert 
590*d415bd75Srobert   // Return true iif this component has tied src2.
hasSrc2Acc()591*d415bd75Srobert   bool hasSrc2Acc() const { return HasSrc2Acc; }
592*d415bd75Srobert 
593*d415bd75Srobert private:
hasMandatoryLiteralAt(unsigned CompSrcIdx)594*d415bd75Srobert   bool hasMandatoryLiteralAt(unsigned CompSrcIdx) const {
595*d415bd75Srobert     assert(CompSrcIdx < Component::MAX_SRC_NUM);
596*d415bd75Srobert     return hasMandatoryLiteral() &&
597*d415bd75Srobert            *MandatoryLiteralIdx == Component::DST_NUM + CompSrcIdx;
598*d415bd75Srobert   }
599*d415bd75Srobert };
600*d415bd75Srobert 
601*d415bd75Srobert enum ComponentKind : unsigned {
602*d415bd75Srobert   SINGLE = 0,  // A single VOP1 or VOP2 instruction which may be used in VOPD.
603*d415bd75Srobert   COMPONENT_X, // A VOPD instruction, X component.
604*d415bd75Srobert   COMPONENT_Y, // A VOPD instruction, Y component.
605*d415bd75Srobert   MAX = COMPONENT_Y
606*d415bd75Srobert };
607*d415bd75Srobert 
608*d415bd75Srobert // Interface functions of this class map VOPD component operand indices
609*d415bd75Srobert // to indices of operands in MachineInstr/MCInst or parsed operands array.
610*d415bd75Srobert //
611*d415bd75Srobert // Note that this class operates with 3 kinds of indices:
612*d415bd75Srobert // - VOPD component operand indices (Component::DST, Component::SRC0, etc.);
613*d415bd75Srobert // - MC operand indices (they refer operands in a MachineInstr/MCInst);
614*d415bd75Srobert // - parsed operand indices (they refer operands in parsed operands array).
615*d415bd75Srobert //
616*d415bd75Srobert // For SINGLE components mapping between these indices is trivial.
617*d415bd75Srobert // But things get more complicated for COMPONENT_X and
618*d415bd75Srobert // COMPONENT_Y because these components share the same
619*d415bd75Srobert // MachineInstr/MCInst and the same parsed operands array.
620*d415bd75Srobert // Below is an example of component operand to parsed operand
621*d415bd75Srobert // mapping for the following instruction:
622*d415bd75Srobert //
623*d415bd75Srobert //   v_dual_add_f32 v255, v4, v5 :: v_dual_mov_b32 v6, v1
624*d415bd75Srobert //
625*d415bd75Srobert //                          PARSED        COMPONENT         PARSED
626*d415bd75Srobert // COMPONENT               OPERANDS     OPERAND INDEX    OPERAND INDEX
627*d415bd75Srobert // -------------------------------------------------------------------
628*d415bd75Srobert //                     "v_dual_add_f32"                        0
629*d415bd75Srobert // v_dual_add_f32            v255          0 (DST)    -->      1
630*d415bd75Srobert //                           v4            1 (SRC0)   -->      2
631*d415bd75Srobert //                           v5            2 (SRC1)   -->      3
632*d415bd75Srobert //                          "::"                               4
633*d415bd75Srobert //                     "v_dual_mov_b32"                        5
634*d415bd75Srobert // v_dual_mov_b32            v6            0 (DST)    -->      6
635*d415bd75Srobert //                           v1            1 (SRC0)   -->      7
636*d415bd75Srobert // -------------------------------------------------------------------
637*d415bd75Srobert //
638*d415bd75Srobert class ComponentLayout {
639*d415bd75Srobert private:
640*d415bd75Srobert   // Regular MachineInstr/MCInst operands are ordered as follows:
641*d415bd75Srobert   //   dst, src0 [, other src operands]
642*d415bd75Srobert   // VOPD MachineInstr/MCInst operands are ordered as follows:
643*d415bd75Srobert   //   dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
644*d415bd75Srobert   // Each ComponentKind has operand indices defined below.
645*d415bd75Srobert   static constexpr unsigned MC_DST_IDX[] = {0, 0, 1};
646*d415bd75Srobert   static constexpr unsigned FIRST_MC_SRC_IDX[] = {1, 2, 2 /* + OpX.MCSrcNum */};
647*d415bd75Srobert 
648*d415bd75Srobert   // Parsed operands of regular instructions are ordered as follows:
649*d415bd75Srobert   //   Mnemo dst src0 [vsrc1 ...]
650*d415bd75Srobert   // Parsed VOPD operands are ordered as follows:
651*d415bd75Srobert   //   OpXMnemo dstX src0X [vsrc1X|imm vsrc1X|vsrc1X imm] '::'
652*d415bd75Srobert   //   OpYMnemo dstY src0Y [vsrc1Y|imm vsrc1Y|vsrc1Y imm]
653*d415bd75Srobert   // Each ComponentKind has operand indices defined below.
654*d415bd75Srobert   static constexpr unsigned PARSED_DST_IDX[] = {1, 1,
655*d415bd75Srobert                                                 4 /* + OpX.ParsedSrcNum */};
656*d415bd75Srobert   static constexpr unsigned FIRST_PARSED_SRC_IDX[] = {
657*d415bd75Srobert       2, 2, 5 /* + OpX.ParsedSrcNum */};
658*d415bd75Srobert 
659*d415bd75Srobert private:
660*d415bd75Srobert   const ComponentKind Kind;
661*d415bd75Srobert   const ComponentProps PrevComp;
662*d415bd75Srobert 
663*d415bd75Srobert public:
664*d415bd75Srobert   // Create layout for COMPONENT_X or SINGLE component.
ComponentLayout(ComponentKind Kind)665*d415bd75Srobert   ComponentLayout(ComponentKind Kind) : Kind(Kind) {
666*d415bd75Srobert     assert(Kind == ComponentKind::SINGLE || Kind == ComponentKind::COMPONENT_X);
667*d415bd75Srobert   }
668*d415bd75Srobert 
669*d415bd75Srobert   // Create layout for COMPONENT_Y which depends on COMPONENT_X layout.
ComponentLayout(const ComponentProps & OpXProps)670*d415bd75Srobert   ComponentLayout(const ComponentProps &OpXProps)
671*d415bd75Srobert       : Kind(ComponentKind::COMPONENT_Y), PrevComp(OpXProps) {}
672*d415bd75Srobert 
673*d415bd75Srobert public:
674*d415bd75Srobert   // Return the index of dst operand in MCInst operands.
getIndexOfDstInMCOperands()675*d415bd75Srobert   unsigned getIndexOfDstInMCOperands() const { return MC_DST_IDX[Kind]; }
676*d415bd75Srobert 
677*d415bd75Srobert   // Return the index of the specified src operand in MCInst operands.
getIndexOfSrcInMCOperands(unsigned CompSrcIdx)678*d415bd75Srobert   unsigned getIndexOfSrcInMCOperands(unsigned CompSrcIdx) const {
679*d415bd75Srobert     assert(CompSrcIdx < Component::MAX_SRC_NUM);
680*d415bd75Srobert     return FIRST_MC_SRC_IDX[Kind] + getPrevCompSrcNum() + CompSrcIdx;
681*d415bd75Srobert   }
682*d415bd75Srobert 
683*d415bd75Srobert   // Return the index of dst operand in the parsed operands array.
getIndexOfDstInParsedOperands()684*d415bd75Srobert   unsigned getIndexOfDstInParsedOperands() const {
685*d415bd75Srobert     return PARSED_DST_IDX[Kind] + getPrevCompParsedSrcNum();
686*d415bd75Srobert   }
687*d415bd75Srobert 
688*d415bd75Srobert   // Return the index of the specified src operand in the parsed operands array.
getIndexOfSrcInParsedOperands(unsigned CompSrcIdx)689*d415bd75Srobert   unsigned getIndexOfSrcInParsedOperands(unsigned CompSrcIdx) const {
690*d415bd75Srobert     assert(CompSrcIdx < Component::MAX_SRC_NUM);
691*d415bd75Srobert     return FIRST_PARSED_SRC_IDX[Kind] + getPrevCompParsedSrcNum() + CompSrcIdx;
692*d415bd75Srobert   }
693*d415bd75Srobert 
694*d415bd75Srobert private:
getPrevCompSrcNum()695*d415bd75Srobert   unsigned getPrevCompSrcNum() const {
696*d415bd75Srobert     return PrevComp.getCompSrcOperandsNum();
697*d415bd75Srobert   }
getPrevCompParsedSrcNum()698*d415bd75Srobert   unsigned getPrevCompParsedSrcNum() const {
699*d415bd75Srobert     return PrevComp.getCompParsedSrcOperandsNum();
700*d415bd75Srobert   }
701*d415bd75Srobert };
702*d415bd75Srobert 
703*d415bd75Srobert // Layout and properties of VOPD components.
704*d415bd75Srobert class ComponentInfo : public ComponentLayout, public ComponentProps {
705*d415bd75Srobert public:
706*d415bd75Srobert   // Create ComponentInfo for COMPONENT_X or SINGLE component.
707*d415bd75Srobert   ComponentInfo(const MCInstrDesc &OpDesc,
708*d415bd75Srobert                 ComponentKind Kind = ComponentKind::SINGLE)
ComponentLayout(Kind)709*d415bd75Srobert       : ComponentLayout(Kind), ComponentProps(OpDesc) {}
710*d415bd75Srobert 
711*d415bd75Srobert   // Create ComponentInfo for COMPONENT_Y which depends on COMPONENT_X layout.
ComponentInfo(const MCInstrDesc & OpDesc,const ComponentProps & OpXProps)712*d415bd75Srobert   ComponentInfo(const MCInstrDesc &OpDesc, const ComponentProps &OpXProps)
713*d415bd75Srobert       : ComponentLayout(OpXProps), ComponentProps(OpDesc) {}
714*d415bd75Srobert 
715*d415bd75Srobert   // Map component operand index to parsed operand index.
716*d415bd75Srobert   // Return 0 if the specified operand does not exist.
717*d415bd75Srobert   unsigned getIndexInParsedOperands(unsigned CompOprIdx) const;
718*d415bd75Srobert };
719*d415bd75Srobert 
720*d415bd75Srobert // Properties of VOPD instructions.
721*d415bd75Srobert class InstInfo {
722*d415bd75Srobert private:
723*d415bd75Srobert   const ComponentInfo CompInfo[COMPONENTS_NUM];
724*d415bd75Srobert 
725*d415bd75Srobert public:
726*d415bd75Srobert   using RegIndices = std::array<unsigned, Component::MAX_OPR_NUM>;
727*d415bd75Srobert 
InstInfo(const MCInstrDesc & OpX,const MCInstrDesc & OpY)728*d415bd75Srobert   InstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY)
729*d415bd75Srobert       : CompInfo{OpX, OpY} {}
730*d415bd75Srobert 
InstInfo(const ComponentInfo & OprInfoX,const ComponentInfo & OprInfoY)731*d415bd75Srobert   InstInfo(const ComponentInfo &OprInfoX, const ComponentInfo &OprInfoY)
732*d415bd75Srobert       : CompInfo{OprInfoX, OprInfoY} {}
733*d415bd75Srobert 
734*d415bd75Srobert   const ComponentInfo &operator[](size_t ComponentIdx) const {
735*d415bd75Srobert     assert(ComponentIdx < COMPONENTS_NUM);
736*d415bd75Srobert     return CompInfo[ComponentIdx];
737*d415bd75Srobert   }
738*d415bd75Srobert 
739*d415bd75Srobert   // Check VOPD operands constraints.
740*d415bd75Srobert   // GetRegIdx(Component, MCOperandIdx) must return a VGPR register index
741*d415bd75Srobert   // for the specified component and MC operand. The callback must return 0
742*d415bd75Srobert   // if the operand is not a register or not a VGPR.
hasInvalidOperand(std::function<unsigned (unsigned,unsigned)> GetRegIdx)743*d415bd75Srobert   bool hasInvalidOperand(
744*d415bd75Srobert       std::function<unsigned(unsigned, unsigned)> GetRegIdx) const {
745*d415bd75Srobert     return getInvalidCompOperandIndex(GetRegIdx).has_value();
746*d415bd75Srobert   }
747*d415bd75Srobert 
748*d415bd75Srobert   // Check VOPD operands constraints.
749*d415bd75Srobert   // Return the index of an invalid component operand, if any.
750*d415bd75Srobert   std::optional<unsigned> getInvalidCompOperandIndex(
751*d415bd75Srobert       std::function<unsigned(unsigned, unsigned)> GetRegIdx) const;
752*d415bd75Srobert 
753*d415bd75Srobert private:
754*d415bd75Srobert   RegIndices
755*d415bd75Srobert   getRegIndices(unsigned ComponentIdx,
756*d415bd75Srobert                 std::function<unsigned(unsigned, unsigned)> GetRegIdx) const;
757*d415bd75Srobert };
758*d415bd75Srobert 
759*d415bd75Srobert } // namespace VOPD
760*d415bd75Srobert 
761*d415bd75Srobert LLVM_READONLY
762*d415bd75Srobert std::pair<unsigned, unsigned> getVOPDComponents(unsigned VOPDOpcode);
763*d415bd75Srobert 
764*d415bd75Srobert LLVM_READONLY
765*d415bd75Srobert // Get properties of 2 single VOP1/VOP2 instructions
766*d415bd75Srobert // used as components to create a VOPD instruction.
767*d415bd75Srobert VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY);
768*d415bd75Srobert 
769*d415bd75Srobert LLVM_READONLY
770*d415bd75Srobert // Get properties of VOPD X and Y components.
771*d415bd75Srobert VOPD::InstInfo
772*d415bd75Srobert getVOPDInstInfo(unsigned VOPDOpcode, const MCInstrInfo *InstrInfo);
773*d415bd75Srobert 
774*d415bd75Srobert LLVM_READONLY
775*d415bd75Srobert bool isTrue16Inst(unsigned Opc);
776*d415bd75Srobert 
777*d415bd75Srobert LLVM_READONLY
778*d415bd75Srobert unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc);
779*d415bd75Srobert 
780*d415bd75Srobert LLVM_READONLY
781*d415bd75Srobert unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc);
782*d415bd75Srobert 
78309467b48Spatrick void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header,
78409467b48Spatrick                                const MCSubtargetInfo *STI);
78509467b48Spatrick 
78609467b48Spatrick amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor(
78709467b48Spatrick     const MCSubtargetInfo *STI);
78809467b48Spatrick 
78909467b48Spatrick bool isGroupSegment(const GlobalValue *GV);
79009467b48Spatrick bool isGlobalSegment(const GlobalValue *GV);
79109467b48Spatrick bool isReadOnlySegment(const GlobalValue *GV);
79209467b48Spatrick 
79309467b48Spatrick /// \returns True if constants should be emitted to .text section for given
79409467b48Spatrick /// target triple \p TT, false otherwise.
79509467b48Spatrick bool shouldEmitConstantsToTextSection(const Triple &TT);
79609467b48Spatrick 
79709467b48Spatrick /// \returns Integer value requested using \p F's \p Name attribute.
79809467b48Spatrick ///
79909467b48Spatrick /// \returns \p Default if attribute is not present.
80009467b48Spatrick ///
80109467b48Spatrick /// \returns \p Default and emits error if requested value cannot be converted
80209467b48Spatrick /// to integer.
80309467b48Spatrick int getIntegerAttribute(const Function &F, StringRef Name, int Default);
80409467b48Spatrick 
80509467b48Spatrick /// \returns A pair of integer values requested using \p F's \p Name attribute
80609467b48Spatrick /// in "first[,second]" format ("second" is optional unless \p OnlyFirstRequired
80709467b48Spatrick /// is false).
80809467b48Spatrick ///
80909467b48Spatrick /// \returns \p Default if attribute is not present.
81009467b48Spatrick ///
81109467b48Spatrick /// \returns \p Default and emits error if one of the requested values cannot be
81209467b48Spatrick /// converted to integer, or \p OnlyFirstRequired is false and "second" value is
81309467b48Spatrick /// not present.
81409467b48Spatrick std::pair<int, int> getIntegerPairAttribute(const Function &F,
81509467b48Spatrick                                             StringRef Name,
81609467b48Spatrick                                             std::pair<int, int> Default,
81709467b48Spatrick                                             bool OnlyFirstRequired = false);
81809467b48Spatrick 
81909467b48Spatrick /// Represents the counter values to wait for in an s_waitcnt instruction.
82009467b48Spatrick ///
82109467b48Spatrick /// Large values (including the maximum possible integer) can be used to
82209467b48Spatrick /// represent "don't care" waits.
82309467b48Spatrick struct Waitcnt {
82409467b48Spatrick   unsigned VmCnt = ~0u;
82509467b48Spatrick   unsigned ExpCnt = ~0u;
82609467b48Spatrick   unsigned LgkmCnt = ~0u;
82709467b48Spatrick   unsigned VsCnt = ~0u;
82809467b48Spatrick 
829*d415bd75Srobert   Waitcnt() = default;
WaitcntWaitcnt83009467b48Spatrick   Waitcnt(unsigned VmCnt, unsigned ExpCnt, unsigned LgkmCnt, unsigned VsCnt)
83109467b48Spatrick       : VmCnt(VmCnt), ExpCnt(ExpCnt), LgkmCnt(LgkmCnt), VsCnt(VsCnt) {}
83209467b48Spatrick 
allZeroWaitcnt83373471bf0Spatrick   static Waitcnt allZero(bool HasVscnt) {
83473471bf0Spatrick     return Waitcnt(0, 0, 0, HasVscnt ? 0 : ~0u);
83509467b48Spatrick   }
allZeroExceptVsCntWaitcnt83609467b48Spatrick   static Waitcnt allZeroExceptVsCnt() { return Waitcnt(0, 0, 0, ~0u); }
83709467b48Spatrick 
hasWaitWaitcnt83809467b48Spatrick   bool hasWait() const {
83909467b48Spatrick     return VmCnt != ~0u || ExpCnt != ~0u || LgkmCnt != ~0u || VsCnt != ~0u;
84009467b48Spatrick   }
84109467b48Spatrick 
hasWaitExceptVsCntWaitcnt84273471bf0Spatrick   bool hasWaitExceptVsCnt() const {
84373471bf0Spatrick     return VmCnt != ~0u || ExpCnt != ~0u || LgkmCnt != ~0u;
84473471bf0Spatrick   }
84573471bf0Spatrick 
hasWaitVsCntWaitcnt84673471bf0Spatrick   bool hasWaitVsCnt() const {
84773471bf0Spatrick     return VsCnt != ~0u;
84873471bf0Spatrick   }
84973471bf0Spatrick 
dominatesWaitcnt85009467b48Spatrick   bool dominates(const Waitcnt &Other) const {
85109467b48Spatrick     return VmCnt <= Other.VmCnt && ExpCnt <= Other.ExpCnt &&
85209467b48Spatrick            LgkmCnt <= Other.LgkmCnt && VsCnt <= Other.VsCnt;
85309467b48Spatrick   }
85409467b48Spatrick 
combinedWaitcnt85509467b48Spatrick   Waitcnt combined(const Waitcnt &Other) const {
85609467b48Spatrick     return Waitcnt(std::min(VmCnt, Other.VmCnt), std::min(ExpCnt, Other.ExpCnt),
85709467b48Spatrick                    std::min(LgkmCnt, Other.LgkmCnt),
85809467b48Spatrick                    std::min(VsCnt, Other.VsCnt));
85909467b48Spatrick   }
86009467b48Spatrick };
86109467b48Spatrick 
86209467b48Spatrick /// \returns Vmcnt bit mask for given isa \p Version.
86309467b48Spatrick unsigned getVmcntBitMask(const IsaVersion &Version);
86409467b48Spatrick 
86509467b48Spatrick /// \returns Expcnt bit mask for given isa \p Version.
86609467b48Spatrick unsigned getExpcntBitMask(const IsaVersion &Version);
86709467b48Spatrick 
86809467b48Spatrick /// \returns Lgkmcnt bit mask for given isa \p Version.
86909467b48Spatrick unsigned getLgkmcntBitMask(const IsaVersion &Version);
87009467b48Spatrick 
87109467b48Spatrick /// \returns Waitcnt bit mask for given isa \p Version.
87209467b48Spatrick unsigned getWaitcntBitMask(const IsaVersion &Version);
87309467b48Spatrick 
87409467b48Spatrick /// \returns Decoded Vmcnt from given \p Waitcnt for given isa \p Version.
87509467b48Spatrick unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt);
87609467b48Spatrick 
87709467b48Spatrick /// \returns Decoded Expcnt from given \p Waitcnt for given isa \p Version.
87809467b48Spatrick unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt);
87909467b48Spatrick 
88009467b48Spatrick /// \returns Decoded Lgkmcnt from given \p Waitcnt for given isa \p Version.
88109467b48Spatrick unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt);
88209467b48Spatrick 
88309467b48Spatrick /// Decodes Vmcnt, Expcnt and Lgkmcnt from given \p Waitcnt for given isa
88409467b48Spatrick /// \p Version, and writes decoded values into \p Vmcnt, \p Expcnt and
88509467b48Spatrick /// \p Lgkmcnt respectively.
88609467b48Spatrick ///
88709467b48Spatrick /// \details \p Vmcnt, \p Expcnt and \p Lgkmcnt are decoded as follows:
888*d415bd75Srobert ///     \p Vmcnt = \p Waitcnt[3:0]        (pre-gfx9)
889*d415bd75Srobert ///     \p Vmcnt = \p Waitcnt[15:14,3:0]  (gfx9,10)
890*d415bd75Srobert ///     \p Vmcnt = \p Waitcnt[15:10]      (gfx11+)
891*d415bd75Srobert ///     \p Expcnt = \p Waitcnt[6:4]       (pre-gfx11)
892*d415bd75Srobert ///     \p Expcnt = \p Waitcnt[2:0]       (gfx11+)
893*d415bd75Srobert ///     \p Lgkmcnt = \p Waitcnt[11:8]     (pre-gfx10)
894*d415bd75Srobert ///     \p Lgkmcnt = \p Waitcnt[13:8]     (gfx10)
895*d415bd75Srobert ///     \p Lgkmcnt = \p Waitcnt[9:4]      (gfx11+)
89609467b48Spatrick void decodeWaitcnt(const IsaVersion &Version, unsigned Waitcnt,
89709467b48Spatrick                    unsigned &Vmcnt, unsigned &Expcnt, unsigned &Lgkmcnt);
89809467b48Spatrick 
89909467b48Spatrick Waitcnt decodeWaitcnt(const IsaVersion &Version, unsigned Encoded);
90009467b48Spatrick 
90109467b48Spatrick /// \returns \p Waitcnt with encoded \p Vmcnt for given isa \p Version.
90209467b48Spatrick unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt,
90309467b48Spatrick                      unsigned Vmcnt);
90409467b48Spatrick 
90509467b48Spatrick /// \returns \p Waitcnt with encoded \p Expcnt for given isa \p Version.
90609467b48Spatrick unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt,
90709467b48Spatrick                       unsigned Expcnt);
90809467b48Spatrick 
90909467b48Spatrick /// \returns \p Waitcnt with encoded \p Lgkmcnt for given isa \p Version.
91009467b48Spatrick unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt,
91109467b48Spatrick                        unsigned Lgkmcnt);
91209467b48Spatrick 
91309467b48Spatrick /// Encodes \p Vmcnt, \p Expcnt and \p Lgkmcnt into Waitcnt for given isa
91409467b48Spatrick /// \p Version.
91509467b48Spatrick ///
91609467b48Spatrick /// \details \p Vmcnt, \p Expcnt and \p Lgkmcnt are encoded as follows:
917*d415bd75Srobert ///     Waitcnt[2:0]   = \p Expcnt      (gfx11+)
918*d415bd75Srobert ///     Waitcnt[3:0]   = \p Vmcnt       (pre-gfx9)
919*d415bd75Srobert ///     Waitcnt[3:0]   = \p Vmcnt[3:0]  (gfx9,10)
920*d415bd75Srobert ///     Waitcnt[6:4]   = \p Expcnt      (pre-gfx11)
921*d415bd75Srobert ///     Waitcnt[9:4]   = \p Lgkmcnt     (gfx11+)
922*d415bd75Srobert ///     Waitcnt[11:8]  = \p Lgkmcnt     (pre-gfx10)
923*d415bd75Srobert ///     Waitcnt[13:8]  = \p Lgkmcnt     (gfx10)
924*d415bd75Srobert ///     Waitcnt[15:10] = \p Vmcnt       (gfx11+)
925*d415bd75Srobert ///     Waitcnt[15:14] = \p Vmcnt[5:4]  (gfx9,10)
92609467b48Spatrick ///
92709467b48Spatrick /// \returns Waitcnt with encoded \p Vmcnt, \p Expcnt and \p Lgkmcnt for given
92809467b48Spatrick /// isa \p Version.
92909467b48Spatrick unsigned encodeWaitcnt(const IsaVersion &Version,
93009467b48Spatrick                        unsigned Vmcnt, unsigned Expcnt, unsigned Lgkmcnt);
93109467b48Spatrick 
93209467b48Spatrick unsigned encodeWaitcnt(const IsaVersion &Version, const Waitcnt &Decoded);
93309467b48Spatrick 
93409467b48Spatrick namespace Hwreg {
93509467b48Spatrick 
93609467b48Spatrick LLVM_READONLY
937*d415bd75Srobert int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI);
93809467b48Spatrick 
93909467b48Spatrick LLVM_READNONE
94009467b48Spatrick bool isValidHwreg(int64_t Id);
94109467b48Spatrick 
94209467b48Spatrick LLVM_READNONE
94309467b48Spatrick bool isValidHwregOffset(int64_t Offset);
94409467b48Spatrick 
94509467b48Spatrick LLVM_READNONE
94609467b48Spatrick bool isValidHwregWidth(int64_t Width);
94709467b48Spatrick 
94809467b48Spatrick LLVM_READNONE
94909467b48Spatrick uint64_t encodeHwreg(uint64_t Id, uint64_t Offset, uint64_t Width);
95009467b48Spatrick 
95109467b48Spatrick LLVM_READNONE
95209467b48Spatrick StringRef getHwreg(unsigned Id, const MCSubtargetInfo &STI);
95309467b48Spatrick 
95409467b48Spatrick void decodeHwreg(unsigned Val, unsigned &Id, unsigned &Offset, unsigned &Width);
95509467b48Spatrick 
95609467b48Spatrick } // namespace Hwreg
95709467b48Spatrick 
958*d415bd75Srobert namespace DepCtr {
959*d415bd75Srobert 
960*d415bd75Srobert int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI);
961*d415bd75Srobert int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask,
962*d415bd75Srobert                  const MCSubtargetInfo &STI);
963*d415bd75Srobert bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal,
964*d415bd75Srobert                               const MCSubtargetInfo &STI);
965*d415bd75Srobert bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val,
966*d415bd75Srobert                   bool &IsDefault, const MCSubtargetInfo &STI);
967*d415bd75Srobert 
968*d415bd75Srobert } // namespace DepCtr
969*d415bd75Srobert 
97073471bf0Spatrick namespace Exp {
97173471bf0Spatrick 
97273471bf0Spatrick bool getTgtName(unsigned Id, StringRef &Name, int &Index);
97373471bf0Spatrick 
97473471bf0Spatrick LLVM_READONLY
97573471bf0Spatrick unsigned getTgtId(const StringRef Name);
97673471bf0Spatrick 
97773471bf0Spatrick LLVM_READNONE
97873471bf0Spatrick bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI);
97973471bf0Spatrick 
98073471bf0Spatrick } // namespace Exp
98173471bf0Spatrick 
98273471bf0Spatrick namespace MTBUFFormat {
98373471bf0Spatrick 
98473471bf0Spatrick LLVM_READNONE
98573471bf0Spatrick int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt);
98673471bf0Spatrick 
98773471bf0Spatrick void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt);
98873471bf0Spatrick 
98973471bf0Spatrick int64_t getDfmt(const StringRef Name);
99073471bf0Spatrick 
99173471bf0Spatrick StringRef getDfmtName(unsigned Id);
99273471bf0Spatrick 
99373471bf0Spatrick int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI);
99473471bf0Spatrick 
99573471bf0Spatrick StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI);
99673471bf0Spatrick 
99773471bf0Spatrick bool isValidDfmtNfmt(unsigned Val, const MCSubtargetInfo &STI);
99873471bf0Spatrick 
99973471bf0Spatrick bool isValidNfmt(unsigned Val, const MCSubtargetInfo &STI);
100073471bf0Spatrick 
1001*d415bd75Srobert int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI);
100273471bf0Spatrick 
1003*d415bd75Srobert StringRef getUnifiedFormatName(unsigned Id, const MCSubtargetInfo &STI);
100473471bf0Spatrick 
1005*d415bd75Srobert bool isValidUnifiedFormat(unsigned Val, const MCSubtargetInfo &STI);
100673471bf0Spatrick 
1007*d415bd75Srobert int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt,
1008*d415bd75Srobert                              const MCSubtargetInfo &STI);
100973471bf0Spatrick 
101073471bf0Spatrick bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI);
101173471bf0Spatrick 
101273471bf0Spatrick unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI);
101373471bf0Spatrick 
101473471bf0Spatrick } // namespace MTBUFFormat
101573471bf0Spatrick 
101609467b48Spatrick namespace SendMsg {
101709467b48Spatrick 
101809467b48Spatrick LLVM_READONLY
1019*d415bd75Srobert int64_t getMsgId(const StringRef Name, const MCSubtargetInfo &STI);
102009467b48Spatrick 
102109467b48Spatrick LLVM_READONLY
102209467b48Spatrick int64_t getMsgOpId(int64_t MsgId, const StringRef Name);
102309467b48Spatrick 
102409467b48Spatrick LLVM_READNONE
1025*d415bd75Srobert StringRef getMsgName(int64_t MsgId, const MCSubtargetInfo &STI);
102609467b48Spatrick 
102709467b48Spatrick LLVM_READNONE
1028*d415bd75Srobert StringRef getMsgOpName(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI);
102909467b48Spatrick 
103009467b48Spatrick LLVM_READNONE
1031*d415bd75Srobert bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI);
103209467b48Spatrick 
103309467b48Spatrick LLVM_READNONE
103473471bf0Spatrick bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI,
103573471bf0Spatrick                   bool Strict = true);
103609467b48Spatrick 
103709467b48Spatrick LLVM_READNONE
103873471bf0Spatrick bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId,
103973471bf0Spatrick                       const MCSubtargetInfo &STI, bool Strict = true);
104009467b48Spatrick 
104109467b48Spatrick LLVM_READNONE
1042*d415bd75Srobert bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI);
104309467b48Spatrick 
104409467b48Spatrick LLVM_READNONE
1045*d415bd75Srobert bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI);
104609467b48Spatrick 
1047*d415bd75Srobert void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId,
1048*d415bd75Srobert                uint16_t &StreamId, const MCSubtargetInfo &STI);
104909467b48Spatrick 
105009467b48Spatrick LLVM_READNONE
105109467b48Spatrick uint64_t encodeMsg(uint64_t MsgId,
105209467b48Spatrick                    uint64_t OpId,
105309467b48Spatrick                    uint64_t StreamId);
105409467b48Spatrick 
105509467b48Spatrick } // namespace SendMsg
105609467b48Spatrick 
105709467b48Spatrick 
105809467b48Spatrick unsigned getInitialPSInputAddr(const Function &F);
105909467b48Spatrick 
106073471bf0Spatrick bool getHasColorExport(const Function &F);
106173471bf0Spatrick 
106273471bf0Spatrick bool getHasDepthExport(const Function &F);
106373471bf0Spatrick 
106409467b48Spatrick LLVM_READNONE
106509467b48Spatrick bool isShader(CallingConv::ID CC);
106609467b48Spatrick 
106709467b48Spatrick LLVM_READNONE
106873471bf0Spatrick bool isGraphics(CallingConv::ID CC);
106973471bf0Spatrick 
107073471bf0Spatrick LLVM_READNONE
107109467b48Spatrick bool isCompute(CallingConv::ID CC);
107209467b48Spatrick 
107309467b48Spatrick LLVM_READNONE
107409467b48Spatrick bool isEntryFunctionCC(CallingConv::ID CC);
107509467b48Spatrick 
107673471bf0Spatrick // These functions are considered entrypoints into the current module, i.e. they
107773471bf0Spatrick // are allowed to be called from outside the current module. This is different
107873471bf0Spatrick // from isEntryFunctionCC, which is only true for functions that are entered by
107973471bf0Spatrick // the hardware. Module entry points include all entry functions but also
108073471bf0Spatrick // include functions that can be called from other functions inside or outside
108173471bf0Spatrick // the current module. Module entry functions are allowed to allocate LDS.
108273471bf0Spatrick LLVM_READNONE
108373471bf0Spatrick bool isModuleEntryFunctionCC(CallingConv::ID CC);
108473471bf0Spatrick 
1085*d415bd75Srobert bool isKernelCC(const Function *Func);
1086*d415bd75Srobert 
108709467b48Spatrick // FIXME: Remove this when calling conventions cleaned up
108809467b48Spatrick LLVM_READNONE
isKernel(CallingConv::ID CC)108909467b48Spatrick inline bool isKernel(CallingConv::ID CC) {
109009467b48Spatrick   switch (CC) {
109109467b48Spatrick   case CallingConv::AMDGPU_KERNEL:
109209467b48Spatrick   case CallingConv::SPIR_KERNEL:
109309467b48Spatrick     return true;
109409467b48Spatrick   default:
109509467b48Spatrick     return false;
109609467b48Spatrick   }
109709467b48Spatrick }
109809467b48Spatrick 
109909467b48Spatrick bool hasXNACK(const MCSubtargetInfo &STI);
110009467b48Spatrick bool hasSRAMECC(const MCSubtargetInfo &STI);
110109467b48Spatrick bool hasMIMG_R128(const MCSubtargetInfo &STI);
1102*d415bd75Srobert bool hasA16(const MCSubtargetInfo &STI);
1103097a140dSpatrick bool hasG16(const MCSubtargetInfo &STI);
110409467b48Spatrick bool hasPackedD16(const MCSubtargetInfo &STI);
110509467b48Spatrick 
110609467b48Spatrick bool isSI(const MCSubtargetInfo &STI);
110709467b48Spatrick bool isCI(const MCSubtargetInfo &STI);
110809467b48Spatrick bool isVI(const MCSubtargetInfo &STI);
110909467b48Spatrick bool isGFX9(const MCSubtargetInfo &STI);
1110*d415bd75Srobert bool isGFX9_GFX10(const MCSubtargetInfo &STI);
1111*d415bd75Srobert bool isGFX8_GFX9_GFX10(const MCSubtargetInfo &STI);
1112*d415bd75Srobert bool isGFX8Plus(const MCSubtargetInfo &STI);
111373471bf0Spatrick bool isGFX9Plus(const MCSubtargetInfo &STI);
111409467b48Spatrick bool isGFX10(const MCSubtargetInfo &STI);
111573471bf0Spatrick bool isGFX10Plus(const MCSubtargetInfo &STI);
1116*d415bd75Srobert bool isNotGFX10Plus(const MCSubtargetInfo &STI);
1117*d415bd75Srobert bool isGFX10Before1030(const MCSubtargetInfo &STI);
1118*d415bd75Srobert bool isGFX11(const MCSubtargetInfo &STI);
1119*d415bd75Srobert bool isGFX11Plus(const MCSubtargetInfo &STI);
1120*d415bd75Srobert bool isNotGFX11Plus(const MCSubtargetInfo &STI);
1121097a140dSpatrick bool isGCN3Encoding(const MCSubtargetInfo &STI);
112273471bf0Spatrick bool isGFX10_AEncoding(const MCSubtargetInfo &STI);
1123097a140dSpatrick bool isGFX10_BEncoding(const MCSubtargetInfo &STI);
1124097a140dSpatrick bool hasGFX10_3Insts(const MCSubtargetInfo &STI);
112573471bf0Spatrick bool isGFX90A(const MCSubtargetInfo &STI);
1126*d415bd75Srobert bool isGFX940(const MCSubtargetInfo &STI);
112773471bf0Spatrick bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI);
1128*d415bd75Srobert bool hasMAIInsts(const MCSubtargetInfo &STI);
1129*d415bd75Srobert bool hasVOPD(const MCSubtargetInfo &STI);
1130*d415bd75Srobert int getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR, int32_t ArgNumVGPR);
113109467b48Spatrick 
113209467b48Spatrick /// Is Reg - scalar register
113309467b48Spatrick bool isSGPR(unsigned Reg, const MCRegisterInfo* TRI);
113409467b48Spatrick 
113509467b48Spatrick /// If \p Reg is a pseudo reg, return the correct hardware register given
113609467b48Spatrick /// \p STI otherwise return \p Reg.
113709467b48Spatrick unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI);
113809467b48Spatrick 
113909467b48Spatrick /// Convert hardware register \p Reg to a pseudo register
114009467b48Spatrick LLVM_READNONE
114109467b48Spatrick unsigned mc2PseudoReg(unsigned Reg);
114209467b48Spatrick 
1143*d415bd75Srobert LLVM_READNONE
1144*d415bd75Srobert bool isInlineValue(unsigned Reg);
1145*d415bd75Srobert 
1146*d415bd75Srobert /// Is this an AMDGPU specific source operand? These include registers,
1147*d415bd75Srobert /// inline constants, literals and mandatory literals (KImm).
114809467b48Spatrick bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo);
114909467b48Spatrick 
1150*d415bd75Srobert /// Is this a KImm operand?
1151*d415bd75Srobert bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo);
1152*d415bd75Srobert 
115309467b48Spatrick /// Is this floating-point operand?
115409467b48Spatrick bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo);
115509467b48Spatrick 
1156*d415bd75Srobert /// Does this operand support only inlinable literals?
115709467b48Spatrick bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo);
115809467b48Spatrick 
115909467b48Spatrick /// Get the size in bits of a register from the register class \p RC.
116009467b48Spatrick unsigned getRegBitWidth(unsigned RCID);
116109467b48Spatrick 
116209467b48Spatrick /// Get the size in bits of a register from the register class \p RC.
116309467b48Spatrick unsigned getRegBitWidth(const MCRegisterClass &RC);
116409467b48Spatrick 
116509467b48Spatrick /// Get size of register operand
116609467b48Spatrick unsigned getRegOperandSize(const MCRegisterInfo *MRI, const MCInstrDesc &Desc,
116709467b48Spatrick                            unsigned OpNo);
116809467b48Spatrick 
116909467b48Spatrick LLVM_READNONE
getOperandSize(const MCOperandInfo & OpInfo)117009467b48Spatrick inline unsigned getOperandSize(const MCOperandInfo &OpInfo) {
117109467b48Spatrick   switch (OpInfo.OperandType) {
117209467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_INT32:
117309467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_FP32:
1174*d415bd75Srobert   case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED:
117509467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_INT32:
117609467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_FP32:
117709467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
117809467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
117973471bf0Spatrick   case AMDGPU::OPERAND_REG_IMM_V2INT32:
118073471bf0Spatrick   case AMDGPU::OPERAND_REG_IMM_V2FP32:
118173471bf0Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_V2INT32:
118273471bf0Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_V2FP32:
1183*d415bd75Srobert   case AMDGPU::OPERAND_KIMM32:
1184*d415bd75Srobert   case AMDGPU::OPERAND_KIMM16: // mandatory literal is always size 4
118509467b48Spatrick     return 4;
118609467b48Spatrick 
118709467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_INT64:
118809467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_FP64:
118909467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_INT64:
119009467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_FP64:
119173471bf0Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
119209467b48Spatrick     return 8;
119309467b48Spatrick 
119409467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_INT16:
119509467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_FP16:
1196*d415bd75Srobert   case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED:
119709467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_INT16:
119809467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_FP16:
119909467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
120009467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
120109467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
120209467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
120309467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
120409467b48Spatrick   case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
120509467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_V2INT16:
120609467b48Spatrick   case AMDGPU::OPERAND_REG_IMM_V2FP16:
120709467b48Spatrick     return 2;
120809467b48Spatrick 
120909467b48Spatrick   default:
121009467b48Spatrick     llvm_unreachable("unhandled operand type");
121109467b48Spatrick   }
121209467b48Spatrick }
121309467b48Spatrick 
121409467b48Spatrick LLVM_READNONE
getOperandSize(const MCInstrDesc & Desc,unsigned OpNo)121509467b48Spatrick inline unsigned getOperandSize(const MCInstrDesc &Desc, unsigned OpNo) {
1216*d415bd75Srobert   return getOperandSize(Desc.operands()[OpNo]);
121709467b48Spatrick }
121809467b48Spatrick 
1219097a140dSpatrick /// Is this literal inlinable, and not one of the values intended for floating
1220097a140dSpatrick /// point values.
1221097a140dSpatrick LLVM_READNONE
isInlinableIntLiteral(int64_t Literal)1222097a140dSpatrick inline bool isInlinableIntLiteral(int64_t Literal) {
1223097a140dSpatrick   return Literal >= -16 && Literal <= 64;
1224097a140dSpatrick }
1225097a140dSpatrick 
122609467b48Spatrick /// Is this literal inlinable
122709467b48Spatrick LLVM_READNONE
122809467b48Spatrick bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi);
122909467b48Spatrick 
123009467b48Spatrick LLVM_READNONE
123109467b48Spatrick bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi);
123209467b48Spatrick 
123309467b48Spatrick LLVM_READNONE
123409467b48Spatrick bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi);
123509467b48Spatrick 
123609467b48Spatrick LLVM_READNONE
123709467b48Spatrick bool isInlinableLiteralV216(int32_t Literal, bool HasInv2Pi);
123809467b48Spatrick 
1239097a140dSpatrick LLVM_READNONE
1240097a140dSpatrick bool isInlinableIntLiteralV216(int32_t Literal);
1241097a140dSpatrick 
1242097a140dSpatrick LLVM_READNONE
1243097a140dSpatrick bool isFoldableLiteralV216(int32_t Literal, bool HasInv2Pi);
1244097a140dSpatrick 
124509467b48Spatrick bool isArgPassedInSGPR(const Argument *Arg);
124609467b48Spatrick 
1247097a140dSpatrick LLVM_READONLY
1248097a140dSpatrick bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST,
1249097a140dSpatrick                                       int64_t EncodedOffset);
1250097a140dSpatrick 
1251097a140dSpatrick LLVM_READONLY
1252097a140dSpatrick bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST,
1253097a140dSpatrick                                     int64_t EncodedOffset,
1254097a140dSpatrick                                     bool IsBuffer);
1255097a140dSpatrick 
1256097a140dSpatrick /// Convert \p ByteOffset to dwords if the subtarget uses dword SMRD immediate
1257097a140dSpatrick /// offsets.
1258097a140dSpatrick uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset);
1259097a140dSpatrick 
1260097a140dSpatrick /// \returns The encoding that will be used for \p ByteOffset in the
1261*d415bd75Srobert /// SMRD offset field, or std::nullopt if it won't fit. On GFX9 and GFX10
1262097a140dSpatrick /// S_LOAD instructions have a signed offset, on other subtargets it is
1263097a140dSpatrick /// unsigned. S_BUFFER has an unsigned offset for all subtargets.
1264*d415bd75Srobert std::optional<int64_t> getSMRDEncodedOffset(const MCSubtargetInfo &ST,
1265097a140dSpatrick                                             int64_t ByteOffset, bool IsBuffer);
1266097a140dSpatrick 
1267097a140dSpatrick /// \return The encoding that can be used for a 32-bit literal offset in an SMRD
1268097a140dSpatrick /// instruction. This is only useful on CI.s
1269*d415bd75Srobert std::optional<int64_t> getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST,
1270097a140dSpatrick                                                      int64_t ByteOffset);
127109467b48Spatrick 
127273471bf0Spatrick /// For FLAT segment the offset must be positive;
127373471bf0Spatrick /// MSB is ignored and forced to zero.
127473471bf0Spatrick ///
1275*d415bd75Srobert /// \return The number of bits available for the signed offset field in flat
1276*d415bd75Srobert /// instructions. Note that some forms of the instruction disallow negative
1277*d415bd75Srobert /// offsets.
1278*d415bd75Srobert unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST);
127973471bf0Spatrick 
128009467b48Spatrick /// \returns true if this offset is small enough to fit in the SMRD
128109467b48Spatrick /// offset field.  \p ByteOffset should be the offset in bytes and
128209467b48Spatrick /// not the encoded offset.
128309467b48Spatrick bool isLegalSMRDImmOffset(const MCSubtargetInfo &ST, int64_t ByteOffset);
128409467b48Spatrick 
128509467b48Spatrick bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset,
1286097a140dSpatrick                       const GCNSubtarget *Subtarget,
1287097a140dSpatrick                       Align Alignment = Align(4));
128809467b48Spatrick 
128973471bf0Spatrick LLVM_READNONE
isLegal64BitDPPControl(unsigned DC)129073471bf0Spatrick inline bool isLegal64BitDPPControl(unsigned DC) {
129173471bf0Spatrick   return DC >= DPP::ROW_NEWBCAST_FIRST && DC <= DPP::ROW_NEWBCAST_LAST;
129273471bf0Spatrick }
129373471bf0Spatrick 
129409467b48Spatrick /// \returns true if the intrinsic is divergent
129509467b48Spatrick bool isIntrinsicSourceOfDivergence(unsigned IntrID);
129609467b48Spatrick 
1297*d415bd75Srobert // Track defaults for fields in the MODE register.
129809467b48Spatrick struct SIModeRegisterDefaults {
129909467b48Spatrick   /// Floating point opcodes that support exception flag gathering quiet and
130009467b48Spatrick   /// propagate signaling NaN inputs per IEEE 754-2008. Min_dx10 and max_dx10
130109467b48Spatrick   /// become IEEE 754- 2008 compliant due to signaling NaN propagation and
130209467b48Spatrick   /// quieting.
130309467b48Spatrick   bool IEEE : 1;
130409467b48Spatrick 
130509467b48Spatrick   /// Used by the vector ALU to force DX10-style treatment of NaNs: when set,
130609467b48Spatrick   /// clamp NaN to zero; otherwise, pass NaN through.
130709467b48Spatrick   bool DX10Clamp : 1;
130809467b48Spatrick 
130909467b48Spatrick   /// If this is set, neither input or output denormals are flushed for most f32
131009467b48Spatrick   /// instructions.
1311*d415bd75Srobert   DenormalMode FP32Denormals;
131209467b48Spatrick 
131309467b48Spatrick   /// If this is set, neither input or output denormals are flushed for both f64
131409467b48Spatrick   /// and f16/v2f16 instructions.
1315*d415bd75Srobert   DenormalMode FP64FP16Denormals;
131609467b48Spatrick 
SIModeRegisterDefaultsSIModeRegisterDefaults131709467b48Spatrick   SIModeRegisterDefaults() :
131809467b48Spatrick     IEEE(true),
131909467b48Spatrick     DX10Clamp(true),
1320*d415bd75Srobert     FP32Denormals(DenormalMode::getIEEE()),
1321*d415bd75Srobert     FP64FP16Denormals(DenormalMode::getIEEE()) {}
132209467b48Spatrick 
1323097a140dSpatrick   SIModeRegisterDefaults(const Function &F);
132409467b48Spatrick 
getDefaultForCallingConvSIModeRegisterDefaults132509467b48Spatrick   static SIModeRegisterDefaults getDefaultForCallingConv(CallingConv::ID CC) {
132609467b48Spatrick     SIModeRegisterDefaults Mode;
132773471bf0Spatrick     Mode.IEEE = !AMDGPU::isShader(CC);
132809467b48Spatrick     return Mode;
132909467b48Spatrick   }
133009467b48Spatrick 
133109467b48Spatrick   bool operator ==(const SIModeRegisterDefaults Other) const {
133209467b48Spatrick     return IEEE == Other.IEEE && DX10Clamp == Other.DX10Clamp &&
1333*d415bd75Srobert            FP32Denormals == Other.FP32Denormals &&
1334*d415bd75Srobert            FP64FP16Denormals == Other.FP64FP16Denormals;
1335097a140dSpatrick   }
1336097a140dSpatrick 
allFP32DenormalsSIModeRegisterDefaults1337097a140dSpatrick   bool allFP32Denormals() const {
1338*d415bd75Srobert     return FP32Denormals == DenormalMode::getIEEE();
1339097a140dSpatrick   }
1340097a140dSpatrick 
allFP64FP16DenormalsSIModeRegisterDefaults1341097a140dSpatrick   bool allFP64FP16Denormals() const {
1342*d415bd75Srobert     return FP64FP16Denormals == DenormalMode::getIEEE();
1343097a140dSpatrick   }
1344097a140dSpatrick 
1345097a140dSpatrick   /// Get the encoding value for the FP_DENORM bits of the mode register for the
1346097a140dSpatrick   /// FP32 denormal mode.
fpDenormModeSPValueSIModeRegisterDefaults1347097a140dSpatrick   uint32_t fpDenormModeSPValue() const {
1348*d415bd75Srobert     if (FP32Denormals == DenormalMode::getPreserveSign())
1349097a140dSpatrick       return FP_DENORM_FLUSH_IN_FLUSH_OUT;
1350*d415bd75Srobert     if (FP32Denormals.Output == DenormalMode::PreserveSign)
1351*d415bd75Srobert       return FP_DENORM_FLUSH_OUT;
1352*d415bd75Srobert     if (FP32Denormals.Input == DenormalMode::PreserveSign)
1353*d415bd75Srobert       return FP_DENORM_FLUSH_IN;
1354*d415bd75Srobert     return FP_DENORM_FLUSH_NONE;
1355097a140dSpatrick   }
1356097a140dSpatrick 
1357097a140dSpatrick   /// Get the encoding value for the FP_DENORM bits of the mode register for the
1358097a140dSpatrick   /// FP64/FP16 denormal mode.
fpDenormModeDPValueSIModeRegisterDefaults1359097a140dSpatrick   uint32_t fpDenormModeDPValue() const {
1360*d415bd75Srobert     if (FP64FP16Denormals == DenormalMode::getPreserveSign())
1361097a140dSpatrick       return FP_DENORM_FLUSH_IN_FLUSH_OUT;
1362*d415bd75Srobert     if (FP64FP16Denormals.Output == DenormalMode::PreserveSign)
1363*d415bd75Srobert       return FP_DENORM_FLUSH_OUT;
1364*d415bd75Srobert     if (FP64FP16Denormals.Input == DenormalMode::PreserveSign)
1365*d415bd75Srobert       return FP_DENORM_FLUSH_IN;
1366*d415bd75Srobert     return FP_DENORM_FLUSH_NONE;
136709467b48Spatrick   }
136809467b48Spatrick 
136909467b48Spatrick   /// Returns true if a flag is compatible if it's enabled in the callee, but
137009467b48Spatrick   /// disabled in the caller.
oneWayCompatibleSIModeRegisterDefaults137109467b48Spatrick   static bool oneWayCompatible(bool CallerMode, bool CalleeMode) {
1372097a140dSpatrick     return CallerMode == CalleeMode || (!CallerMode && CalleeMode);
137309467b48Spatrick   }
137409467b48Spatrick 
137509467b48Spatrick   // FIXME: Inlining should be OK for dx10-clamp, since the caller's mode should
137609467b48Spatrick   // be able to override.
isInlineCompatibleSIModeRegisterDefaults137709467b48Spatrick   bool isInlineCompatible(SIModeRegisterDefaults CalleeMode) const {
137809467b48Spatrick     if (DX10Clamp != CalleeMode.DX10Clamp)
137909467b48Spatrick       return false;
138009467b48Spatrick     if (IEEE != CalleeMode.IEEE)
138109467b48Spatrick       return false;
138209467b48Spatrick 
138309467b48Spatrick     // Allow inlining denormals enabled into denormals flushed functions.
1384*d415bd75Srobert     return oneWayCompatible(FP64FP16Denormals.Input !=
1385*d415bd75Srobert                                 DenormalMode::PreserveSign,
1386*d415bd75Srobert                             CalleeMode.FP64FP16Denormals.Input !=
1387*d415bd75Srobert                                 DenormalMode::PreserveSign) &&
1388*d415bd75Srobert            oneWayCompatible(FP64FP16Denormals.Output !=
1389*d415bd75Srobert                                 DenormalMode::PreserveSign,
1390*d415bd75Srobert                             CalleeMode.FP64FP16Denormals.Output !=
1391*d415bd75Srobert                                 DenormalMode::PreserveSign) &&
1392*d415bd75Srobert            oneWayCompatible(FP32Denormals.Input != DenormalMode::PreserveSign,
1393*d415bd75Srobert                             CalleeMode.FP32Denormals.Input !=
1394*d415bd75Srobert                                 DenormalMode::PreserveSign) &&
1395*d415bd75Srobert            oneWayCompatible(FP32Denormals.Output != DenormalMode::PreserveSign,
1396*d415bd75Srobert                             CalleeMode.FP32Denormals.Output !=
1397*d415bd75Srobert                                 DenormalMode::PreserveSign);
139809467b48Spatrick   }
139909467b48Spatrick };
140009467b48Spatrick 
140109467b48Spatrick } // end namespace AMDGPU
140273471bf0Spatrick 
140373471bf0Spatrick raw_ostream &operator<<(raw_ostream &OS,
140473471bf0Spatrick                         const AMDGPU::IsaInfo::TargetIDSetting S);
140573471bf0Spatrick 
140609467b48Spatrick } // end namespace llvm
140709467b48Spatrick 
140809467b48Spatrick #endif // LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H
1409