xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AMDGPUBaseInfo.cpp - AMDGPU Base encoding information --------------===//
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 #include "AMDGPUBaseInfo.h"
100b57cec5SDimitry Andric #include "AMDGPU.h"
110b57cec5SDimitry Andric #include "AMDGPUAsmUtils.h"
12e8d8bef9SDimitry Andric #include "AMDKernelCodeT.h"
13e8d8bef9SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
14*0fca6ea1SDimitry Andric #include "Utils/AMDKernelCodeTUtils.h"
15*0fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h"
160b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
170b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
1806c3fb27SDimitry Andric #include "llvm/IR/Constants.h"
190b57cec5SDimitry Andric #include "llvm/IR/Function.h"
200b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
21480093f4SDimitry Andric #include "llvm/IR/IntrinsicsAMDGPU.h"
22480093f4SDimitry Andric #include "llvm/IR/IntrinsicsR600.h"
230b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
2406c3fb27SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2506c3fb27SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
27e8d8bef9SDimitry Andric #include "llvm/Support/AMDHSAKernelDescriptor.h"
28e8d8bef9SDimitry Andric #include "llvm/Support/CommandLine.h"
2906c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h"
30bdd1243dSDimitry Andric #include <optional>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #define GET_INSTRINFO_NAMED_OPS
330b57cec5SDimitry Andric #define GET_INSTRMAP_INFO
340b57cec5SDimitry Andric #include "AMDGPUGenInstrInfo.inc"
35e8d8bef9SDimitry Andric 
367a6dacacSDimitry Andric static llvm::cl::opt<unsigned> DefaultAMDHSACodeObjectVersion(
377a6dacacSDimitry Andric     "amdhsa-code-object-version", llvm::cl::Hidden,
387a6dacacSDimitry Andric     llvm::cl::init(llvm::AMDGPU::AMDHSA_COV5),
397a6dacacSDimitry Andric     llvm::cl::desc("Set default AMDHSA Code Object Version (module flag "
407a6dacacSDimitry Andric                    "or asm directive still take priority if present)"));
4181ad6265SDimitry Andric 
420b57cec5SDimitry Andric namespace {
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric /// \returns Bit mask for given bit \p Shift and bit \p Width.
getBitMask(unsigned Shift,unsigned Width)450b57cec5SDimitry Andric unsigned getBitMask(unsigned Shift, unsigned Width) {
460b57cec5SDimitry Andric   return ((1 << Width) - 1) << Shift;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric /// Packs \p Src into \p Dst for given bit \p Shift and bit \p Width.
500b57cec5SDimitry Andric ///
510b57cec5SDimitry Andric /// \returns Packed \p Dst.
packBits(unsigned Src,unsigned Dst,unsigned Shift,unsigned Width)520b57cec5SDimitry Andric unsigned packBits(unsigned Src, unsigned Dst, unsigned Shift, unsigned Width) {
5381ad6265SDimitry Andric   unsigned Mask = getBitMask(Shift, Width);
5481ad6265SDimitry Andric   return ((Src << Shift) & Mask) | (Dst & ~Mask);
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric /// Unpacks bits from \p Src for given bit \p Shift and bit \p Width.
580b57cec5SDimitry Andric ///
590b57cec5SDimitry Andric /// \returns Unpacked bits.
unpackBits(unsigned Src,unsigned Shift,unsigned Width)600b57cec5SDimitry Andric unsigned unpackBits(unsigned Src, unsigned Shift, unsigned Width) {
610b57cec5SDimitry Andric   return (Src & getBitMask(Shift, Width)) >> Shift;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric /// \returns Vmcnt bit shift (lower bits).
getVmcntBitShiftLo(unsigned VersionMajor)6581ad6265SDimitry Andric unsigned getVmcntBitShiftLo(unsigned VersionMajor) {
6681ad6265SDimitry Andric   return VersionMajor >= 11 ? 10 : 0;
6781ad6265SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric /// \returns Vmcnt bit width (lower bits).
getVmcntBitWidthLo(unsigned VersionMajor)7081ad6265SDimitry Andric unsigned getVmcntBitWidthLo(unsigned VersionMajor) {
7181ad6265SDimitry Andric   return VersionMajor >= 11 ? 6 : 4;
7281ad6265SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric /// \returns Expcnt bit shift.
getExpcntBitShift(unsigned VersionMajor)7581ad6265SDimitry Andric unsigned getExpcntBitShift(unsigned VersionMajor) {
7681ad6265SDimitry Andric   return VersionMajor >= 11 ? 0 : 4;
7781ad6265SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric /// \returns Expcnt bit width.
getExpcntBitWidth(unsigned VersionMajor)8081ad6265SDimitry Andric unsigned getExpcntBitWidth(unsigned VersionMajor) { return 3; }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric /// \returns Lgkmcnt bit shift.
getLgkmcntBitShift(unsigned VersionMajor)8381ad6265SDimitry Andric unsigned getLgkmcntBitShift(unsigned VersionMajor) {
8481ad6265SDimitry Andric   return VersionMajor >= 11 ? 4 : 8;
8581ad6265SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric /// \returns Lgkmcnt bit width.
getLgkmcntBitWidth(unsigned VersionMajor)880b57cec5SDimitry Andric unsigned getLgkmcntBitWidth(unsigned VersionMajor) {
8981ad6265SDimitry Andric   return VersionMajor >= 10 ? 6 : 4;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric /// \returns Vmcnt bit shift (higher bits).
getVmcntBitShiftHi(unsigned VersionMajor)9381ad6265SDimitry Andric unsigned getVmcntBitShiftHi(unsigned VersionMajor) { return 14; }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric /// \returns Vmcnt bit width (higher bits).
getVmcntBitWidthHi(unsigned VersionMajor)9681ad6265SDimitry Andric unsigned getVmcntBitWidthHi(unsigned VersionMajor) {
9781ad6265SDimitry Andric   return (VersionMajor == 9 || VersionMajor == 10) ? 2 : 0;
9881ad6265SDimitry Andric }
990b57cec5SDimitry Andric 
1007a6dacacSDimitry Andric /// \returns Loadcnt bit width
getLoadcntBitWidth(unsigned VersionMajor)1017a6dacacSDimitry Andric unsigned getLoadcntBitWidth(unsigned VersionMajor) {
1027a6dacacSDimitry Andric   return VersionMajor >= 12 ? 6 : 0;
1037a6dacacSDimitry Andric }
1047a6dacacSDimitry Andric 
1057a6dacacSDimitry Andric /// \returns Samplecnt bit width.
getSamplecntBitWidth(unsigned VersionMajor)1067a6dacacSDimitry Andric unsigned getSamplecntBitWidth(unsigned VersionMajor) {
1077a6dacacSDimitry Andric   return VersionMajor >= 12 ? 6 : 0;
1087a6dacacSDimitry Andric }
1097a6dacacSDimitry Andric 
1107a6dacacSDimitry Andric /// \returns Bvhcnt bit width.
getBvhcntBitWidth(unsigned VersionMajor)1117a6dacacSDimitry Andric unsigned getBvhcntBitWidth(unsigned VersionMajor) {
1127a6dacacSDimitry Andric   return VersionMajor >= 12 ? 3 : 0;
1137a6dacacSDimitry Andric }
1147a6dacacSDimitry Andric 
1157a6dacacSDimitry Andric /// \returns Dscnt bit width.
getDscntBitWidth(unsigned VersionMajor)1167a6dacacSDimitry Andric unsigned getDscntBitWidth(unsigned VersionMajor) {
1177a6dacacSDimitry Andric   return VersionMajor >= 12 ? 6 : 0;
1187a6dacacSDimitry Andric }
1197a6dacacSDimitry Andric 
1207a6dacacSDimitry Andric /// \returns Dscnt bit shift in combined S_WAIT instructions.
getDscntBitShift(unsigned VersionMajor)1217a6dacacSDimitry Andric unsigned getDscntBitShift(unsigned VersionMajor) { return 0; }
1227a6dacacSDimitry Andric 
1237a6dacacSDimitry Andric /// \returns Storecnt or Vscnt bit width, depending on VersionMajor.
getStorecntBitWidth(unsigned VersionMajor)1247a6dacacSDimitry Andric unsigned getStorecntBitWidth(unsigned VersionMajor) {
1257a6dacacSDimitry Andric   return VersionMajor >= 10 ? 6 : 0;
1267a6dacacSDimitry Andric }
1277a6dacacSDimitry Andric 
1287a6dacacSDimitry Andric /// \returns Kmcnt bit width.
getKmcntBitWidth(unsigned VersionMajor)1297a6dacacSDimitry Andric unsigned getKmcntBitWidth(unsigned VersionMajor) {
1307a6dacacSDimitry Andric   return VersionMajor >= 12 ? 5 : 0;
1317a6dacacSDimitry Andric }
1327a6dacacSDimitry Andric 
1337a6dacacSDimitry Andric /// \returns shift for Loadcnt/Storecnt in combined S_WAIT instructions.
getLoadcntStorecntBitShift(unsigned VersionMajor)1347a6dacacSDimitry Andric unsigned getLoadcntStorecntBitShift(unsigned VersionMajor) {
1357a6dacacSDimitry Andric   return VersionMajor >= 12 ? 8 : 0;
1367a6dacacSDimitry Andric }
1377a6dacacSDimitry Andric 
13806c3fb27SDimitry Andric /// \returns VmVsrc bit width
getVmVsrcBitWidth()13906c3fb27SDimitry Andric inline unsigned getVmVsrcBitWidth() { return 3; }
14006c3fb27SDimitry Andric 
14106c3fb27SDimitry Andric /// \returns VmVsrc bit shift
getVmVsrcBitShift()14206c3fb27SDimitry Andric inline unsigned getVmVsrcBitShift() { return 2; }
14306c3fb27SDimitry Andric 
14406c3fb27SDimitry Andric /// \returns VaVdst bit width
getVaVdstBitWidth()14506c3fb27SDimitry Andric inline unsigned getVaVdstBitWidth() { return 4; }
14606c3fb27SDimitry Andric 
14706c3fb27SDimitry Andric /// \returns VaVdst bit shift
getVaVdstBitShift()14806c3fb27SDimitry Andric inline unsigned getVaVdstBitShift() { return 12; }
14906c3fb27SDimitry Andric 
15006c3fb27SDimitry Andric /// \returns SaSdst bit width
getSaSdstBitWidth()15106c3fb27SDimitry Andric inline unsigned getSaSdstBitWidth() { return 1; }
15206c3fb27SDimitry Andric 
15306c3fb27SDimitry Andric /// \returns SaSdst bit shift
getSaSdstBitShift()15406c3fb27SDimitry Andric inline unsigned getSaSdstBitShift() { return 0; }
15506c3fb27SDimitry Andric 
156*0fca6ea1SDimitry Andric } // end anonymous namespace
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric namespace llvm {
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric namespace AMDGPU {
1610b57cec5SDimitry Andric 
162*0fca6ea1SDimitry Andric /// \returns true if the target supports signed immediate offset for SMRD
163*0fca6ea1SDimitry Andric /// instructions.
hasSMRDSignedImmOffset(const MCSubtargetInfo & ST)164*0fca6ea1SDimitry Andric bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST) {
165*0fca6ea1SDimitry Andric   return isGFX9Plus(ST);
166*0fca6ea1SDimitry Andric }
167*0fca6ea1SDimitry Andric 
1685f757f3fSDimitry Andric /// \returns True if \p STI is AMDHSA.
isHsaAbi(const MCSubtargetInfo & STI)1695f757f3fSDimitry Andric bool isHsaAbi(const MCSubtargetInfo &STI) {
1705f757f3fSDimitry Andric   return STI.getTargetTriple().getOS() == Triple::AMDHSA;
1715f757f3fSDimitry Andric }
1725f757f3fSDimitry Andric 
getAMDHSACodeObjectVersion(const Module & M)1737a6dacacSDimitry Andric unsigned getAMDHSACodeObjectVersion(const Module &M) {
17406c3fb27SDimitry Andric   if (auto Ver = mdconst::extract_or_null<ConstantInt>(
175*0fca6ea1SDimitry Andric           M.getModuleFlag("amdhsa_code_object_version"))) {
17606c3fb27SDimitry Andric     return (unsigned)Ver->getZExtValue() / 100;
17706c3fb27SDimitry Andric   }
17806c3fb27SDimitry Andric 
1797a6dacacSDimitry Andric   return getDefaultAMDHSACodeObjectVersion();
1807a6dacacSDimitry Andric }
1817a6dacacSDimitry Andric 
getDefaultAMDHSACodeObjectVersion()1827a6dacacSDimitry Andric unsigned getDefaultAMDHSACodeObjectVersion() {
1837a6dacacSDimitry Andric   return DefaultAMDHSACodeObjectVersion;
1847a6dacacSDimitry Andric }
1857a6dacacSDimitry Andric 
getAMDHSACodeObjectVersion(unsigned ABIVersion)186*0fca6ea1SDimitry Andric unsigned getAMDHSACodeObjectVersion(unsigned ABIVersion) {
187*0fca6ea1SDimitry Andric   switch (ABIVersion) {
188*0fca6ea1SDimitry Andric   case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
189*0fca6ea1SDimitry Andric     return 4;
190*0fca6ea1SDimitry Andric   case ELF::ELFABIVERSION_AMDGPU_HSA_V5:
191*0fca6ea1SDimitry Andric     return 5;
192*0fca6ea1SDimitry Andric   case ELF::ELFABIVERSION_AMDGPU_HSA_V6:
193*0fca6ea1SDimitry Andric     return 6;
194*0fca6ea1SDimitry Andric   default:
195*0fca6ea1SDimitry Andric     return getDefaultAMDHSACodeObjectVersion();
196*0fca6ea1SDimitry Andric   }
197*0fca6ea1SDimitry Andric }
198*0fca6ea1SDimitry Andric 
getELFABIVersion(const Triple & T,unsigned CodeObjectVersion)1997a6dacacSDimitry Andric uint8_t getELFABIVersion(const Triple &T, unsigned CodeObjectVersion) {
2007a6dacacSDimitry Andric   if (T.getOS() != Triple::AMDHSA)
2017a6dacacSDimitry Andric     return 0;
2027a6dacacSDimitry Andric 
2037a6dacacSDimitry Andric   switch (CodeObjectVersion) {
2047a6dacacSDimitry Andric   case 4:
2057a6dacacSDimitry Andric     return ELF::ELFABIVERSION_AMDGPU_HSA_V4;
2067a6dacacSDimitry Andric   case 5:
2077a6dacacSDimitry Andric     return ELF::ELFABIVERSION_AMDGPU_HSA_V5;
208*0fca6ea1SDimitry Andric   case 6:
209*0fca6ea1SDimitry Andric     return ELF::ELFABIVERSION_AMDGPU_HSA_V6;
2107a6dacacSDimitry Andric   default:
2117a6dacacSDimitry Andric     report_fatal_error("Unsupported AMDHSA Code Object Version " +
2127a6dacacSDimitry Andric                        Twine(CodeObjectVersion));
2137a6dacacSDimitry Andric   }
21406c3fb27SDimitry Andric }
21506c3fb27SDimitry Andric 
getMultigridSyncArgImplicitArgPosition(unsigned CodeObjectVersion)21606c3fb27SDimitry Andric unsigned getMultigridSyncArgImplicitArgPosition(unsigned CodeObjectVersion) {
21706c3fb27SDimitry Andric   switch (CodeObjectVersion) {
21806c3fb27SDimitry Andric   case AMDHSA_COV4:
21981ad6265SDimitry Andric     return 48;
22006c3fb27SDimitry Andric   case AMDHSA_COV5:
221*0fca6ea1SDimitry Andric   case AMDHSA_COV6:
22281ad6265SDimitry Andric   default:
22306c3fb27SDimitry Andric     return AMDGPU::ImplicitArg::MULTIGRID_SYNC_ARG_OFFSET;
22481ad6265SDimitry Andric   }
22581ad6265SDimitry Andric }
22681ad6265SDimitry Andric 
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric // FIXME: All such magic numbers about the ABI should be in a
22981ad6265SDimitry Andric // central TD file.
getHostcallImplicitArgPosition(unsigned CodeObjectVersion)23006c3fb27SDimitry Andric unsigned getHostcallImplicitArgPosition(unsigned CodeObjectVersion) {
23106c3fb27SDimitry Andric   switch (CodeObjectVersion) {
23206c3fb27SDimitry Andric   case AMDHSA_COV4:
23381ad6265SDimitry Andric     return 24;
23406c3fb27SDimitry Andric   case AMDHSA_COV5:
235*0fca6ea1SDimitry Andric   case AMDHSA_COV6:
23681ad6265SDimitry Andric   default:
23706c3fb27SDimitry Andric     return AMDGPU::ImplicitArg::HOSTCALL_PTR_OFFSET;
23881ad6265SDimitry Andric   }
23981ad6265SDimitry Andric }
24081ad6265SDimitry Andric 
getDefaultQueueImplicitArgPosition(unsigned CodeObjectVersion)24106c3fb27SDimitry Andric unsigned getDefaultQueueImplicitArgPosition(unsigned CodeObjectVersion) {
24206c3fb27SDimitry Andric   switch (CodeObjectVersion) {
24306c3fb27SDimitry Andric   case AMDHSA_COV4:
244bdd1243dSDimitry Andric     return 32;
24506c3fb27SDimitry Andric   case AMDHSA_COV5:
246*0fca6ea1SDimitry Andric   case AMDHSA_COV6:
247bdd1243dSDimitry Andric   default:
248bdd1243dSDimitry Andric     return AMDGPU::ImplicitArg::DEFAULT_QUEUE_OFFSET;
249bdd1243dSDimitry Andric   }
250bdd1243dSDimitry Andric }
251bdd1243dSDimitry Andric 
getCompletionActionImplicitArgPosition(unsigned CodeObjectVersion)25206c3fb27SDimitry Andric unsigned getCompletionActionImplicitArgPosition(unsigned CodeObjectVersion) {
25306c3fb27SDimitry Andric   switch (CodeObjectVersion) {
25406c3fb27SDimitry Andric   case AMDHSA_COV4:
255bdd1243dSDimitry Andric     return 40;
25606c3fb27SDimitry Andric   case AMDHSA_COV5:
257*0fca6ea1SDimitry Andric   case AMDHSA_COV6:
258bdd1243dSDimitry Andric   default:
259bdd1243dSDimitry Andric     return AMDGPU::ImplicitArg::COMPLETION_ACTION_OFFSET;
260bdd1243dSDimitry Andric   }
261bdd1243dSDimitry Andric }
262bdd1243dSDimitry Andric 
2630b57cec5SDimitry Andric #define GET_MIMGBaseOpcodesTable_IMPL
2640b57cec5SDimitry Andric #define GET_MIMGDimInfoTable_IMPL
2650b57cec5SDimitry Andric #define GET_MIMGInfoTable_IMPL
2660b57cec5SDimitry Andric #define GET_MIMGLZMappingTable_IMPL
2670b57cec5SDimitry Andric #define GET_MIMGMIPMappingTable_IMPL
26804eeddc0SDimitry Andric #define GET_MIMGBiasMappingTable_IMPL
26904eeddc0SDimitry Andric #define GET_MIMGOffsetMappingTable_IMPL
2705ffd83dbSDimitry Andric #define GET_MIMGG16MappingTable_IMPL
27181ad6265SDimitry Andric #define GET_MAIInstInfoTable_IMPL
2720b57cec5SDimitry Andric #include "AMDGPUGenSearchableTables.inc"
2730b57cec5SDimitry Andric 
getMIMGOpcode(unsigned BaseOpcode,unsigned MIMGEncoding,unsigned VDataDwords,unsigned VAddrDwords)2740b57cec5SDimitry Andric int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding,
2750b57cec5SDimitry Andric                   unsigned VDataDwords, unsigned VAddrDwords) {
2760b57cec5SDimitry Andric   const MIMGInfo *Info = getMIMGOpcodeHelper(BaseOpcode, MIMGEncoding,
2770b57cec5SDimitry Andric                                              VDataDwords, VAddrDwords);
2780b57cec5SDimitry Andric   return Info ? Info->Opcode : -1;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
getMIMGBaseOpcode(unsigned Opc)2810b57cec5SDimitry Andric const MIMGBaseOpcodeInfo *getMIMGBaseOpcode(unsigned Opc) {
2820b57cec5SDimitry Andric   const MIMGInfo *Info = getMIMGInfo(Opc);
2830b57cec5SDimitry Andric   return Info ? getMIMGBaseOpcodeInfo(Info->BaseOpcode) : nullptr;
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
getMaskedMIMGOp(unsigned Opc,unsigned NewChannels)2860b57cec5SDimitry Andric int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels) {
2870b57cec5SDimitry Andric   const MIMGInfo *OrigInfo = getMIMGInfo(Opc);
2880b57cec5SDimitry Andric   const MIMGInfo *NewInfo =
2890b57cec5SDimitry Andric       getMIMGOpcodeHelper(OrigInfo->BaseOpcode, OrigInfo->MIMGEncoding,
2900b57cec5SDimitry Andric                           NewChannels, OrigInfo->VAddrDwords);
2910b57cec5SDimitry Andric   return NewInfo ? NewInfo->Opcode : -1;
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric 
getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo * BaseOpcode,const MIMGDimInfo * Dim,bool IsA16,bool IsG16Supported)294fe6060f1SDimitry Andric unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode,
295fe6060f1SDimitry Andric                            const MIMGDimInfo *Dim, bool IsA16,
296fe6060f1SDimitry Andric                            bool IsG16Supported) {
297fe6060f1SDimitry Andric   unsigned AddrWords = BaseOpcode->NumExtraArgs;
298fe6060f1SDimitry Andric   unsigned AddrComponents = (BaseOpcode->Coordinates ? Dim->NumCoords : 0) +
299fe6060f1SDimitry Andric                             (BaseOpcode->LodOrClampOrMip ? 1 : 0);
300fe6060f1SDimitry Andric   if (IsA16)
301fe6060f1SDimitry Andric     AddrWords += divideCeil(AddrComponents, 2);
302fe6060f1SDimitry Andric   else
303fe6060f1SDimitry Andric     AddrWords += AddrComponents;
304fe6060f1SDimitry Andric 
305fe6060f1SDimitry Andric   // Note: For subtargets that support A16 but not G16, enabling A16 also
306fe6060f1SDimitry Andric   // enables 16 bit gradients.
307fe6060f1SDimitry Andric   // For subtargets that support A16 (operand) and G16 (done with a different
308fe6060f1SDimitry Andric   // instruction encoding), they are independent.
309fe6060f1SDimitry Andric 
310fe6060f1SDimitry Andric   if (BaseOpcode->Gradients) {
311fe6060f1SDimitry Andric     if ((IsA16 && !IsG16Supported) || BaseOpcode->G16)
312fe6060f1SDimitry Andric       // There are two gradients per coordinate, we pack them separately.
313fe6060f1SDimitry Andric       // For the 3d case,
314fe6060f1SDimitry Andric       // we get (dy/du, dx/du) (-, dz/du) (dy/dv, dx/dv) (-, dz/dv)
315fe6060f1SDimitry Andric       AddrWords += alignTo<2>(Dim->NumGradients / 2);
316fe6060f1SDimitry Andric     else
317fe6060f1SDimitry Andric       AddrWords += Dim->NumGradients;
318fe6060f1SDimitry Andric   }
319fe6060f1SDimitry Andric   return AddrWords;
320fe6060f1SDimitry Andric }
321fe6060f1SDimitry Andric 
3220b57cec5SDimitry Andric struct MUBUFInfo {
3230b57cec5SDimitry Andric   uint16_t Opcode;
3240b57cec5SDimitry Andric   uint16_t BaseOpcode;
3258bcb0991SDimitry Andric   uint8_t elements;
3260b57cec5SDimitry Andric   bool has_vaddr;
3270b57cec5SDimitry Andric   bool has_srsrc;
3280b57cec5SDimitry Andric   bool has_soffset;
329fe6060f1SDimitry Andric   bool IsBufferInv;
330*0fca6ea1SDimitry Andric   bool tfe;
3310b57cec5SDimitry Andric };
3320b57cec5SDimitry Andric 
3338bcb0991SDimitry Andric struct MTBUFInfo {
3348bcb0991SDimitry Andric   uint16_t Opcode;
3358bcb0991SDimitry Andric   uint16_t BaseOpcode;
3368bcb0991SDimitry Andric   uint8_t elements;
3378bcb0991SDimitry Andric   bool has_vaddr;
3388bcb0991SDimitry Andric   bool has_srsrc;
3398bcb0991SDimitry Andric   bool has_soffset;
3408bcb0991SDimitry Andric };
3418bcb0991SDimitry Andric 
3425ffd83dbSDimitry Andric struct SMInfo {
3435ffd83dbSDimitry Andric   uint16_t Opcode;
3445ffd83dbSDimitry Andric   bool IsBuffer;
3455ffd83dbSDimitry Andric };
3465ffd83dbSDimitry Andric 
347fe6060f1SDimitry Andric struct VOPInfo {
348fe6060f1SDimitry Andric   uint16_t Opcode;
349fe6060f1SDimitry Andric   bool IsSingle;
350fe6060f1SDimitry Andric };
351fe6060f1SDimitry Andric 
35281ad6265SDimitry Andric struct VOPC64DPPInfo {
35381ad6265SDimitry Andric   uint16_t Opcode;
35481ad6265SDimitry Andric };
35581ad6265SDimitry Andric 
356*0fca6ea1SDimitry Andric struct VOPCDPPAsmOnlyInfo {
357*0fca6ea1SDimitry Andric   uint16_t Opcode;
358*0fca6ea1SDimitry Andric };
359*0fca6ea1SDimitry Andric 
360*0fca6ea1SDimitry Andric struct VOP3CDPPAsmOnlyInfo {
361*0fca6ea1SDimitry Andric   uint16_t Opcode;
362*0fca6ea1SDimitry Andric };
363*0fca6ea1SDimitry Andric 
364753f127fSDimitry Andric struct VOPDComponentInfo {
365753f127fSDimitry Andric   uint16_t BaseVOP;
366753f127fSDimitry Andric   uint16_t VOPDOp;
367753f127fSDimitry Andric   bool CanBeVOPDX;
368753f127fSDimitry Andric };
369753f127fSDimitry Andric 
370753f127fSDimitry Andric struct VOPDInfo {
371753f127fSDimitry Andric   uint16_t Opcode;
372753f127fSDimitry Andric   uint16_t OpX;
373753f127fSDimitry Andric   uint16_t OpY;
3745f757f3fSDimitry Andric   uint16_t Subtarget;
375753f127fSDimitry Andric };
376753f127fSDimitry Andric 
377bdd1243dSDimitry Andric struct VOPTrue16Info {
378bdd1243dSDimitry Andric   uint16_t Opcode;
379bdd1243dSDimitry Andric   bool IsTrue16;
380bdd1243dSDimitry Andric };
381bdd1243dSDimitry Andric 
382*0fca6ea1SDimitry Andric struct SingleUseExceptionInfo {
383*0fca6ea1SDimitry Andric   uint16_t Opcode;
384*0fca6ea1SDimitry Andric   bool IsInvalidSingleUseConsumer;
385*0fca6ea1SDimitry Andric   bool IsInvalidSingleUseProducer;
386*0fca6ea1SDimitry Andric };
387*0fca6ea1SDimitry Andric 
3888bcb0991SDimitry Andric #define GET_MTBUFInfoTable_DECL
3898bcb0991SDimitry Andric #define GET_MTBUFInfoTable_IMPL
3900b57cec5SDimitry Andric #define GET_MUBUFInfoTable_DECL
3910b57cec5SDimitry Andric #define GET_MUBUFInfoTable_IMPL
392*0fca6ea1SDimitry Andric #define GET_SingleUseExceptionTable_DECL
393*0fca6ea1SDimitry Andric #define GET_SingleUseExceptionTable_IMPL
3945ffd83dbSDimitry Andric #define GET_SMInfoTable_DECL
3955ffd83dbSDimitry Andric #define GET_SMInfoTable_IMPL
396fe6060f1SDimitry Andric #define GET_VOP1InfoTable_DECL
397fe6060f1SDimitry Andric #define GET_VOP1InfoTable_IMPL
398fe6060f1SDimitry Andric #define GET_VOP2InfoTable_DECL
399fe6060f1SDimitry Andric #define GET_VOP2InfoTable_IMPL
400fe6060f1SDimitry Andric #define GET_VOP3InfoTable_DECL
401fe6060f1SDimitry Andric #define GET_VOP3InfoTable_IMPL
40281ad6265SDimitry Andric #define GET_VOPC64DPPTable_DECL
40381ad6265SDimitry Andric #define GET_VOPC64DPPTable_IMPL
40481ad6265SDimitry Andric #define GET_VOPC64DPP8Table_DECL
40581ad6265SDimitry Andric #define GET_VOPC64DPP8Table_IMPL
406*0fca6ea1SDimitry Andric #define GET_VOPCAsmOnlyInfoTable_DECL
407*0fca6ea1SDimitry Andric #define GET_VOPCAsmOnlyInfoTable_IMPL
408*0fca6ea1SDimitry Andric #define GET_VOP3CAsmOnlyInfoTable_DECL
409*0fca6ea1SDimitry Andric #define GET_VOP3CAsmOnlyInfoTable_IMPL
410753f127fSDimitry Andric #define GET_VOPDComponentTable_DECL
411753f127fSDimitry Andric #define GET_VOPDComponentTable_IMPL
412753f127fSDimitry Andric #define GET_VOPDPairs_DECL
413753f127fSDimitry Andric #define GET_VOPDPairs_IMPL
414bdd1243dSDimitry Andric #define GET_VOPTrue16Table_DECL
415bdd1243dSDimitry Andric #define GET_VOPTrue16Table_IMPL
41681ad6265SDimitry Andric #define GET_WMMAOpcode2AddrMappingTable_DECL
41781ad6265SDimitry Andric #define GET_WMMAOpcode2AddrMappingTable_IMPL
41881ad6265SDimitry Andric #define GET_WMMAOpcode3AddrMappingTable_DECL
41981ad6265SDimitry Andric #define GET_WMMAOpcode3AddrMappingTable_IMPL
4200b57cec5SDimitry Andric #include "AMDGPUGenSearchableTables.inc"
4210b57cec5SDimitry Andric 
getMTBUFBaseOpcode(unsigned Opc)4228bcb0991SDimitry Andric int getMTBUFBaseOpcode(unsigned Opc) {
4238bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFInfoFromOpcode(Opc);
4248bcb0991SDimitry Andric   return Info ? Info->BaseOpcode : -1;
4258bcb0991SDimitry Andric }
4268bcb0991SDimitry Andric 
getMTBUFOpcode(unsigned BaseOpc,unsigned Elements)4278bcb0991SDimitry Andric int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements) {
4288bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFInfoFromBaseOpcodeAndElements(BaseOpc, Elements);
4298bcb0991SDimitry Andric   return Info ? Info->Opcode : -1;
4308bcb0991SDimitry Andric }
4318bcb0991SDimitry Andric 
getMTBUFElements(unsigned Opc)4328bcb0991SDimitry Andric int getMTBUFElements(unsigned Opc) {
4338bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
4348bcb0991SDimitry Andric   return Info ? Info->elements : 0;
4358bcb0991SDimitry Andric }
4368bcb0991SDimitry Andric 
getMTBUFHasVAddr(unsigned Opc)4378bcb0991SDimitry Andric bool getMTBUFHasVAddr(unsigned Opc) {
4388bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
4398bcb0991SDimitry Andric   return Info ? Info->has_vaddr : false;
4408bcb0991SDimitry Andric }
4418bcb0991SDimitry Andric 
getMTBUFHasSrsrc(unsigned Opc)4428bcb0991SDimitry Andric bool getMTBUFHasSrsrc(unsigned Opc) {
4438bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
4448bcb0991SDimitry Andric   return Info ? Info->has_srsrc : false;
4458bcb0991SDimitry Andric }
4468bcb0991SDimitry Andric 
getMTBUFHasSoffset(unsigned Opc)4478bcb0991SDimitry Andric bool getMTBUFHasSoffset(unsigned Opc) {
4488bcb0991SDimitry Andric   const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
4498bcb0991SDimitry Andric   return Info ? Info->has_soffset : false;
4508bcb0991SDimitry Andric }
4518bcb0991SDimitry Andric 
getMUBUFBaseOpcode(unsigned Opc)4520b57cec5SDimitry Andric int getMUBUFBaseOpcode(unsigned Opc) {
4530b57cec5SDimitry Andric   const MUBUFInfo *Info = getMUBUFInfoFromOpcode(Opc);
4540b57cec5SDimitry Andric   return Info ? Info->BaseOpcode : -1;
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
getMUBUFOpcode(unsigned BaseOpc,unsigned Elements)4578bcb0991SDimitry Andric int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements) {
4588bcb0991SDimitry Andric   const MUBUFInfo *Info = getMUBUFInfoFromBaseOpcodeAndElements(BaseOpc, Elements);
4590b57cec5SDimitry Andric   return Info ? Info->Opcode : -1;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
getMUBUFElements(unsigned Opc)4628bcb0991SDimitry Andric int getMUBUFElements(unsigned Opc) {
4630b57cec5SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
4648bcb0991SDimitry Andric   return Info ? Info->elements : 0;
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
getMUBUFHasVAddr(unsigned Opc)4670b57cec5SDimitry Andric bool getMUBUFHasVAddr(unsigned Opc) {
4680b57cec5SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
4690b57cec5SDimitry Andric   return Info ? Info->has_vaddr : false;
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
getMUBUFHasSrsrc(unsigned Opc)4720b57cec5SDimitry Andric bool getMUBUFHasSrsrc(unsigned Opc) {
4730b57cec5SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
4740b57cec5SDimitry Andric   return Info ? Info->has_srsrc : false;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
getMUBUFHasSoffset(unsigned Opc)4770b57cec5SDimitry Andric bool getMUBUFHasSoffset(unsigned Opc) {
4780b57cec5SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
4790b57cec5SDimitry Andric   return Info ? Info->has_soffset : false;
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
getMUBUFIsBufferInv(unsigned Opc)482fe6060f1SDimitry Andric bool getMUBUFIsBufferInv(unsigned Opc) {
483fe6060f1SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
484fe6060f1SDimitry Andric   return Info ? Info->IsBufferInv : false;
485fe6060f1SDimitry Andric }
486fe6060f1SDimitry Andric 
getMUBUFTfe(unsigned Opc)487*0fca6ea1SDimitry Andric bool getMUBUFTfe(unsigned Opc) {
488*0fca6ea1SDimitry Andric   const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
489*0fca6ea1SDimitry Andric   return Info ? Info->tfe : false;
490*0fca6ea1SDimitry Andric }
491*0fca6ea1SDimitry Andric 
getSMEMIsBuffer(unsigned Opc)4925ffd83dbSDimitry Andric bool getSMEMIsBuffer(unsigned Opc) {
4935ffd83dbSDimitry Andric   const SMInfo *Info = getSMEMOpcodeHelper(Opc);
4945ffd83dbSDimitry Andric   return Info ? Info->IsBuffer : false;
4955ffd83dbSDimitry Andric }
4965ffd83dbSDimitry Andric 
getVOP1IsSingle(unsigned Opc)497fe6060f1SDimitry Andric bool getVOP1IsSingle(unsigned Opc) {
498fe6060f1SDimitry Andric   const VOPInfo *Info = getVOP1OpcodeHelper(Opc);
499*0fca6ea1SDimitry Andric   return Info ? Info->IsSingle : true;
500fe6060f1SDimitry Andric }
501fe6060f1SDimitry Andric 
getVOP2IsSingle(unsigned Opc)502fe6060f1SDimitry Andric bool getVOP2IsSingle(unsigned Opc) {
503fe6060f1SDimitry Andric   const VOPInfo *Info = getVOP2OpcodeHelper(Opc);
504*0fca6ea1SDimitry Andric   return Info ? Info->IsSingle : true;
505fe6060f1SDimitry Andric }
506fe6060f1SDimitry Andric 
getVOP3IsSingle(unsigned Opc)507fe6060f1SDimitry Andric bool getVOP3IsSingle(unsigned Opc) {
508fe6060f1SDimitry Andric   const VOPInfo *Info = getVOP3OpcodeHelper(Opc);
509*0fca6ea1SDimitry Andric   return Info ? Info->IsSingle : true;
510fe6060f1SDimitry Andric }
511fe6060f1SDimitry Andric 
isVOPC64DPP(unsigned Opc)51281ad6265SDimitry Andric bool isVOPC64DPP(unsigned Opc) {
51381ad6265SDimitry Andric   return isVOPC64DPPOpcodeHelper(Opc) || isVOPC64DPP8OpcodeHelper(Opc);
51481ad6265SDimitry Andric }
51581ad6265SDimitry Andric 
isVOPCAsmOnly(unsigned Opc)516*0fca6ea1SDimitry Andric bool isVOPCAsmOnly(unsigned Opc) { return isVOPCAsmOnlyOpcodeHelper(Opc); }
517*0fca6ea1SDimitry Andric 
getMAIIsDGEMM(unsigned Opc)51881ad6265SDimitry Andric bool getMAIIsDGEMM(unsigned Opc) {
51981ad6265SDimitry Andric   const MAIInstInfo *Info = getMAIInstInfoHelper(Opc);
52081ad6265SDimitry Andric   return Info ? Info->is_dgemm : false;
52181ad6265SDimitry Andric }
52281ad6265SDimitry Andric 
getMAIIsGFX940XDL(unsigned Opc)52381ad6265SDimitry Andric bool getMAIIsGFX940XDL(unsigned Opc) {
52481ad6265SDimitry Andric   const MAIInstInfo *Info = getMAIInstInfoHelper(Opc);
52581ad6265SDimitry Andric   return Info ? Info->is_gfx940_xdl : false;
52681ad6265SDimitry Andric }
52781ad6265SDimitry Andric 
getVOPDEncodingFamily(const MCSubtargetInfo & ST)5285f757f3fSDimitry Andric unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST) {
5295f757f3fSDimitry Andric   if (ST.hasFeature(AMDGPU::FeatureGFX12Insts))
5305f757f3fSDimitry Andric     return SIEncodingFamily::GFX12;
5315f757f3fSDimitry Andric   if (ST.hasFeature(AMDGPU::FeatureGFX11Insts))
5325f757f3fSDimitry Andric     return SIEncodingFamily::GFX11;
5335f757f3fSDimitry Andric   llvm_unreachable("Subtarget generation does not support VOPD!");
5345f757f3fSDimitry Andric }
5355f757f3fSDimitry Andric 
getCanBeVOPD(unsigned Opc)536753f127fSDimitry Andric CanBeVOPD getCanBeVOPD(unsigned Opc) {
537753f127fSDimitry Andric   const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc);
538753f127fSDimitry Andric   if (Info)
539fcaf7f86SDimitry Andric     return {Info->CanBeVOPDX, true};
540fcaf7f86SDimitry Andric   return {false, false};
541753f127fSDimitry Andric }
542753f127fSDimitry Andric 
getVOPDOpcode(unsigned Opc)543753f127fSDimitry Andric unsigned getVOPDOpcode(unsigned Opc) {
544753f127fSDimitry Andric   const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc);
545753f127fSDimitry Andric   return Info ? Info->VOPDOp : ~0u;
546753f127fSDimitry Andric }
547753f127fSDimitry Andric 
isVOPD(unsigned Opc)548bdd1243dSDimitry Andric bool isVOPD(unsigned Opc) {
549bdd1243dSDimitry Andric   return AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0X);
550bdd1243dSDimitry Andric }
551bdd1243dSDimitry Andric 
isMAC(unsigned Opc)552bdd1243dSDimitry Andric bool isMAC(unsigned Opc) {
553bdd1243dSDimitry Andric   return Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 ||
554bdd1243dSDimitry Andric          Opc == AMDGPU::V_MAC_F32_e64_gfx10 ||
555bdd1243dSDimitry Andric          Opc == AMDGPU::V_MAC_F32_e64_vi ||
556bdd1243dSDimitry Andric          Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx6_gfx7 ||
557bdd1243dSDimitry Andric          Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx10 ||
558bdd1243dSDimitry Andric          Opc == AMDGPU::V_MAC_F16_e64_vi ||
559bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F64_e64_gfx90a ||
560bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F32_e64_gfx10 ||
561bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F32_e64_gfx11 ||
5625f757f3fSDimitry Andric          Opc == AMDGPU::V_FMAC_F32_e64_gfx12 ||
563bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F32_e64_vi ||
564bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_LEGACY_F32_e64_gfx10 ||
565bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_DX9_ZERO_F32_e64_gfx11 ||
566bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F16_e64_gfx10 ||
567bdd1243dSDimitry Andric          Opc == AMDGPU::V_FMAC_F16_t16_e64_gfx11 ||
5685f757f3fSDimitry Andric          Opc == AMDGPU::V_FMAC_F16_t16_e64_gfx12 ||
569bdd1243dSDimitry Andric          Opc == AMDGPU::V_DOT2C_F32_F16_e64_vi ||
570bdd1243dSDimitry Andric          Opc == AMDGPU::V_DOT2C_I32_I16_e64_vi ||
571bdd1243dSDimitry Andric          Opc == AMDGPU::V_DOT4C_I32_I8_e64_vi ||
572bdd1243dSDimitry Andric          Opc == AMDGPU::V_DOT8C_I32_I4_e64_vi;
573bdd1243dSDimitry Andric }
574bdd1243dSDimitry Andric 
isPermlane16(unsigned Opc)575bdd1243dSDimitry Andric bool isPermlane16(unsigned Opc) {
576bdd1243dSDimitry Andric   return Opc == AMDGPU::V_PERMLANE16_B32_gfx10 ||
577bdd1243dSDimitry Andric          Opc == AMDGPU::V_PERMLANEX16_B32_gfx10 ||
578bdd1243dSDimitry Andric          Opc == AMDGPU::V_PERMLANE16_B32_e64_gfx11 ||
5795f757f3fSDimitry Andric          Opc == AMDGPU::V_PERMLANEX16_B32_e64_gfx11 ||
5805f757f3fSDimitry Andric          Opc == AMDGPU::V_PERMLANE16_B32_e64_gfx12 ||
5815f757f3fSDimitry Andric          Opc == AMDGPU::V_PERMLANEX16_B32_e64_gfx12 ||
5825f757f3fSDimitry Andric          Opc == AMDGPU::V_PERMLANE16_VAR_B32_e64_gfx12 ||
5835f757f3fSDimitry Andric          Opc == AMDGPU::V_PERMLANEX16_VAR_B32_e64_gfx12;
5845f757f3fSDimitry Andric }
5855f757f3fSDimitry Andric 
isCvt_F32_Fp8_Bf8_e64(unsigned Opc)586b3edf446SDimitry Andric bool isCvt_F32_Fp8_Bf8_e64(unsigned Opc) {
587b3edf446SDimitry Andric   return Opc == AMDGPU::V_CVT_F32_BF8_e64_gfx12 ||
588b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_F32_FP8_e64_gfx12 ||
589b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_F32_BF8_e64_dpp_gfx12 ||
590b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_F32_FP8_e64_dpp_gfx12 ||
591b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_F32_BF8_e64_dpp8_gfx12 ||
592b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_F32_FP8_e64_dpp8_gfx12 ||
593b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_PK_F32_BF8_e64_gfx12 ||
594b3edf446SDimitry Andric          Opc == AMDGPU::V_CVT_PK_F32_FP8_e64_gfx12;
595b3edf446SDimitry Andric }
596b3edf446SDimitry Andric 
isGenericAtomic(unsigned Opc)5975f757f3fSDimitry Andric bool isGenericAtomic(unsigned Opc) {
598*0fca6ea1SDimitry Andric   return Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP ||
5995f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD ||
6005f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB ||
6015f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN ||
6025f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN ||
6035f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX ||
6045f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX ||
6055f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND ||
6065f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR ||
6075f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR ||
6085f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC ||
6095f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC ||
6105f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD ||
6115f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN ||
6125f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX ||
6135f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP ||
6145f757f3fSDimitry Andric          Opc == AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG;
615bdd1243dSDimitry Andric }
616bdd1243dSDimitry Andric 
isTrue16Inst(unsigned Opc)617bdd1243dSDimitry Andric bool isTrue16Inst(unsigned Opc) {
618bdd1243dSDimitry Andric   const VOPTrue16Info *Info = getTrue16OpcodeHelper(Opc);
619bdd1243dSDimitry Andric   return Info ? Info->IsTrue16 : false;
620bdd1243dSDimitry Andric }
621bdd1243dSDimitry Andric 
isInvalidSingleUseConsumerInst(unsigned Opc)622*0fca6ea1SDimitry Andric bool isInvalidSingleUseConsumerInst(unsigned Opc) {
623*0fca6ea1SDimitry Andric   const SingleUseExceptionInfo *Info = getSingleUseExceptionHelper(Opc);
624*0fca6ea1SDimitry Andric   return Info && Info->IsInvalidSingleUseConsumer;
625*0fca6ea1SDimitry Andric }
626*0fca6ea1SDimitry Andric 
isInvalidSingleUseProducerInst(unsigned Opc)627*0fca6ea1SDimitry Andric bool isInvalidSingleUseProducerInst(unsigned Opc) {
628*0fca6ea1SDimitry Andric   const SingleUseExceptionInfo *Info = getSingleUseExceptionHelper(Opc);
629*0fca6ea1SDimitry Andric   return Info && Info->IsInvalidSingleUseProducer;
630*0fca6ea1SDimitry Andric }
631*0fca6ea1SDimitry Andric 
mapWMMA2AddrTo3AddrOpcode(unsigned Opc)63281ad6265SDimitry Andric unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc) {
63381ad6265SDimitry Andric   const WMMAOpcodeMappingInfo *Info = getWMMAMappingInfoFrom2AddrOpcode(Opc);
63481ad6265SDimitry Andric   return Info ? Info->Opcode3Addr : ~0u;
63581ad6265SDimitry Andric }
63681ad6265SDimitry Andric 
mapWMMA3AddrTo2AddrOpcode(unsigned Opc)63781ad6265SDimitry Andric unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc) {
63881ad6265SDimitry Andric   const WMMAOpcodeMappingInfo *Info = getWMMAMappingInfoFrom3AddrOpcode(Opc);
63981ad6265SDimitry Andric   return Info ? Info->Opcode2Addr : ~0u;
64081ad6265SDimitry Andric }
64181ad6265SDimitry Andric 
6420b57cec5SDimitry Andric // Wrapper for Tablegen'd function.  enum Subtarget is not defined in any
6430b57cec5SDimitry Andric // header files, so we need to wrap it in a function that takes unsigned
6440b57cec5SDimitry Andric // instead.
getMCOpcode(uint16_t Opcode,unsigned Gen)6450b57cec5SDimitry Andric int getMCOpcode(uint16_t Opcode, unsigned Gen) {
6460b57cec5SDimitry Andric   return getMCOpcodeGen(Opcode, static_cast<Subtarget>(Gen));
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
getVOPDFull(unsigned OpX,unsigned OpY,unsigned EncodingFamily)6495f757f3fSDimitry Andric int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily) {
6505f757f3fSDimitry Andric   const VOPDInfo *Info =
6515f757f3fSDimitry Andric       getVOPDInfoFromComponentOpcodes(OpX, OpY, EncodingFamily);
652753f127fSDimitry Andric   return Info ? Info->Opcode : -1;
653753f127fSDimitry Andric }
654753f127fSDimitry Andric 
getVOPDComponents(unsigned VOPDOpcode)655bdd1243dSDimitry Andric std::pair<unsigned, unsigned> getVOPDComponents(unsigned VOPDOpcode) {
656bdd1243dSDimitry Andric   const VOPDInfo *Info = getVOPDOpcodeHelper(VOPDOpcode);
657bdd1243dSDimitry Andric   assert(Info);
658bdd1243dSDimitry Andric   auto OpX = getVOPDBaseFromComponent(Info->OpX);
659bdd1243dSDimitry Andric   auto OpY = getVOPDBaseFromComponent(Info->OpY);
660bdd1243dSDimitry Andric   assert(OpX && OpY);
661bdd1243dSDimitry Andric   return {OpX->BaseVOP, OpY->BaseVOP};
662bdd1243dSDimitry Andric }
663bdd1243dSDimitry Andric 
664bdd1243dSDimitry Andric namespace VOPD {
665bdd1243dSDimitry Andric 
ComponentProps(const MCInstrDesc & OpDesc)666bdd1243dSDimitry Andric ComponentProps::ComponentProps(const MCInstrDesc &OpDesc) {
667bdd1243dSDimitry Andric   assert(OpDesc.getNumDefs() == Component::DST_NUM);
668bdd1243dSDimitry Andric 
669bdd1243dSDimitry Andric   assert(OpDesc.getOperandConstraint(Component::SRC0, MCOI::TIED_TO) == -1);
670bdd1243dSDimitry Andric   assert(OpDesc.getOperandConstraint(Component::SRC1, MCOI::TIED_TO) == -1);
671bdd1243dSDimitry Andric   auto TiedIdx = OpDesc.getOperandConstraint(Component::SRC2, MCOI::TIED_TO);
672bdd1243dSDimitry Andric   assert(TiedIdx == -1 || TiedIdx == Component::DST);
673bdd1243dSDimitry Andric   HasSrc2Acc = TiedIdx != -1;
674bdd1243dSDimitry Andric 
675bdd1243dSDimitry Andric   SrcOperandsNum = OpDesc.getNumOperands() - OpDesc.getNumDefs();
676bdd1243dSDimitry Andric   assert(SrcOperandsNum <= Component::MAX_SRC_NUM);
677bdd1243dSDimitry Andric 
678bdd1243dSDimitry Andric   auto OperandsNum = OpDesc.getNumOperands();
679bdd1243dSDimitry Andric   unsigned CompOprIdx;
680bdd1243dSDimitry Andric   for (CompOprIdx = Component::SRC1; CompOprIdx < OperandsNum; ++CompOprIdx) {
681bdd1243dSDimitry Andric     if (OpDesc.operands()[CompOprIdx].OperandType == AMDGPU::OPERAND_KIMM32) {
682bdd1243dSDimitry Andric       MandatoryLiteralIdx = CompOprIdx;
683bdd1243dSDimitry Andric       break;
684bdd1243dSDimitry Andric     }
685bdd1243dSDimitry Andric   }
686bdd1243dSDimitry Andric }
687bdd1243dSDimitry Andric 
getIndexInParsedOperands(unsigned CompOprIdx) const688bdd1243dSDimitry Andric unsigned ComponentInfo::getIndexInParsedOperands(unsigned CompOprIdx) const {
689bdd1243dSDimitry Andric   assert(CompOprIdx < Component::MAX_OPR_NUM);
690bdd1243dSDimitry Andric 
691bdd1243dSDimitry Andric   if (CompOprIdx == Component::DST)
692bdd1243dSDimitry Andric     return getIndexOfDstInParsedOperands();
693bdd1243dSDimitry Andric 
694bdd1243dSDimitry Andric   auto CompSrcIdx = CompOprIdx - Component::DST_NUM;
695bdd1243dSDimitry Andric   if (CompSrcIdx < getCompParsedSrcOperandsNum())
696bdd1243dSDimitry Andric     return getIndexOfSrcInParsedOperands(CompSrcIdx);
697bdd1243dSDimitry Andric 
698bdd1243dSDimitry Andric   // The specified operand does not exist.
699bdd1243dSDimitry Andric   return 0;
700bdd1243dSDimitry Andric }
701bdd1243dSDimitry Andric 
getInvalidCompOperandIndex(std::function<unsigned (unsigned,unsigned)> GetRegIdx,bool SkipSrc) const702bdd1243dSDimitry Andric std::optional<unsigned> InstInfo::getInvalidCompOperandIndex(
7035f757f3fSDimitry Andric     std::function<unsigned(unsigned, unsigned)> GetRegIdx, bool SkipSrc) const {
704bdd1243dSDimitry Andric 
705bdd1243dSDimitry Andric   auto OpXRegs = getRegIndices(ComponentIndex::X, GetRegIdx);
706bdd1243dSDimitry Andric   auto OpYRegs = getRegIndices(ComponentIndex::Y, GetRegIdx);
707bdd1243dSDimitry Andric 
7085f757f3fSDimitry Andric   const unsigned CompOprNum =
7095f757f3fSDimitry Andric       SkipSrc ? Component::DST_NUM : Component::MAX_OPR_NUM;
710bdd1243dSDimitry Andric   unsigned CompOprIdx;
7115f757f3fSDimitry Andric   for (CompOprIdx = 0; CompOprIdx < CompOprNum; ++CompOprIdx) {
71206c3fb27SDimitry Andric     unsigned BanksMasks = VOPD_VGPR_BANK_MASKS[CompOprIdx];
713bdd1243dSDimitry Andric     if (OpXRegs[CompOprIdx] && OpYRegs[CompOprIdx] &&
71406c3fb27SDimitry Andric         ((OpXRegs[CompOprIdx] & BanksMasks) ==
71506c3fb27SDimitry Andric          (OpYRegs[CompOprIdx] & BanksMasks)))
716bdd1243dSDimitry Andric       return CompOprIdx;
717bdd1243dSDimitry Andric   }
718bdd1243dSDimitry Andric 
719bdd1243dSDimitry Andric   return {};
720bdd1243dSDimitry Andric }
721bdd1243dSDimitry Andric 
722bdd1243dSDimitry Andric // Return an array of VGPR registers [DST,SRC0,SRC1,SRC2] used
723bdd1243dSDimitry Andric // by the specified component. If an operand is unused
724bdd1243dSDimitry Andric // or is not a VGPR, the corresponding value is 0.
725bdd1243dSDimitry Andric //
726bdd1243dSDimitry Andric // GetRegIdx(Component, MCOperandIdx) must return a VGPR register index
727bdd1243dSDimitry Andric // for the specified component and MC operand. The callback must return 0
728bdd1243dSDimitry Andric // if the operand is not a register or not a VGPR.
getRegIndices(unsigned CompIdx,std::function<unsigned (unsigned,unsigned)> GetRegIdx) const729bdd1243dSDimitry Andric InstInfo::RegIndices InstInfo::getRegIndices(
730bdd1243dSDimitry Andric     unsigned CompIdx,
731bdd1243dSDimitry Andric     std::function<unsigned(unsigned, unsigned)> GetRegIdx) const {
732bdd1243dSDimitry Andric   assert(CompIdx < COMPONENTS_NUM);
733bdd1243dSDimitry Andric 
734bdd1243dSDimitry Andric   const auto &Comp = CompInfo[CompIdx];
735bdd1243dSDimitry Andric   InstInfo::RegIndices RegIndices;
736bdd1243dSDimitry Andric 
737bdd1243dSDimitry Andric   RegIndices[DST] = GetRegIdx(CompIdx, Comp.getIndexOfDstInMCOperands());
738bdd1243dSDimitry Andric 
739bdd1243dSDimitry Andric   for (unsigned CompOprIdx : {SRC0, SRC1, SRC2}) {
740bdd1243dSDimitry Andric     unsigned CompSrcIdx = CompOprIdx - DST_NUM;
741bdd1243dSDimitry Andric     RegIndices[CompOprIdx] =
742bdd1243dSDimitry Andric         Comp.hasRegSrcOperand(CompSrcIdx)
743bdd1243dSDimitry Andric             ? GetRegIdx(CompIdx, Comp.getIndexOfSrcInMCOperands(CompSrcIdx))
744bdd1243dSDimitry Andric             : 0;
745bdd1243dSDimitry Andric   }
746bdd1243dSDimitry Andric   return RegIndices;
747bdd1243dSDimitry Andric }
748bdd1243dSDimitry Andric 
749bdd1243dSDimitry Andric } // namespace VOPD
750bdd1243dSDimitry Andric 
getVOPDInstInfo(const MCInstrDesc & OpX,const MCInstrDesc & OpY)751bdd1243dSDimitry Andric VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY) {
752bdd1243dSDimitry Andric   return VOPD::InstInfo(OpX, OpY);
753bdd1243dSDimitry Andric }
754bdd1243dSDimitry Andric 
getVOPDInstInfo(unsigned VOPDOpcode,const MCInstrInfo * InstrInfo)755bdd1243dSDimitry Andric VOPD::InstInfo getVOPDInstInfo(unsigned VOPDOpcode,
756bdd1243dSDimitry Andric                                const MCInstrInfo *InstrInfo) {
757bdd1243dSDimitry Andric   auto [OpX, OpY] = getVOPDComponents(VOPDOpcode);
758bdd1243dSDimitry Andric   const auto &OpXDesc = InstrInfo->get(OpX);
759bdd1243dSDimitry Andric   const auto &OpYDesc = InstrInfo->get(OpY);
760bdd1243dSDimitry Andric   VOPD::ComponentInfo OpXInfo(OpXDesc, VOPD::ComponentKind::COMPONENT_X);
761bdd1243dSDimitry Andric   VOPD::ComponentInfo OpYInfo(OpYDesc, OpXInfo);
762bdd1243dSDimitry Andric   return VOPD::InstInfo(OpXInfo, OpYInfo);
763bdd1243dSDimitry Andric }
764bdd1243dSDimitry Andric 
7650b57cec5SDimitry Andric namespace IsaInfo {
7660b57cec5SDimitry Andric 
AMDGPUTargetID(const MCSubtargetInfo & STI)767e8d8bef9SDimitry Andric AMDGPUTargetID::AMDGPUTargetID(const MCSubtargetInfo &STI)
768fe6060f1SDimitry Andric     : STI(STI), XnackSetting(TargetIDSetting::Any),
7697a6dacacSDimitry Andric       SramEccSetting(TargetIDSetting::Any) {
770e8d8bef9SDimitry Andric   if (!STI.getFeatureBits().test(FeatureSupportsXNACK))
771e8d8bef9SDimitry Andric     XnackSetting = TargetIDSetting::Unsupported;
772e8d8bef9SDimitry Andric   if (!STI.getFeatureBits().test(FeatureSupportsSRAMECC))
773e8d8bef9SDimitry Andric     SramEccSetting = TargetIDSetting::Unsupported;
774e8d8bef9SDimitry Andric }
775e8d8bef9SDimitry Andric 
setTargetIDFromFeaturesString(StringRef FS)776e8d8bef9SDimitry Andric void AMDGPUTargetID::setTargetIDFromFeaturesString(StringRef FS) {
777e8d8bef9SDimitry Andric   // Check if xnack or sramecc is explicitly enabled or disabled.  In the
778e8d8bef9SDimitry Andric   // absence of the target features we assume we must generate code that can run
779e8d8bef9SDimitry Andric   // in any environment.
780e8d8bef9SDimitry Andric   SubtargetFeatures Features(FS);
781bdd1243dSDimitry Andric   std::optional<bool> XnackRequested;
782bdd1243dSDimitry Andric   std::optional<bool> SramEccRequested;
783e8d8bef9SDimitry Andric 
784e8d8bef9SDimitry Andric   for (const std::string &Feature : Features.getFeatures()) {
785e8d8bef9SDimitry Andric     if (Feature == "+xnack")
786e8d8bef9SDimitry Andric       XnackRequested = true;
787e8d8bef9SDimitry Andric     else if (Feature == "-xnack")
788e8d8bef9SDimitry Andric       XnackRequested = false;
789e8d8bef9SDimitry Andric     else if (Feature == "+sramecc")
790e8d8bef9SDimitry Andric       SramEccRequested = true;
791e8d8bef9SDimitry Andric     else if (Feature == "-sramecc")
792e8d8bef9SDimitry Andric       SramEccRequested = false;
793e8d8bef9SDimitry Andric   }
794e8d8bef9SDimitry Andric 
795e8d8bef9SDimitry Andric   bool XnackSupported = isXnackSupported();
796e8d8bef9SDimitry Andric   bool SramEccSupported = isSramEccSupported();
797e8d8bef9SDimitry Andric 
798e8d8bef9SDimitry Andric   if (XnackRequested) {
799e8d8bef9SDimitry Andric     if (XnackSupported) {
800e8d8bef9SDimitry Andric       XnackSetting =
801e8d8bef9SDimitry Andric           *XnackRequested ? TargetIDSetting::On : TargetIDSetting::Off;
802e8d8bef9SDimitry Andric     } else {
803e8d8bef9SDimitry Andric       // If a specific xnack setting was requested and this GPU does not support
804e8d8bef9SDimitry Andric       // xnack emit a warning. Setting will remain set to "Unsupported".
805e8d8bef9SDimitry Andric       if (*XnackRequested) {
806e8d8bef9SDimitry Andric         errs() << "warning: xnack 'On' was requested for a processor that does "
807e8d8bef9SDimitry Andric                   "not support it!\n";
808e8d8bef9SDimitry Andric       } else {
809e8d8bef9SDimitry Andric         errs() << "warning: xnack 'Off' was requested for a processor that "
810e8d8bef9SDimitry Andric                   "does not support it!\n";
811e8d8bef9SDimitry Andric       }
812e8d8bef9SDimitry Andric     }
813e8d8bef9SDimitry Andric   }
814e8d8bef9SDimitry Andric 
815e8d8bef9SDimitry Andric   if (SramEccRequested) {
816e8d8bef9SDimitry Andric     if (SramEccSupported) {
817e8d8bef9SDimitry Andric       SramEccSetting =
818e8d8bef9SDimitry Andric           *SramEccRequested ? TargetIDSetting::On : TargetIDSetting::Off;
819e8d8bef9SDimitry Andric     } else {
820e8d8bef9SDimitry Andric       // If a specific sramecc setting was requested and this GPU does not
821e8d8bef9SDimitry Andric       // support sramecc emit a warning. Setting will remain set to
822e8d8bef9SDimitry Andric       // "Unsupported".
823e8d8bef9SDimitry Andric       if (*SramEccRequested) {
824e8d8bef9SDimitry Andric         errs() << "warning: sramecc 'On' was requested for a processor that "
825e8d8bef9SDimitry Andric                   "does not support it!\n";
826e8d8bef9SDimitry Andric       } else {
827e8d8bef9SDimitry Andric         errs() << "warning: sramecc 'Off' was requested for a processor that "
828e8d8bef9SDimitry Andric                   "does not support it!\n";
829e8d8bef9SDimitry Andric       }
830e8d8bef9SDimitry Andric     }
831e8d8bef9SDimitry Andric   }
832e8d8bef9SDimitry Andric }
833e8d8bef9SDimitry Andric 
834e8d8bef9SDimitry Andric static TargetIDSetting
getTargetIDSettingFromFeatureString(StringRef FeatureString)835e8d8bef9SDimitry Andric getTargetIDSettingFromFeatureString(StringRef FeatureString) {
8365f757f3fSDimitry Andric   if (FeatureString.ends_with("-"))
837e8d8bef9SDimitry Andric     return TargetIDSetting::Off;
8385f757f3fSDimitry Andric   if (FeatureString.ends_with("+"))
839e8d8bef9SDimitry Andric     return TargetIDSetting::On;
840e8d8bef9SDimitry Andric 
841e8d8bef9SDimitry Andric   llvm_unreachable("Malformed feature string");
842e8d8bef9SDimitry Andric }
843e8d8bef9SDimitry Andric 
setTargetIDFromTargetIDStream(StringRef TargetID)844e8d8bef9SDimitry Andric void AMDGPUTargetID::setTargetIDFromTargetIDStream(StringRef TargetID) {
845e8d8bef9SDimitry Andric   SmallVector<StringRef, 3> TargetIDSplit;
846e8d8bef9SDimitry Andric   TargetID.split(TargetIDSplit, ':');
847e8d8bef9SDimitry Andric 
848e8d8bef9SDimitry Andric   for (const auto &FeatureString : TargetIDSplit) {
8495f757f3fSDimitry Andric     if (FeatureString.starts_with("xnack"))
850e8d8bef9SDimitry Andric       XnackSetting = getTargetIDSettingFromFeatureString(FeatureString);
8515f757f3fSDimitry Andric     if (FeatureString.starts_with("sramecc"))
852e8d8bef9SDimitry Andric       SramEccSetting = getTargetIDSettingFromFeatureString(FeatureString);
853e8d8bef9SDimitry Andric   }
854e8d8bef9SDimitry Andric }
855e8d8bef9SDimitry Andric 
toString() const856fe6060f1SDimitry Andric std::string AMDGPUTargetID::toString() const {
85704eeddc0SDimitry Andric   std::string StringRep;
858fe6060f1SDimitry Andric   raw_string_ostream StreamRep(StringRep);
8590b57cec5SDimitry Andric 
860fe6060f1SDimitry Andric   auto TargetTriple = STI.getTargetTriple();
861fe6060f1SDimitry Andric   auto Version = getIsaVersion(STI.getCPU());
862fe6060f1SDimitry Andric 
863fe6060f1SDimitry Andric   StreamRep << TargetTriple.getArchName() << '-'
8640b57cec5SDimitry Andric             << TargetTriple.getVendorName() << '-'
8650b57cec5SDimitry Andric             << TargetTriple.getOSName() << '-'
866fe6060f1SDimitry Andric             << TargetTriple.getEnvironmentName() << '-';
8670b57cec5SDimitry Andric 
86804eeddc0SDimitry Andric   std::string Processor;
869fe6060f1SDimitry Andric   // TODO: Following else statement is present here because we used various
870fe6060f1SDimitry Andric   // alias names for GPUs up until GFX9 (e.g. 'fiji' is same as 'gfx803').
871fe6060f1SDimitry Andric   // Remove once all aliases are removed from GCNProcessors.td.
872fe6060f1SDimitry Andric   if (Version.Major >= 9)
873fe6060f1SDimitry Andric     Processor = STI.getCPU().str();
874fe6060f1SDimitry Andric   else
875fe6060f1SDimitry Andric     Processor = (Twine("gfx") + Twine(Version.Major) + Twine(Version.Minor) +
876fe6060f1SDimitry Andric                  Twine(Version.Stepping))
877fe6060f1SDimitry Andric                     .str();
8780b57cec5SDimitry Andric 
87904eeddc0SDimitry Andric   std::string Features;
88006c3fb27SDimitry Andric   if (STI.getTargetTriple().getOS() == Triple::AMDHSA) {
881fe6060f1SDimitry Andric     // sramecc.
882fe6060f1SDimitry Andric     if (getSramEccSetting() == TargetIDSetting::Off)
883fe6060f1SDimitry Andric       Features += ":sramecc-";
884fe6060f1SDimitry Andric     else if (getSramEccSetting() == TargetIDSetting::On)
885fe6060f1SDimitry Andric       Features += ":sramecc+";
886fe6060f1SDimitry Andric     // xnack.
887fe6060f1SDimitry Andric     if (getXnackSetting() == TargetIDSetting::Off)
888fe6060f1SDimitry Andric       Features += ":xnack-";
889fe6060f1SDimitry Andric     else if (getXnackSetting() == TargetIDSetting::On)
890fe6060f1SDimitry Andric       Features += ":xnack+";
891fe6060f1SDimitry Andric   }
892fe6060f1SDimitry Andric 
893fe6060f1SDimitry Andric   StreamRep << Processor << Features;
894fe6060f1SDimitry Andric 
895fe6060f1SDimitry Andric   StreamRep.flush();
896fe6060f1SDimitry Andric   return StringRep;
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric 
getWavefrontSize(const MCSubtargetInfo * STI)8990b57cec5SDimitry Andric unsigned getWavefrontSize(const MCSubtargetInfo *STI) {
9000b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureWavefrontSize16))
9010b57cec5SDimitry Andric     return 16;
9020b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureWavefrontSize32))
9030b57cec5SDimitry Andric     return 32;
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric   return 64;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
getLocalMemorySize(const MCSubtargetInfo * STI)9080b57cec5SDimitry Andric unsigned getLocalMemorySize(const MCSubtargetInfo *STI) {
909bdd1243dSDimitry Andric   unsigned BytesPerCU = 0;
910bdd1243dSDimitry Andric   if (STI->getFeatureBits().test(FeatureLocalMemorySize32768))
911bdd1243dSDimitry Andric     BytesPerCU = 32768;
912bdd1243dSDimitry Andric   if (STI->getFeatureBits().test(FeatureLocalMemorySize65536))
913bdd1243dSDimitry Andric     BytesPerCU = 65536;
914bdd1243dSDimitry Andric 
915bdd1243dSDimitry Andric   // "Per CU" really means "per whatever functional block the waves of a
916bdd1243dSDimitry Andric   // workgroup must share". So the effective local memory size is doubled in
917bdd1243dSDimitry Andric   // WGP mode on gfx10.
918bdd1243dSDimitry Andric   if (isGFX10Plus(*STI) && !STI->getFeatureBits().test(FeatureCuMode))
919bdd1243dSDimitry Andric     BytesPerCU *= 2;
920bdd1243dSDimitry Andric 
921bdd1243dSDimitry Andric   return BytesPerCU;
922bdd1243dSDimitry Andric }
923bdd1243dSDimitry Andric 
getAddressableLocalMemorySize(const MCSubtargetInfo * STI)924bdd1243dSDimitry Andric unsigned getAddressableLocalMemorySize(const MCSubtargetInfo *STI) {
9250b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureLocalMemorySize32768))
9260b57cec5SDimitry Andric     return 32768;
9270b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureLocalMemorySize65536))
9280b57cec5SDimitry Andric     return 65536;
9290b57cec5SDimitry Andric   return 0;
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
getEUsPerCU(const MCSubtargetInfo * STI)9320b57cec5SDimitry Andric unsigned getEUsPerCU(const MCSubtargetInfo *STI) {
9335ffd83dbSDimitry Andric   // "Per CU" really means "per whatever functional block the waves of a
9345ffd83dbSDimitry Andric   // workgroup must share". For gfx10 in CU mode this is the CU, which contains
9355ffd83dbSDimitry Andric   // two SIMDs.
936e8d8bef9SDimitry Andric   if (isGFX10Plus(*STI) && STI->getFeatureBits().test(FeatureCuMode))
9375ffd83dbSDimitry Andric     return 2;
9385ffd83dbSDimitry Andric   // Pre-gfx10 a CU contains four SIMDs. For gfx10 in WGP mode the WGP contains
9395ffd83dbSDimitry Andric   // two CUs, so a total of four SIMDs.
9400b57cec5SDimitry Andric   return 4;
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric 
getMaxWorkGroupsPerCU(const MCSubtargetInfo * STI,unsigned FlatWorkGroupSize)9430b57cec5SDimitry Andric unsigned getMaxWorkGroupsPerCU(const MCSubtargetInfo *STI,
9440b57cec5SDimitry Andric                                unsigned FlatWorkGroupSize) {
9450b57cec5SDimitry Andric   assert(FlatWorkGroupSize != 0);
9460b57cec5SDimitry Andric   if (STI->getTargetTriple().getArch() != Triple::amdgcn)
9470b57cec5SDimitry Andric     return 8;
948bdd1243dSDimitry Andric   unsigned MaxWaves = getMaxWavesPerEU(STI) * getEUsPerCU(STI);
9490b57cec5SDimitry Andric   unsigned N = getWavesPerWorkGroup(STI, FlatWorkGroupSize);
950bdd1243dSDimitry Andric   if (N == 1) {
951bdd1243dSDimitry Andric     // Single-wave workgroups don't consume barrier resources.
952bdd1243dSDimitry Andric     return MaxWaves;
953bdd1243dSDimitry Andric   }
954bdd1243dSDimitry Andric 
955bdd1243dSDimitry Andric   unsigned MaxBarriers = 16;
956bdd1243dSDimitry Andric   if (isGFX10Plus(*STI) && !STI->getFeatureBits().test(FeatureCuMode))
957bdd1243dSDimitry Andric     MaxBarriers = 32;
958bdd1243dSDimitry Andric 
959bdd1243dSDimitry Andric   return std::min(MaxWaves / N, MaxBarriers);
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric 
getMinWavesPerEU(const MCSubtargetInfo * STI)9620b57cec5SDimitry Andric unsigned getMinWavesPerEU(const MCSubtargetInfo *STI) {
9630b57cec5SDimitry Andric   return 1;
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
getMaxWavesPerEU(const MCSubtargetInfo * STI)9668bcb0991SDimitry Andric unsigned getMaxWavesPerEU(const MCSubtargetInfo *STI) {
9670b57cec5SDimitry Andric   // FIXME: Need to take scratch memory into account.
968fe6060f1SDimitry Andric   if (isGFX90A(*STI))
969fe6060f1SDimitry Andric     return 8;
970e8d8bef9SDimitry Andric   if (!isGFX10Plus(*STI))
9710b57cec5SDimitry Andric     return 10;
9725ffd83dbSDimitry Andric   return hasGFX10_3Insts(*STI) ? 16 : 20;
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
getWavesPerEUForWorkGroup(const MCSubtargetInfo * STI,unsigned FlatWorkGroupSize)9755ffd83dbSDimitry Andric unsigned getWavesPerEUForWorkGroup(const MCSubtargetInfo *STI,
9760b57cec5SDimitry Andric                                    unsigned FlatWorkGroupSize) {
9775ffd83dbSDimitry Andric   return divideCeil(getWavesPerWorkGroup(STI, FlatWorkGroupSize),
9785ffd83dbSDimitry Andric                     getEUsPerCU(STI));
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
getMinFlatWorkGroupSize(const MCSubtargetInfo * STI)9810b57cec5SDimitry Andric unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo *STI) {
9820b57cec5SDimitry Andric   return 1;
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric 
getMaxFlatWorkGroupSize(const MCSubtargetInfo * STI)9850b57cec5SDimitry Andric unsigned getMaxFlatWorkGroupSize(const MCSubtargetInfo *STI) {
986480093f4SDimitry Andric   // Some subtargets allow encoding 2048, but this isn't tested or supported.
987480093f4SDimitry Andric   return 1024;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
getWavesPerWorkGroup(const MCSubtargetInfo * STI,unsigned FlatWorkGroupSize)9900b57cec5SDimitry Andric unsigned getWavesPerWorkGroup(const MCSubtargetInfo *STI,
9910b57cec5SDimitry Andric                               unsigned FlatWorkGroupSize) {
9925ffd83dbSDimitry Andric   return divideCeil(FlatWorkGroupSize, getWavefrontSize(STI));
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric 
getSGPRAllocGranule(const MCSubtargetInfo * STI)9950b57cec5SDimitry Andric unsigned getSGPRAllocGranule(const MCSubtargetInfo *STI) {
9960b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
9970b57cec5SDimitry Andric   if (Version.Major >= 10)
9980b57cec5SDimitry Andric     return getAddressableNumSGPRs(STI);
9990b57cec5SDimitry Andric   if (Version.Major >= 8)
10000b57cec5SDimitry Andric     return 16;
10010b57cec5SDimitry Andric   return 8;
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric 
getSGPREncodingGranule(const MCSubtargetInfo * STI)10040b57cec5SDimitry Andric unsigned getSGPREncodingGranule(const MCSubtargetInfo *STI) {
10050b57cec5SDimitry Andric   return 8;
10060b57cec5SDimitry Andric }
10070b57cec5SDimitry Andric 
getTotalNumSGPRs(const MCSubtargetInfo * STI)10080b57cec5SDimitry Andric unsigned getTotalNumSGPRs(const MCSubtargetInfo *STI) {
10090b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
10100b57cec5SDimitry Andric   if (Version.Major >= 8)
10110b57cec5SDimitry Andric     return 800;
10120b57cec5SDimitry Andric   return 512;
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
getAddressableNumSGPRs(const MCSubtargetInfo * STI)10150b57cec5SDimitry Andric unsigned getAddressableNumSGPRs(const MCSubtargetInfo *STI) {
10160b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureSGPRInitBug))
10170b57cec5SDimitry Andric     return FIXED_NUM_SGPRS_FOR_INIT_BUG;
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
10200b57cec5SDimitry Andric   if (Version.Major >= 10)
10210b57cec5SDimitry Andric     return 106;
10220b57cec5SDimitry Andric   if (Version.Major >= 8)
10230b57cec5SDimitry Andric     return 102;
10240b57cec5SDimitry Andric   return 104;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
getMinNumSGPRs(const MCSubtargetInfo * STI,unsigned WavesPerEU)10270b57cec5SDimitry Andric unsigned getMinNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU) {
10280b57cec5SDimitry Andric   assert(WavesPerEU != 0);
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
10310b57cec5SDimitry Andric   if (Version.Major >= 10)
10320b57cec5SDimitry Andric     return 0;
10330b57cec5SDimitry Andric 
10348bcb0991SDimitry Andric   if (WavesPerEU >= getMaxWavesPerEU(STI))
10350b57cec5SDimitry Andric     return 0;
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   unsigned MinNumSGPRs = getTotalNumSGPRs(STI) / (WavesPerEU + 1);
10380b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureTrapHandler))
10390b57cec5SDimitry Andric     MinNumSGPRs -= std::min(MinNumSGPRs, (unsigned)TRAP_NUM_SGPRS);
10400b57cec5SDimitry Andric   MinNumSGPRs = alignDown(MinNumSGPRs, getSGPRAllocGranule(STI)) + 1;
10410b57cec5SDimitry Andric   return std::min(MinNumSGPRs, getAddressableNumSGPRs(STI));
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric 
getMaxNumSGPRs(const MCSubtargetInfo * STI,unsigned WavesPerEU,bool Addressable)10440b57cec5SDimitry Andric unsigned getMaxNumSGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU,
10450b57cec5SDimitry Andric                         bool Addressable) {
10460b57cec5SDimitry Andric   assert(WavesPerEU != 0);
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric   unsigned AddressableNumSGPRs = getAddressableNumSGPRs(STI);
10490b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
10500b57cec5SDimitry Andric   if (Version.Major >= 10)
10510b57cec5SDimitry Andric     return Addressable ? AddressableNumSGPRs : 108;
10520b57cec5SDimitry Andric   if (Version.Major >= 8 && !Addressable)
10530b57cec5SDimitry Andric     AddressableNumSGPRs = 112;
10540b57cec5SDimitry Andric   unsigned MaxNumSGPRs = getTotalNumSGPRs(STI) / WavesPerEU;
10550b57cec5SDimitry Andric   if (STI->getFeatureBits().test(FeatureTrapHandler))
10560b57cec5SDimitry Andric     MaxNumSGPRs -= std::min(MaxNumSGPRs, (unsigned)TRAP_NUM_SGPRS);
10570b57cec5SDimitry Andric   MaxNumSGPRs = alignDown(MaxNumSGPRs, getSGPRAllocGranule(STI));
10580b57cec5SDimitry Andric   return std::min(MaxNumSGPRs, AddressableNumSGPRs);
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
getNumExtraSGPRs(const MCSubtargetInfo * STI,bool VCCUsed,bool FlatScrUsed,bool XNACKUsed)10610b57cec5SDimitry Andric unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed,
10620b57cec5SDimitry Andric                           bool FlatScrUsed, bool XNACKUsed) {
10630b57cec5SDimitry Andric   unsigned ExtraSGPRs = 0;
10640b57cec5SDimitry Andric   if (VCCUsed)
10650b57cec5SDimitry Andric     ExtraSGPRs = 2;
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
10680b57cec5SDimitry Andric   if (Version.Major >= 10)
10690b57cec5SDimitry Andric     return ExtraSGPRs;
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   if (Version.Major < 8) {
10720b57cec5SDimitry Andric     if (FlatScrUsed)
10730b57cec5SDimitry Andric       ExtraSGPRs = 4;
10740b57cec5SDimitry Andric   } else {
10750b57cec5SDimitry Andric     if (XNACKUsed)
10760b57cec5SDimitry Andric       ExtraSGPRs = 4;
10770b57cec5SDimitry Andric 
1078349cc55cSDimitry Andric     if (FlatScrUsed ||
1079349cc55cSDimitry Andric         STI->getFeatureBits().test(AMDGPU::FeatureArchitectedFlatScratch))
10800b57cec5SDimitry Andric       ExtraSGPRs = 6;
10810b57cec5SDimitry Andric   }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   return ExtraSGPRs;
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric 
getNumExtraSGPRs(const MCSubtargetInfo * STI,bool VCCUsed,bool FlatScrUsed)10860b57cec5SDimitry Andric unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed,
10870b57cec5SDimitry Andric                           bool FlatScrUsed) {
10880b57cec5SDimitry Andric   return getNumExtraSGPRs(STI, VCCUsed, FlatScrUsed,
10890b57cec5SDimitry Andric                           STI->getFeatureBits().test(AMDGPU::FeatureXNACK));
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
getGranulatedNumRegisterBlocks(unsigned NumRegs,unsigned Granule)1092*0fca6ea1SDimitry Andric static unsigned getGranulatedNumRegisterBlocks(unsigned NumRegs,
1093*0fca6ea1SDimitry Andric                                                unsigned Granule) {
1094*0fca6ea1SDimitry Andric   return divideCeil(std::max(1u, NumRegs), Granule);
1095*0fca6ea1SDimitry Andric }
1096*0fca6ea1SDimitry Andric 
getNumSGPRBlocks(const MCSubtargetInfo * STI,unsigned NumSGPRs)10970b57cec5SDimitry Andric unsigned getNumSGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs) {
10980b57cec5SDimitry Andric   // SGPRBlocks is actual number of SGPR blocks minus 1.
1099*0fca6ea1SDimitry Andric   return getGranulatedNumRegisterBlocks(NumSGPRs, getSGPREncodingGranule(STI)) -
1100*0fca6ea1SDimitry Andric          1;
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric 
getVGPRAllocGranule(const MCSubtargetInfo * STI,std::optional<bool> EnableWavefrontSize32)11030b57cec5SDimitry Andric unsigned getVGPRAllocGranule(const MCSubtargetInfo *STI,
1104bdd1243dSDimitry Andric                              std::optional<bool> EnableWavefrontSize32) {
1105fe6060f1SDimitry Andric   if (STI->getFeatureBits().test(FeatureGFX90AInsts))
1106fe6060f1SDimitry Andric     return 8;
1107fe6060f1SDimitry Andric 
11080b57cec5SDimitry Andric   bool IsWave32 = EnableWavefrontSize32 ?
11090b57cec5SDimitry Andric       *EnableWavefrontSize32 :
11100b57cec5SDimitry Andric       STI->getFeatureBits().test(FeatureWavefrontSize32);
11115ffd83dbSDimitry Andric 
1112*0fca6ea1SDimitry Andric   if (STI->getFeatureBits().test(Feature1_5xVGPRs))
1113bdd1243dSDimitry Andric     return IsWave32 ? 24 : 12;
1114bdd1243dSDimitry Andric 
11155ffd83dbSDimitry Andric   if (hasGFX10_3Insts(*STI))
11165ffd83dbSDimitry Andric     return IsWave32 ? 16 : 8;
11175ffd83dbSDimitry Andric 
11180b57cec5SDimitry Andric   return IsWave32 ? 8 : 4;
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
getVGPREncodingGranule(const MCSubtargetInfo * STI,std::optional<bool> EnableWavefrontSize32)11210b57cec5SDimitry Andric unsigned getVGPREncodingGranule(const MCSubtargetInfo *STI,
1122bdd1243dSDimitry Andric                                 std::optional<bool> EnableWavefrontSize32) {
1123fe6060f1SDimitry Andric   if (STI->getFeatureBits().test(FeatureGFX90AInsts))
1124fe6060f1SDimitry Andric     return 8;
11255ffd83dbSDimitry Andric 
11265ffd83dbSDimitry Andric   bool IsWave32 = EnableWavefrontSize32 ?
11275ffd83dbSDimitry Andric       *EnableWavefrontSize32 :
11285ffd83dbSDimitry Andric       STI->getFeatureBits().test(FeatureWavefrontSize32);
11295ffd83dbSDimitry Andric 
11305ffd83dbSDimitry Andric   return IsWave32 ? 8 : 4;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
getTotalNumVGPRs(const MCSubtargetInfo * STI)11330b57cec5SDimitry Andric unsigned getTotalNumVGPRs(const MCSubtargetInfo *STI) {
1134fe6060f1SDimitry Andric   if (STI->getFeatureBits().test(FeatureGFX90AInsts))
1135fe6060f1SDimitry Andric     return 512;
1136e8d8bef9SDimitry Andric   if (!isGFX10Plus(*STI))
11370b57cec5SDimitry Andric     return 256;
1138bdd1243dSDimitry Andric   bool IsWave32 = STI->getFeatureBits().test(FeatureWavefrontSize32);
1139*0fca6ea1SDimitry Andric   if (STI->getFeatureBits().test(Feature1_5xVGPRs))
1140bdd1243dSDimitry Andric     return IsWave32 ? 1536 : 768;
1141bdd1243dSDimitry Andric   return IsWave32 ? 1024 : 512;
11420b57cec5SDimitry Andric }
11430b57cec5SDimitry Andric 
getAddressableNumArchVGPRs(const MCSubtargetInfo * STI)1144*0fca6ea1SDimitry Andric unsigned getAddressableNumArchVGPRs(const MCSubtargetInfo *STI) { return 256; }
1145*0fca6ea1SDimitry Andric 
getAddressableNumVGPRs(const MCSubtargetInfo * STI)11460b57cec5SDimitry Andric unsigned getAddressableNumVGPRs(const MCSubtargetInfo *STI) {
1147fe6060f1SDimitry Andric   if (STI->getFeatureBits().test(FeatureGFX90AInsts))
1148fe6060f1SDimitry Andric     return 512;
1149*0fca6ea1SDimitry Andric   return getAddressableNumArchVGPRs(STI);
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric 
getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo * STI,unsigned NumVGPRs)1152bdd1243dSDimitry Andric unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo *STI,
1153bdd1243dSDimitry Andric                                       unsigned NumVGPRs) {
1154*0fca6ea1SDimitry Andric   return getNumWavesPerEUWithNumVGPRs(NumVGPRs, getVGPRAllocGranule(STI),
1155*0fca6ea1SDimitry Andric                                       getMaxWavesPerEU(STI),
1156*0fca6ea1SDimitry Andric                                       getTotalNumVGPRs(STI));
1157*0fca6ea1SDimitry Andric }
1158*0fca6ea1SDimitry Andric 
getNumWavesPerEUWithNumVGPRs(unsigned NumVGPRs,unsigned Granule,unsigned MaxWaves,unsigned TotalNumVGPRs)1159*0fca6ea1SDimitry Andric unsigned getNumWavesPerEUWithNumVGPRs(unsigned NumVGPRs, unsigned Granule,
1160*0fca6ea1SDimitry Andric                                       unsigned MaxWaves,
1161*0fca6ea1SDimitry Andric                                       unsigned TotalNumVGPRs) {
1162bdd1243dSDimitry Andric   if (NumVGPRs < Granule)
1163bdd1243dSDimitry Andric     return MaxWaves;
1164bdd1243dSDimitry Andric   unsigned RoundedRegs = alignTo(NumVGPRs, Granule);
1165*0fca6ea1SDimitry Andric   return std::min(std::max(TotalNumVGPRs / RoundedRegs, 1u), MaxWaves);
1166*0fca6ea1SDimitry Andric }
1167*0fca6ea1SDimitry Andric 
getOccupancyWithNumSGPRs(unsigned SGPRs,unsigned MaxWaves,AMDGPUSubtarget::Generation Gen)1168*0fca6ea1SDimitry Andric unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves,
1169*0fca6ea1SDimitry Andric                                   AMDGPUSubtarget::Generation Gen) {
1170*0fca6ea1SDimitry Andric   if (Gen >= AMDGPUSubtarget::GFX10)
1171*0fca6ea1SDimitry Andric     return MaxWaves;
1172*0fca6ea1SDimitry Andric 
1173*0fca6ea1SDimitry Andric   if (Gen >= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
1174*0fca6ea1SDimitry Andric     if (SGPRs <= 80)
1175*0fca6ea1SDimitry Andric       return 10;
1176*0fca6ea1SDimitry Andric     if (SGPRs <= 88)
1177*0fca6ea1SDimitry Andric       return 9;
1178*0fca6ea1SDimitry Andric     if (SGPRs <= 100)
1179*0fca6ea1SDimitry Andric       return 8;
1180*0fca6ea1SDimitry Andric     return 7;
1181*0fca6ea1SDimitry Andric   }
1182*0fca6ea1SDimitry Andric   if (SGPRs <= 48)
1183*0fca6ea1SDimitry Andric     return 10;
1184*0fca6ea1SDimitry Andric   if (SGPRs <= 56)
1185*0fca6ea1SDimitry Andric     return 9;
1186*0fca6ea1SDimitry Andric   if (SGPRs <= 64)
1187*0fca6ea1SDimitry Andric     return 8;
1188*0fca6ea1SDimitry Andric   if (SGPRs <= 72)
1189*0fca6ea1SDimitry Andric     return 7;
1190*0fca6ea1SDimitry Andric   if (SGPRs <= 80)
1191*0fca6ea1SDimitry Andric     return 6;
1192*0fca6ea1SDimitry Andric   return 5;
1193bdd1243dSDimitry Andric }
1194bdd1243dSDimitry Andric 
getMinNumVGPRs(const MCSubtargetInfo * STI,unsigned WavesPerEU)11950b57cec5SDimitry Andric unsigned getMinNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU) {
11960b57cec5SDimitry Andric   assert(WavesPerEU != 0);
11970b57cec5SDimitry Andric 
1198bdd1243dSDimitry Andric   unsigned MaxWavesPerEU = getMaxWavesPerEU(STI);
1199bdd1243dSDimitry Andric   if (WavesPerEU >= MaxWavesPerEU)
12000b57cec5SDimitry Andric     return 0;
1201bdd1243dSDimitry Andric 
1202bdd1243dSDimitry Andric   unsigned TotNumVGPRs = getTotalNumVGPRs(STI);
1203bdd1243dSDimitry Andric   unsigned AddrsableNumVGPRs = getAddressableNumVGPRs(STI);
1204bdd1243dSDimitry Andric   unsigned Granule = getVGPRAllocGranule(STI);
1205bdd1243dSDimitry Andric   unsigned MaxNumVGPRs = alignDown(TotNumVGPRs / WavesPerEU, Granule);
1206bdd1243dSDimitry Andric 
1207bdd1243dSDimitry Andric   if (MaxNumVGPRs == alignDown(TotNumVGPRs / MaxWavesPerEU, Granule))
1208bdd1243dSDimitry Andric     return 0;
1209bdd1243dSDimitry Andric 
1210bdd1243dSDimitry Andric   unsigned MinWavesPerEU = getNumWavesPerEUWithNumVGPRs(STI, AddrsableNumVGPRs);
1211bdd1243dSDimitry Andric   if (WavesPerEU < MinWavesPerEU)
1212bdd1243dSDimitry Andric     return getMinNumVGPRs(STI, MinWavesPerEU);
1213bdd1243dSDimitry Andric 
1214bdd1243dSDimitry Andric   unsigned MaxNumVGPRsNext = alignDown(TotNumVGPRs / (WavesPerEU + 1), Granule);
1215bdd1243dSDimitry Andric   unsigned MinNumVGPRs = 1 + std::min(MaxNumVGPRs - Granule, MaxNumVGPRsNext);
1216bdd1243dSDimitry Andric   return std::min(MinNumVGPRs, AddrsableNumVGPRs);
12170b57cec5SDimitry Andric }
12180b57cec5SDimitry Andric 
getMaxNumVGPRs(const MCSubtargetInfo * STI,unsigned WavesPerEU)12190b57cec5SDimitry Andric unsigned getMaxNumVGPRs(const MCSubtargetInfo *STI, unsigned WavesPerEU) {
12200b57cec5SDimitry Andric   assert(WavesPerEU != 0);
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   unsigned MaxNumVGPRs = alignDown(getTotalNumVGPRs(STI) / WavesPerEU,
12230b57cec5SDimitry Andric                                    getVGPRAllocGranule(STI));
12240b57cec5SDimitry Andric   unsigned AddressableNumVGPRs = getAddressableNumVGPRs(STI);
12250b57cec5SDimitry Andric   return std::min(MaxNumVGPRs, AddressableNumVGPRs);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
getEncodedNumVGPRBlocks(const MCSubtargetInfo * STI,unsigned NumVGPRs,std::optional<bool> EnableWavefrontSize32)1228*0fca6ea1SDimitry Andric unsigned getEncodedNumVGPRBlocks(const MCSubtargetInfo *STI, unsigned NumVGPRs,
1229bdd1243dSDimitry Andric                                  std::optional<bool> EnableWavefrontSize32) {
1230*0fca6ea1SDimitry Andric   return getGranulatedNumRegisterBlocks(
1231*0fca6ea1SDimitry Andric              NumVGPRs, getVGPREncodingGranule(STI, EnableWavefrontSize32)) -
1232*0fca6ea1SDimitry Andric          1;
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
getAllocatedNumVGPRBlocks(const MCSubtargetInfo * STI,unsigned NumVGPRs,std::optional<bool> EnableWavefrontSize32)1235*0fca6ea1SDimitry Andric unsigned getAllocatedNumVGPRBlocks(const MCSubtargetInfo *STI,
1236*0fca6ea1SDimitry Andric                                    unsigned NumVGPRs,
1237*0fca6ea1SDimitry Andric                                    std::optional<bool> EnableWavefrontSize32) {
1238*0fca6ea1SDimitry Andric   return getGranulatedNumRegisterBlocks(
1239*0fca6ea1SDimitry Andric       NumVGPRs, getVGPRAllocGranule(STI, EnableWavefrontSize32));
1240*0fca6ea1SDimitry Andric }
12410b57cec5SDimitry Andric } // end namespace IsaInfo
12420b57cec5SDimitry Andric 
initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT & KernelCode,const MCSubtargetInfo * STI)1243*0fca6ea1SDimitry Andric void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &KernelCode,
12440b57cec5SDimitry Andric                                const MCSubtargetInfo *STI) {
12450b57cec5SDimitry Andric   IsaVersion Version = getIsaVersion(STI->getCPU());
1246*0fca6ea1SDimitry Andric   KernelCode.amd_kernel_code_version_major = 1;
1247*0fca6ea1SDimitry Andric   KernelCode.amd_kernel_code_version_minor = 2;
1248*0fca6ea1SDimitry Andric   KernelCode.amd_machine_kind = 1; // AMD_MACHINE_KIND_AMDGPU
1249*0fca6ea1SDimitry Andric   KernelCode.amd_machine_version_major = Version.Major;
1250*0fca6ea1SDimitry Andric   KernelCode.amd_machine_version_minor = Version.Minor;
1251*0fca6ea1SDimitry Andric   KernelCode.amd_machine_version_stepping = Version.Stepping;
1252*0fca6ea1SDimitry Andric   KernelCode.kernel_code_entry_byte_offset = sizeof(amd_kernel_code_t);
1253*0fca6ea1SDimitry Andric   if (STI->getFeatureBits().test(FeatureWavefrontSize32)) {
1254*0fca6ea1SDimitry Andric     KernelCode.wavefront_size = 5;
1255*0fca6ea1SDimitry Andric     KernelCode.code_properties |= AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
1256*0fca6ea1SDimitry Andric   } else {
1257*0fca6ea1SDimitry Andric     KernelCode.wavefront_size = 6;
1258*0fca6ea1SDimitry Andric   }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   // If the code object does not support indirect functions, then the value must
12610b57cec5SDimitry Andric   // be 0xffffffff.
1262*0fca6ea1SDimitry Andric   KernelCode.call_convention = -1;
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   // These alignment values are specified in powers of two, so alignment =
12650b57cec5SDimitry Andric   // 2^n.  The minimum alignment is 2^4 = 16.
1266*0fca6ea1SDimitry Andric   KernelCode.kernarg_segment_alignment = 4;
1267*0fca6ea1SDimitry Andric   KernelCode.group_segment_alignment = 4;
1268*0fca6ea1SDimitry Andric   KernelCode.private_segment_alignment = 4;
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric   if (Version.Major >= 10) {
1271*0fca6ea1SDimitry Andric     KernelCode.compute_pgm_resource_registers |=
12720b57cec5SDimitry Andric         S_00B848_WGP_MODE(STI->getFeatureBits().test(FeatureCuMode) ? 0 : 1) |
12730b57cec5SDimitry Andric         S_00B848_MEM_ORDERED(1);
12740b57cec5SDimitry Andric   }
12750b57cec5SDimitry Andric }
12760b57cec5SDimitry Andric 
isGroupSegment(const GlobalValue * GV)12770b57cec5SDimitry Andric bool isGroupSegment(const GlobalValue *GV) {
1278480093f4SDimitry Andric   return GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS;
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
isGlobalSegment(const GlobalValue * GV)12810b57cec5SDimitry Andric bool isGlobalSegment(const GlobalValue *GV) {
1282480093f4SDimitry Andric   return GV->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS;
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric 
isReadOnlySegment(const GlobalValue * GV)12850b57cec5SDimitry Andric bool isReadOnlySegment(const GlobalValue *GV) {
1286480093f4SDimitry Andric   unsigned AS = GV->getAddressSpace();
1287480093f4SDimitry Andric   return AS == AMDGPUAS::CONSTANT_ADDRESS ||
1288480093f4SDimitry Andric          AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT;
12890b57cec5SDimitry Andric }
12900b57cec5SDimitry Andric 
shouldEmitConstantsToTextSection(const Triple & TT)12910b57cec5SDimitry Andric bool shouldEmitConstantsToTextSection(const Triple &TT) {
1292e8d8bef9SDimitry Andric   return TT.getArch() == Triple::r600;
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
129506c3fb27SDimitry Andric std::pair<unsigned, unsigned>
getIntegerPairAttribute(const Function & F,StringRef Name,std::pair<unsigned,unsigned> Default,bool OnlyFirstRequired)129606c3fb27SDimitry Andric getIntegerPairAttribute(const Function &F, StringRef Name,
129706c3fb27SDimitry Andric                         std::pair<unsigned, unsigned> Default,
12980b57cec5SDimitry Andric                         bool OnlyFirstRequired) {
12990b57cec5SDimitry Andric   Attribute A = F.getFnAttribute(Name);
13000b57cec5SDimitry Andric   if (!A.isStringAttribute())
13010b57cec5SDimitry Andric     return Default;
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric   LLVMContext &Ctx = F.getContext();
130406c3fb27SDimitry Andric   std::pair<unsigned, unsigned> Ints = Default;
13050b57cec5SDimitry Andric   std::pair<StringRef, StringRef> Strs = A.getValueAsString().split(',');
13060b57cec5SDimitry Andric   if (Strs.first.trim().getAsInteger(0, Ints.first)) {
13070b57cec5SDimitry Andric     Ctx.emitError("can't parse first integer attribute " + Name);
13080b57cec5SDimitry Andric     return Default;
13090b57cec5SDimitry Andric   }
13100b57cec5SDimitry Andric   if (Strs.second.trim().getAsInteger(0, Ints.second)) {
13110b57cec5SDimitry Andric     if (!OnlyFirstRequired || !Strs.second.trim().empty()) {
13120b57cec5SDimitry Andric       Ctx.emitError("can't parse second integer attribute " + Name);
13130b57cec5SDimitry Andric       return Default;
13140b57cec5SDimitry Andric     }
13150b57cec5SDimitry Andric   }
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric   return Ints;
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric 
getIntegerVecAttribute(const Function & F,StringRef Name,unsigned Size)1320*0fca6ea1SDimitry Andric SmallVector<unsigned> getIntegerVecAttribute(const Function &F, StringRef Name,
1321*0fca6ea1SDimitry Andric                                              unsigned Size) {
1322*0fca6ea1SDimitry Andric   assert(Size > 2);
1323*0fca6ea1SDimitry Andric   SmallVector<unsigned> Default(Size, 0);
1324*0fca6ea1SDimitry Andric 
1325*0fca6ea1SDimitry Andric   Attribute A = F.getFnAttribute(Name);
1326*0fca6ea1SDimitry Andric   if (!A.isStringAttribute())
1327*0fca6ea1SDimitry Andric     return Default;
1328*0fca6ea1SDimitry Andric 
1329*0fca6ea1SDimitry Andric   SmallVector<unsigned> Vals(Size, 0);
1330*0fca6ea1SDimitry Andric 
1331*0fca6ea1SDimitry Andric   LLVMContext &Ctx = F.getContext();
1332*0fca6ea1SDimitry Andric 
1333*0fca6ea1SDimitry Andric   StringRef S = A.getValueAsString();
1334*0fca6ea1SDimitry Andric   unsigned i = 0;
1335*0fca6ea1SDimitry Andric   for (; !S.empty() && i < Size; i++) {
1336*0fca6ea1SDimitry Andric     std::pair<StringRef, StringRef> Strs = S.split(',');
1337*0fca6ea1SDimitry Andric     unsigned IntVal;
1338*0fca6ea1SDimitry Andric     if (Strs.first.trim().getAsInteger(0, IntVal)) {
1339*0fca6ea1SDimitry Andric       Ctx.emitError("can't parse integer attribute " + Strs.first + " in " +
1340*0fca6ea1SDimitry Andric                     Name);
1341*0fca6ea1SDimitry Andric       return Default;
1342*0fca6ea1SDimitry Andric     }
1343*0fca6ea1SDimitry Andric     Vals[i] = IntVal;
1344*0fca6ea1SDimitry Andric     S = Strs.second;
1345*0fca6ea1SDimitry Andric   }
1346*0fca6ea1SDimitry Andric 
1347*0fca6ea1SDimitry Andric   if (!S.empty() || i < Size) {
1348*0fca6ea1SDimitry Andric     Ctx.emitError("attribute " + Name +
1349*0fca6ea1SDimitry Andric                   " has incorrect number of integers; expected " +
1350*0fca6ea1SDimitry Andric                   llvm::utostr(Size));
1351*0fca6ea1SDimitry Andric     return Default;
1352*0fca6ea1SDimitry Andric   }
1353*0fca6ea1SDimitry Andric   return Vals;
1354*0fca6ea1SDimitry Andric }
1355*0fca6ea1SDimitry Andric 
getVmcntBitMask(const IsaVersion & Version)13560b57cec5SDimitry Andric unsigned getVmcntBitMask(const IsaVersion &Version) {
135781ad6265SDimitry Andric   return (1 << (getVmcntBitWidthLo(Version.Major) +
135881ad6265SDimitry Andric                 getVmcntBitWidthHi(Version.Major))) -
135981ad6265SDimitry Andric          1;
13600b57cec5SDimitry Andric }
13610b57cec5SDimitry Andric 
getLoadcntBitMask(const IsaVersion & Version)13627a6dacacSDimitry Andric unsigned getLoadcntBitMask(const IsaVersion &Version) {
13637a6dacacSDimitry Andric   return (1 << getLoadcntBitWidth(Version.Major)) - 1;
13647a6dacacSDimitry Andric }
13657a6dacacSDimitry Andric 
getSamplecntBitMask(const IsaVersion & Version)13667a6dacacSDimitry Andric unsigned getSamplecntBitMask(const IsaVersion &Version) {
13677a6dacacSDimitry Andric   return (1 << getSamplecntBitWidth(Version.Major)) - 1;
13687a6dacacSDimitry Andric }
13697a6dacacSDimitry Andric 
getBvhcntBitMask(const IsaVersion & Version)13707a6dacacSDimitry Andric unsigned getBvhcntBitMask(const IsaVersion &Version) {
13717a6dacacSDimitry Andric   return (1 << getBvhcntBitWidth(Version.Major)) - 1;
13727a6dacacSDimitry Andric }
13737a6dacacSDimitry Andric 
getExpcntBitMask(const IsaVersion & Version)13740b57cec5SDimitry Andric unsigned getExpcntBitMask(const IsaVersion &Version) {
137581ad6265SDimitry Andric   return (1 << getExpcntBitWidth(Version.Major)) - 1;
13760b57cec5SDimitry Andric }
13770b57cec5SDimitry Andric 
getLgkmcntBitMask(const IsaVersion & Version)13780b57cec5SDimitry Andric unsigned getLgkmcntBitMask(const IsaVersion &Version) {
13790b57cec5SDimitry Andric   return (1 << getLgkmcntBitWidth(Version.Major)) - 1;
13800b57cec5SDimitry Andric }
13810b57cec5SDimitry Andric 
getDscntBitMask(const IsaVersion & Version)13827a6dacacSDimitry Andric unsigned getDscntBitMask(const IsaVersion &Version) {
13837a6dacacSDimitry Andric   return (1 << getDscntBitWidth(Version.Major)) - 1;
13847a6dacacSDimitry Andric }
13857a6dacacSDimitry Andric 
getKmcntBitMask(const IsaVersion & Version)13867a6dacacSDimitry Andric unsigned getKmcntBitMask(const IsaVersion &Version) {
13877a6dacacSDimitry Andric   return (1 << getKmcntBitWidth(Version.Major)) - 1;
13887a6dacacSDimitry Andric }
13897a6dacacSDimitry Andric 
getStorecntBitMask(const IsaVersion & Version)13907a6dacacSDimitry Andric unsigned getStorecntBitMask(const IsaVersion &Version) {
13917a6dacacSDimitry Andric   return (1 << getStorecntBitWidth(Version.Major)) - 1;
13927a6dacacSDimitry Andric }
13937a6dacacSDimitry Andric 
getWaitcntBitMask(const IsaVersion & Version)13940b57cec5SDimitry Andric unsigned getWaitcntBitMask(const IsaVersion &Version) {
139581ad6265SDimitry Andric   unsigned VmcntLo = getBitMask(getVmcntBitShiftLo(Version.Major),
139681ad6265SDimitry Andric                                 getVmcntBitWidthLo(Version.Major));
139781ad6265SDimitry Andric   unsigned Expcnt = getBitMask(getExpcntBitShift(Version.Major),
139881ad6265SDimitry Andric                                getExpcntBitWidth(Version.Major));
139981ad6265SDimitry Andric   unsigned Lgkmcnt = getBitMask(getLgkmcntBitShift(Version.Major),
14000b57cec5SDimitry Andric                                 getLgkmcntBitWidth(Version.Major));
140181ad6265SDimitry Andric   unsigned VmcntHi = getBitMask(getVmcntBitShiftHi(Version.Major),
140281ad6265SDimitry Andric                                 getVmcntBitWidthHi(Version.Major));
140381ad6265SDimitry Andric   return VmcntLo | Expcnt | Lgkmcnt | VmcntHi;
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric 
decodeVmcnt(const IsaVersion & Version,unsigned Waitcnt)14060b57cec5SDimitry Andric unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt) {
140781ad6265SDimitry Andric   unsigned VmcntLo = unpackBits(Waitcnt, getVmcntBitShiftLo(Version.Major),
140881ad6265SDimitry Andric                                 getVmcntBitWidthLo(Version.Major));
140981ad6265SDimitry Andric   unsigned VmcntHi = unpackBits(Waitcnt, getVmcntBitShiftHi(Version.Major),
141081ad6265SDimitry Andric                                 getVmcntBitWidthHi(Version.Major));
141181ad6265SDimitry Andric   return VmcntLo | VmcntHi << getVmcntBitWidthLo(Version.Major);
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
decodeExpcnt(const IsaVersion & Version,unsigned Waitcnt)14140b57cec5SDimitry Andric unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt) {
141581ad6265SDimitry Andric   return unpackBits(Waitcnt, getExpcntBitShift(Version.Major),
141681ad6265SDimitry Andric                     getExpcntBitWidth(Version.Major));
14170b57cec5SDimitry Andric }
14180b57cec5SDimitry Andric 
decodeLgkmcnt(const IsaVersion & Version,unsigned Waitcnt)14190b57cec5SDimitry Andric unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt) {
142081ad6265SDimitry Andric   return unpackBits(Waitcnt, getLgkmcntBitShift(Version.Major),
14210b57cec5SDimitry Andric                     getLgkmcntBitWidth(Version.Major));
14220b57cec5SDimitry Andric }
14230b57cec5SDimitry Andric 
decodeWaitcnt(const IsaVersion & Version,unsigned Waitcnt,unsigned & Vmcnt,unsigned & Expcnt,unsigned & Lgkmcnt)14240b57cec5SDimitry Andric void decodeWaitcnt(const IsaVersion &Version, unsigned Waitcnt,
14250b57cec5SDimitry Andric                    unsigned &Vmcnt, unsigned &Expcnt, unsigned &Lgkmcnt) {
14260b57cec5SDimitry Andric   Vmcnt = decodeVmcnt(Version, Waitcnt);
14270b57cec5SDimitry Andric   Expcnt = decodeExpcnt(Version, Waitcnt);
14280b57cec5SDimitry Andric   Lgkmcnt = decodeLgkmcnt(Version, Waitcnt);
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric 
decodeWaitcnt(const IsaVersion & Version,unsigned Encoded)14310b57cec5SDimitry Andric Waitcnt decodeWaitcnt(const IsaVersion &Version, unsigned Encoded) {
14320b57cec5SDimitry Andric   Waitcnt Decoded;
14337a6dacacSDimitry Andric   Decoded.LoadCnt = decodeVmcnt(Version, Encoded);
14340b57cec5SDimitry Andric   Decoded.ExpCnt = decodeExpcnt(Version, Encoded);
14357a6dacacSDimitry Andric   Decoded.DsCnt = decodeLgkmcnt(Version, Encoded);
14360b57cec5SDimitry Andric   return Decoded;
14370b57cec5SDimitry Andric }
14380b57cec5SDimitry Andric 
encodeVmcnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Vmcnt)14390b57cec5SDimitry Andric unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt,
14400b57cec5SDimitry Andric                      unsigned Vmcnt) {
144181ad6265SDimitry Andric   Waitcnt = packBits(Vmcnt, Waitcnt, getVmcntBitShiftLo(Version.Major),
144281ad6265SDimitry Andric                      getVmcntBitWidthLo(Version.Major));
144381ad6265SDimitry Andric   return packBits(Vmcnt >> getVmcntBitWidthLo(Version.Major), Waitcnt,
144481ad6265SDimitry Andric                   getVmcntBitShiftHi(Version.Major),
144581ad6265SDimitry Andric                   getVmcntBitWidthHi(Version.Major));
14460b57cec5SDimitry Andric }
14470b57cec5SDimitry Andric 
encodeExpcnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Expcnt)14480b57cec5SDimitry Andric unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt,
14490b57cec5SDimitry Andric                       unsigned Expcnt) {
145081ad6265SDimitry Andric   return packBits(Expcnt, Waitcnt, getExpcntBitShift(Version.Major),
145181ad6265SDimitry Andric                   getExpcntBitWidth(Version.Major));
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric 
encodeLgkmcnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Lgkmcnt)14540b57cec5SDimitry Andric unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt,
14550b57cec5SDimitry Andric                        unsigned Lgkmcnt) {
145681ad6265SDimitry Andric   return packBits(Lgkmcnt, Waitcnt, getLgkmcntBitShift(Version.Major),
14570b57cec5SDimitry Andric                   getLgkmcntBitWidth(Version.Major));
14580b57cec5SDimitry Andric }
14590b57cec5SDimitry Andric 
encodeWaitcnt(const IsaVersion & Version,unsigned Vmcnt,unsigned Expcnt,unsigned Lgkmcnt)14600b57cec5SDimitry Andric unsigned encodeWaitcnt(const IsaVersion &Version,
14610b57cec5SDimitry Andric                        unsigned Vmcnt, unsigned Expcnt, unsigned Lgkmcnt) {
14620b57cec5SDimitry Andric   unsigned Waitcnt = getWaitcntBitMask(Version);
14630b57cec5SDimitry Andric   Waitcnt = encodeVmcnt(Version, Waitcnt, Vmcnt);
14640b57cec5SDimitry Andric   Waitcnt = encodeExpcnt(Version, Waitcnt, Expcnt);
14650b57cec5SDimitry Andric   Waitcnt = encodeLgkmcnt(Version, Waitcnt, Lgkmcnt);
14660b57cec5SDimitry Andric   return Waitcnt;
14670b57cec5SDimitry Andric }
14680b57cec5SDimitry Andric 
encodeWaitcnt(const IsaVersion & Version,const Waitcnt & Decoded)14690b57cec5SDimitry Andric unsigned encodeWaitcnt(const IsaVersion &Version, const Waitcnt &Decoded) {
14707a6dacacSDimitry Andric   return encodeWaitcnt(Version, Decoded.LoadCnt, Decoded.ExpCnt, Decoded.DsCnt);
14717a6dacacSDimitry Andric }
14727a6dacacSDimitry Andric 
getCombinedCountBitMask(const IsaVersion & Version,bool IsStore)14737a6dacacSDimitry Andric static unsigned getCombinedCountBitMask(const IsaVersion &Version,
14747a6dacacSDimitry Andric                                         bool IsStore) {
14757a6dacacSDimitry Andric   unsigned Dscnt = getBitMask(getDscntBitShift(Version.Major),
14767a6dacacSDimitry Andric                               getDscntBitWidth(Version.Major));
14777a6dacacSDimitry Andric   if (IsStore) {
14787a6dacacSDimitry Andric     unsigned Storecnt = getBitMask(getLoadcntStorecntBitShift(Version.Major),
14797a6dacacSDimitry Andric                                    getStorecntBitWidth(Version.Major));
14807a6dacacSDimitry Andric     return Dscnt | Storecnt;
1481*0fca6ea1SDimitry Andric   }
14827a6dacacSDimitry Andric   unsigned Loadcnt = getBitMask(getLoadcntStorecntBitShift(Version.Major),
14837a6dacacSDimitry Andric                                 getLoadcntBitWidth(Version.Major));
14847a6dacacSDimitry Andric   return Dscnt | Loadcnt;
14857a6dacacSDimitry Andric }
14867a6dacacSDimitry Andric 
decodeLoadcntDscnt(const IsaVersion & Version,unsigned LoadcntDscnt)14877a6dacacSDimitry Andric Waitcnt decodeLoadcntDscnt(const IsaVersion &Version, unsigned LoadcntDscnt) {
14887a6dacacSDimitry Andric   Waitcnt Decoded;
14897a6dacacSDimitry Andric   Decoded.LoadCnt =
14907a6dacacSDimitry Andric       unpackBits(LoadcntDscnt, getLoadcntStorecntBitShift(Version.Major),
14917a6dacacSDimitry Andric                  getLoadcntBitWidth(Version.Major));
14927a6dacacSDimitry Andric   Decoded.DsCnt = unpackBits(LoadcntDscnt, getDscntBitShift(Version.Major),
14937a6dacacSDimitry Andric                              getDscntBitWidth(Version.Major));
14947a6dacacSDimitry Andric   return Decoded;
14957a6dacacSDimitry Andric }
14967a6dacacSDimitry Andric 
decodeStorecntDscnt(const IsaVersion & Version,unsigned StorecntDscnt)14977a6dacacSDimitry Andric Waitcnt decodeStorecntDscnt(const IsaVersion &Version, unsigned StorecntDscnt) {
14987a6dacacSDimitry Andric   Waitcnt Decoded;
14997a6dacacSDimitry Andric   Decoded.StoreCnt =
15007a6dacacSDimitry Andric       unpackBits(StorecntDscnt, getLoadcntStorecntBitShift(Version.Major),
15017a6dacacSDimitry Andric                  getStorecntBitWidth(Version.Major));
15027a6dacacSDimitry Andric   Decoded.DsCnt = unpackBits(StorecntDscnt, getDscntBitShift(Version.Major),
15037a6dacacSDimitry Andric                              getDscntBitWidth(Version.Major));
15047a6dacacSDimitry Andric   return Decoded;
15057a6dacacSDimitry Andric }
15067a6dacacSDimitry Andric 
encodeLoadcnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Loadcnt)15077a6dacacSDimitry Andric static unsigned encodeLoadcnt(const IsaVersion &Version, unsigned Waitcnt,
15087a6dacacSDimitry Andric                               unsigned Loadcnt) {
15097a6dacacSDimitry Andric   return packBits(Loadcnt, Waitcnt, getLoadcntStorecntBitShift(Version.Major),
15107a6dacacSDimitry Andric                   getLoadcntBitWidth(Version.Major));
15117a6dacacSDimitry Andric }
15127a6dacacSDimitry Andric 
encodeStorecnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Storecnt)15137a6dacacSDimitry Andric static unsigned encodeStorecnt(const IsaVersion &Version, unsigned Waitcnt,
15147a6dacacSDimitry Andric                                unsigned Storecnt) {
15157a6dacacSDimitry Andric   return packBits(Storecnt, Waitcnt, getLoadcntStorecntBitShift(Version.Major),
15167a6dacacSDimitry Andric                   getStorecntBitWidth(Version.Major));
15177a6dacacSDimitry Andric }
15187a6dacacSDimitry Andric 
encodeDscnt(const IsaVersion & Version,unsigned Waitcnt,unsigned Dscnt)15197a6dacacSDimitry Andric static unsigned encodeDscnt(const IsaVersion &Version, unsigned Waitcnt,
15207a6dacacSDimitry Andric                             unsigned Dscnt) {
15217a6dacacSDimitry Andric   return packBits(Dscnt, Waitcnt, getDscntBitShift(Version.Major),
15227a6dacacSDimitry Andric                   getDscntBitWidth(Version.Major));
15237a6dacacSDimitry Andric }
15247a6dacacSDimitry Andric 
encodeLoadcntDscnt(const IsaVersion & Version,unsigned Loadcnt,unsigned Dscnt)15257a6dacacSDimitry Andric static unsigned encodeLoadcntDscnt(const IsaVersion &Version, unsigned Loadcnt,
15267a6dacacSDimitry Andric                                    unsigned Dscnt) {
15277a6dacacSDimitry Andric   unsigned Waitcnt = getCombinedCountBitMask(Version, false);
15287a6dacacSDimitry Andric   Waitcnt = encodeLoadcnt(Version, Waitcnt, Loadcnt);
15297a6dacacSDimitry Andric   Waitcnt = encodeDscnt(Version, Waitcnt, Dscnt);
15307a6dacacSDimitry Andric   return Waitcnt;
15317a6dacacSDimitry Andric }
15327a6dacacSDimitry Andric 
encodeLoadcntDscnt(const IsaVersion & Version,const Waitcnt & Decoded)15337a6dacacSDimitry Andric unsigned encodeLoadcntDscnt(const IsaVersion &Version, const Waitcnt &Decoded) {
15347a6dacacSDimitry Andric   return encodeLoadcntDscnt(Version, Decoded.LoadCnt, Decoded.DsCnt);
15357a6dacacSDimitry Andric }
15367a6dacacSDimitry Andric 
encodeStorecntDscnt(const IsaVersion & Version,unsigned Storecnt,unsigned Dscnt)15377a6dacacSDimitry Andric static unsigned encodeStorecntDscnt(const IsaVersion &Version,
15387a6dacacSDimitry Andric                                     unsigned Storecnt, unsigned Dscnt) {
15397a6dacacSDimitry Andric   unsigned Waitcnt = getCombinedCountBitMask(Version, true);
15407a6dacacSDimitry Andric   Waitcnt = encodeStorecnt(Version, Waitcnt, Storecnt);
15417a6dacacSDimitry Andric   Waitcnt = encodeDscnt(Version, Waitcnt, Dscnt);
15427a6dacacSDimitry Andric   return Waitcnt;
15437a6dacacSDimitry Andric }
15447a6dacacSDimitry Andric 
encodeStorecntDscnt(const IsaVersion & Version,const Waitcnt & Decoded)15457a6dacacSDimitry Andric unsigned encodeStorecntDscnt(const IsaVersion &Version,
15467a6dacacSDimitry Andric                              const Waitcnt &Decoded) {
15477a6dacacSDimitry Andric   return encodeStorecntDscnt(Version, Decoded.StoreCnt, Decoded.DsCnt);
15480b57cec5SDimitry Andric }
15490b57cec5SDimitry Andric 
15500b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
155181ad6265SDimitry Andric // Custom Operand Values
155281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
155381ad6265SDimitry Andric 
getDefaultCustomOperandEncoding(const CustomOperandVal * Opr,int Size,const MCSubtargetInfo & STI)155481ad6265SDimitry Andric static unsigned getDefaultCustomOperandEncoding(const CustomOperandVal *Opr,
155581ad6265SDimitry Andric                                                 int Size,
155681ad6265SDimitry Andric                                                 const MCSubtargetInfo &STI) {
155781ad6265SDimitry Andric   unsigned Enc = 0;
155881ad6265SDimitry Andric   for (int Idx = 0; Idx < Size; ++Idx) {
155981ad6265SDimitry Andric     const auto &Op = Opr[Idx];
156081ad6265SDimitry Andric     if (Op.isSupported(STI))
156181ad6265SDimitry Andric       Enc |= Op.encode(Op.Default);
156281ad6265SDimitry Andric   }
156381ad6265SDimitry Andric   return Enc;
156481ad6265SDimitry Andric }
156581ad6265SDimitry Andric 
isSymbolicCustomOperandEncoding(const CustomOperandVal * Opr,int Size,unsigned Code,bool & HasNonDefaultVal,const MCSubtargetInfo & STI)156681ad6265SDimitry Andric static bool isSymbolicCustomOperandEncoding(const CustomOperandVal *Opr,
156781ad6265SDimitry Andric                                             int Size, unsigned Code,
156881ad6265SDimitry Andric                                             bool &HasNonDefaultVal,
156981ad6265SDimitry Andric                                             const MCSubtargetInfo &STI) {
157081ad6265SDimitry Andric   unsigned UsedOprMask = 0;
157181ad6265SDimitry Andric   HasNonDefaultVal = false;
157281ad6265SDimitry Andric   for (int Idx = 0; Idx < Size; ++Idx) {
157381ad6265SDimitry Andric     const auto &Op = Opr[Idx];
157481ad6265SDimitry Andric     if (!Op.isSupported(STI))
157581ad6265SDimitry Andric       continue;
157681ad6265SDimitry Andric     UsedOprMask |= Op.getMask();
157781ad6265SDimitry Andric     unsigned Val = Op.decode(Code);
157881ad6265SDimitry Andric     if (!Op.isValid(Val))
157981ad6265SDimitry Andric       return false;
158081ad6265SDimitry Andric     HasNonDefaultVal |= (Val != Op.Default);
158181ad6265SDimitry Andric   }
158281ad6265SDimitry Andric   return (Code & ~UsedOprMask) == 0;
158381ad6265SDimitry Andric }
158481ad6265SDimitry Andric 
decodeCustomOperand(const CustomOperandVal * Opr,int Size,unsigned Code,int & Idx,StringRef & Name,unsigned & Val,bool & IsDefault,const MCSubtargetInfo & STI)158581ad6265SDimitry Andric static bool decodeCustomOperand(const CustomOperandVal *Opr, int Size,
158681ad6265SDimitry Andric                                 unsigned Code, int &Idx, StringRef &Name,
158781ad6265SDimitry Andric                                 unsigned &Val, bool &IsDefault,
158881ad6265SDimitry Andric                                 const MCSubtargetInfo &STI) {
158981ad6265SDimitry Andric   while (Idx < Size) {
159081ad6265SDimitry Andric     const auto &Op = Opr[Idx++];
159181ad6265SDimitry Andric     if (Op.isSupported(STI)) {
159281ad6265SDimitry Andric       Name = Op.Name;
159381ad6265SDimitry Andric       Val = Op.decode(Code);
159481ad6265SDimitry Andric       IsDefault = (Val == Op.Default);
159581ad6265SDimitry Andric       return true;
159681ad6265SDimitry Andric     }
159781ad6265SDimitry Andric   }
159881ad6265SDimitry Andric 
159981ad6265SDimitry Andric   return false;
160081ad6265SDimitry Andric }
160181ad6265SDimitry Andric 
encodeCustomOperandVal(const CustomOperandVal & Op,int64_t InputVal)160281ad6265SDimitry Andric static int encodeCustomOperandVal(const CustomOperandVal &Op,
160381ad6265SDimitry Andric                                   int64_t InputVal) {
160481ad6265SDimitry Andric   if (InputVal < 0 || InputVal > Op.Max)
160581ad6265SDimitry Andric     return OPR_VAL_INVALID;
160681ad6265SDimitry Andric   return Op.encode(InputVal);
160781ad6265SDimitry Andric }
160881ad6265SDimitry Andric 
encodeCustomOperand(const CustomOperandVal * Opr,int Size,const StringRef Name,int64_t InputVal,unsigned & UsedOprMask,const MCSubtargetInfo & STI)160981ad6265SDimitry Andric static int encodeCustomOperand(const CustomOperandVal *Opr, int Size,
161081ad6265SDimitry Andric                                const StringRef Name, int64_t InputVal,
161181ad6265SDimitry Andric                                unsigned &UsedOprMask,
161281ad6265SDimitry Andric                                const MCSubtargetInfo &STI) {
161381ad6265SDimitry Andric   int InvalidId = OPR_ID_UNKNOWN;
161481ad6265SDimitry Andric   for (int Idx = 0; Idx < Size; ++Idx) {
161581ad6265SDimitry Andric     const auto &Op = Opr[Idx];
161681ad6265SDimitry Andric     if (Op.Name == Name) {
161781ad6265SDimitry Andric       if (!Op.isSupported(STI)) {
161881ad6265SDimitry Andric         InvalidId = OPR_ID_UNSUPPORTED;
161981ad6265SDimitry Andric         continue;
162081ad6265SDimitry Andric       }
162181ad6265SDimitry Andric       auto OprMask = Op.getMask();
162281ad6265SDimitry Andric       if (OprMask & UsedOprMask)
162381ad6265SDimitry Andric         return OPR_ID_DUPLICATE;
162481ad6265SDimitry Andric       UsedOprMask |= OprMask;
162581ad6265SDimitry Andric       return encodeCustomOperandVal(Op, InputVal);
162681ad6265SDimitry Andric     }
162781ad6265SDimitry Andric   }
162881ad6265SDimitry Andric   return InvalidId;
162981ad6265SDimitry Andric }
163081ad6265SDimitry Andric 
163181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
163281ad6265SDimitry Andric // DepCtr
163381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
163481ad6265SDimitry Andric 
163581ad6265SDimitry Andric namespace DepCtr {
163681ad6265SDimitry Andric 
getDefaultDepCtrEncoding(const MCSubtargetInfo & STI)163781ad6265SDimitry Andric int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI) {
163881ad6265SDimitry Andric   static int Default = -1;
163981ad6265SDimitry Andric   if (Default == -1)
164081ad6265SDimitry Andric     Default = getDefaultCustomOperandEncoding(DepCtrInfo, DEP_CTR_SIZE, STI);
164181ad6265SDimitry Andric   return Default;
164281ad6265SDimitry Andric }
164381ad6265SDimitry Andric 
isSymbolicDepCtrEncoding(unsigned Code,bool & HasNonDefaultVal,const MCSubtargetInfo & STI)164481ad6265SDimitry Andric bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal,
164581ad6265SDimitry Andric                               const MCSubtargetInfo &STI) {
164681ad6265SDimitry Andric   return isSymbolicCustomOperandEncoding(DepCtrInfo, DEP_CTR_SIZE, Code,
164781ad6265SDimitry Andric                                          HasNonDefaultVal, STI);
164881ad6265SDimitry Andric }
164981ad6265SDimitry Andric 
decodeDepCtr(unsigned Code,int & Id,StringRef & Name,unsigned & Val,bool & IsDefault,const MCSubtargetInfo & STI)165081ad6265SDimitry Andric bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val,
165181ad6265SDimitry Andric                   bool &IsDefault, const MCSubtargetInfo &STI) {
165281ad6265SDimitry Andric   return decodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Code, Id, Name, Val,
165381ad6265SDimitry Andric                              IsDefault, STI);
165481ad6265SDimitry Andric }
165581ad6265SDimitry Andric 
encodeDepCtr(const StringRef Name,int64_t Val,unsigned & UsedOprMask,const MCSubtargetInfo & STI)165681ad6265SDimitry Andric int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask,
165781ad6265SDimitry Andric                  const MCSubtargetInfo &STI) {
165881ad6265SDimitry Andric   return encodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Name, Val, UsedOprMask,
165981ad6265SDimitry Andric                              STI);
166081ad6265SDimitry Andric }
166181ad6265SDimitry Andric 
decodeFieldVmVsrc(unsigned Encoded)166206c3fb27SDimitry Andric unsigned decodeFieldVmVsrc(unsigned Encoded) {
166306c3fb27SDimitry Andric   return unpackBits(Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth());
166406c3fb27SDimitry Andric }
166506c3fb27SDimitry Andric 
decodeFieldVaVdst(unsigned Encoded)166606c3fb27SDimitry Andric unsigned decodeFieldVaVdst(unsigned Encoded) {
166706c3fb27SDimitry Andric   return unpackBits(Encoded, getVaVdstBitShift(), getVaVdstBitWidth());
166806c3fb27SDimitry Andric }
166906c3fb27SDimitry Andric 
decodeFieldSaSdst(unsigned Encoded)167006c3fb27SDimitry Andric unsigned decodeFieldSaSdst(unsigned Encoded) {
167106c3fb27SDimitry Andric   return unpackBits(Encoded, getSaSdstBitShift(), getSaSdstBitWidth());
167206c3fb27SDimitry Andric }
167306c3fb27SDimitry Andric 
encodeFieldVmVsrc(unsigned Encoded,unsigned VmVsrc)167406c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned Encoded, unsigned VmVsrc) {
167506c3fb27SDimitry Andric   return packBits(VmVsrc, Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth());
167606c3fb27SDimitry Andric }
167706c3fb27SDimitry Andric 
encodeFieldVmVsrc(unsigned VmVsrc)167806c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned VmVsrc) {
167906c3fb27SDimitry Andric   return encodeFieldVmVsrc(0xffff, VmVsrc);
168006c3fb27SDimitry Andric }
168106c3fb27SDimitry Andric 
encodeFieldVaVdst(unsigned Encoded,unsigned VaVdst)168206c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned Encoded, unsigned VaVdst) {
168306c3fb27SDimitry Andric   return packBits(VaVdst, Encoded, getVaVdstBitShift(), getVaVdstBitWidth());
168406c3fb27SDimitry Andric }
168506c3fb27SDimitry Andric 
encodeFieldVaVdst(unsigned VaVdst)168606c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned VaVdst) {
168706c3fb27SDimitry Andric   return encodeFieldVaVdst(0xffff, VaVdst);
168806c3fb27SDimitry Andric }
168906c3fb27SDimitry Andric 
encodeFieldSaSdst(unsigned Encoded,unsigned SaSdst)169006c3fb27SDimitry Andric unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst) {
169106c3fb27SDimitry Andric   return packBits(SaSdst, Encoded, getSaSdstBitShift(), getSaSdstBitWidth());
169206c3fb27SDimitry Andric }
169306c3fb27SDimitry Andric 
encodeFieldSaSdst(unsigned SaSdst)169406c3fb27SDimitry Andric unsigned encodeFieldSaSdst(unsigned SaSdst) {
169506c3fb27SDimitry Andric   return encodeFieldSaSdst(0xffff, SaSdst);
169606c3fb27SDimitry Andric }
169706c3fb27SDimitry Andric 
169881ad6265SDimitry Andric } // namespace DepCtr
169981ad6265SDimitry Andric 
170081ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1701e8d8bef9SDimitry Andric // exp tgt
1702e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1703e8d8bef9SDimitry Andric 
1704e8d8bef9SDimitry Andric namespace Exp {
1705e8d8bef9SDimitry Andric 
1706e8d8bef9SDimitry Andric struct ExpTgt {
1707e8d8bef9SDimitry Andric   StringLiteral Name;
1708e8d8bef9SDimitry Andric   unsigned Tgt;
1709e8d8bef9SDimitry Andric   unsigned MaxIndex;
1710e8d8bef9SDimitry Andric };
1711e8d8bef9SDimitry Andric 
1712e8d8bef9SDimitry Andric static constexpr ExpTgt ExpTgtInfo[] = {
1713e8d8bef9SDimitry Andric   {{"null"},           ET_NULL,            ET_NULL_MAX_IDX},
1714e8d8bef9SDimitry Andric   {{"mrtz"},           ET_MRTZ,            ET_MRTZ_MAX_IDX},
1715e8d8bef9SDimitry Andric   {{"prim"},           ET_PRIM,            ET_PRIM_MAX_IDX},
1716e8d8bef9SDimitry Andric   {{"mrt"},            ET_MRT0,            ET_MRT_MAX_IDX},
1717e8d8bef9SDimitry Andric   {{"pos"},            ET_POS0,            ET_POS_MAX_IDX},
171881ad6265SDimitry Andric   {{"dual_src_blend"}, ET_DUAL_SRC_BLEND0, ET_DUAL_SRC_BLEND_MAX_IDX},
1719e8d8bef9SDimitry Andric   {{"param"},          ET_PARAM0,          ET_PARAM_MAX_IDX},
1720e8d8bef9SDimitry Andric };
1721e8d8bef9SDimitry Andric 
getTgtName(unsigned Id,StringRef & Name,int & Index)1722e8d8bef9SDimitry Andric bool getTgtName(unsigned Id, StringRef &Name, int &Index) {
1723e8d8bef9SDimitry Andric   for (const ExpTgt &Val : ExpTgtInfo) {
1724e8d8bef9SDimitry Andric     if (Val.Tgt <= Id && Id <= Val.Tgt + Val.MaxIndex) {
1725e8d8bef9SDimitry Andric       Index = (Val.MaxIndex == 0) ? -1 : (Id - Val.Tgt);
1726e8d8bef9SDimitry Andric       Name = Val.Name;
1727e8d8bef9SDimitry Andric       return true;
1728e8d8bef9SDimitry Andric     }
1729e8d8bef9SDimitry Andric   }
1730e8d8bef9SDimitry Andric   return false;
1731e8d8bef9SDimitry Andric }
1732e8d8bef9SDimitry Andric 
getTgtId(const StringRef Name)1733e8d8bef9SDimitry Andric unsigned getTgtId(const StringRef Name) {
1734e8d8bef9SDimitry Andric 
1735e8d8bef9SDimitry Andric   for (const ExpTgt &Val : ExpTgtInfo) {
1736e8d8bef9SDimitry Andric     if (Val.MaxIndex == 0 && Name == Val.Name)
1737e8d8bef9SDimitry Andric       return Val.Tgt;
1738e8d8bef9SDimitry Andric 
17395f757f3fSDimitry Andric     if (Val.MaxIndex > 0 && Name.starts_with(Val.Name)) {
1740e8d8bef9SDimitry Andric       StringRef Suffix = Name.drop_front(Val.Name.size());
1741e8d8bef9SDimitry Andric 
1742e8d8bef9SDimitry Andric       unsigned Id;
1743e8d8bef9SDimitry Andric       if (Suffix.getAsInteger(10, Id) || Id > Val.MaxIndex)
1744e8d8bef9SDimitry Andric         return ET_INVALID;
1745e8d8bef9SDimitry Andric 
1746e8d8bef9SDimitry Andric       // Disable leading zeroes
1747e8d8bef9SDimitry Andric       if (Suffix.size() > 1 && Suffix[0] == '0')
1748e8d8bef9SDimitry Andric         return ET_INVALID;
1749e8d8bef9SDimitry Andric 
1750e8d8bef9SDimitry Andric       return Val.Tgt + Id;
1751e8d8bef9SDimitry Andric     }
1752e8d8bef9SDimitry Andric   }
1753e8d8bef9SDimitry Andric   return ET_INVALID;
1754e8d8bef9SDimitry Andric }
1755e8d8bef9SDimitry Andric 
isSupportedTgtId(unsigned Id,const MCSubtargetInfo & STI)1756e8d8bef9SDimitry Andric bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI) {
175781ad6265SDimitry Andric   switch (Id) {
175881ad6265SDimitry Andric   case ET_NULL:
175981ad6265SDimitry Andric     return !isGFX11Plus(STI);
176081ad6265SDimitry Andric   case ET_POS4:
176181ad6265SDimitry Andric   case ET_PRIM:
176281ad6265SDimitry Andric     return isGFX10Plus(STI);
176381ad6265SDimitry Andric   case ET_DUAL_SRC_BLEND0:
176481ad6265SDimitry Andric   case ET_DUAL_SRC_BLEND1:
176581ad6265SDimitry Andric     return isGFX11Plus(STI);
176681ad6265SDimitry Andric   default:
176781ad6265SDimitry Andric     if (Id >= ET_PARAM0 && Id <= ET_PARAM31)
176881ad6265SDimitry Andric       return !isGFX11Plus(STI);
176981ad6265SDimitry Andric     return true;
177081ad6265SDimitry Andric   }
1771e8d8bef9SDimitry Andric }
1772e8d8bef9SDimitry Andric 
1773e8d8bef9SDimitry Andric } // namespace Exp
1774e8d8bef9SDimitry Andric 
1775e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1776e8d8bef9SDimitry Andric // MTBUF Format
1777e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1778e8d8bef9SDimitry Andric 
1779e8d8bef9SDimitry Andric namespace MTBUFFormat {
1780e8d8bef9SDimitry Andric 
getDfmt(const StringRef Name)1781e8d8bef9SDimitry Andric int64_t getDfmt(const StringRef Name) {
1782e8d8bef9SDimitry Andric   for (int Id = DFMT_MIN; Id <= DFMT_MAX; ++Id) {
1783e8d8bef9SDimitry Andric     if (Name == DfmtSymbolic[Id])
1784e8d8bef9SDimitry Andric       return Id;
1785e8d8bef9SDimitry Andric   }
1786e8d8bef9SDimitry Andric   return DFMT_UNDEF;
1787e8d8bef9SDimitry Andric }
1788e8d8bef9SDimitry Andric 
getDfmtName(unsigned Id)1789e8d8bef9SDimitry Andric StringRef getDfmtName(unsigned Id) {
1790e8d8bef9SDimitry Andric   assert(Id <= DFMT_MAX);
1791e8d8bef9SDimitry Andric   return DfmtSymbolic[Id];
1792e8d8bef9SDimitry Andric }
1793e8d8bef9SDimitry Andric 
getNfmtLookupTable(const MCSubtargetInfo & STI)1794e8d8bef9SDimitry Andric static StringLiteral const *getNfmtLookupTable(const MCSubtargetInfo &STI) {
1795e8d8bef9SDimitry Andric   if (isSI(STI) || isCI(STI))
1796e8d8bef9SDimitry Andric     return NfmtSymbolicSICI;
1797e8d8bef9SDimitry Andric   if (isVI(STI) || isGFX9(STI))
1798e8d8bef9SDimitry Andric     return NfmtSymbolicVI;
1799e8d8bef9SDimitry Andric   return NfmtSymbolicGFX10;
1800e8d8bef9SDimitry Andric }
1801e8d8bef9SDimitry Andric 
getNfmt(const StringRef Name,const MCSubtargetInfo & STI)1802e8d8bef9SDimitry Andric int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI) {
1803e8d8bef9SDimitry Andric   auto lookupTable = getNfmtLookupTable(STI);
1804e8d8bef9SDimitry Andric   for (int Id = NFMT_MIN; Id <= NFMT_MAX; ++Id) {
1805e8d8bef9SDimitry Andric     if (Name == lookupTable[Id])
1806e8d8bef9SDimitry Andric       return Id;
1807e8d8bef9SDimitry Andric   }
1808e8d8bef9SDimitry Andric   return NFMT_UNDEF;
1809e8d8bef9SDimitry Andric }
1810e8d8bef9SDimitry Andric 
getNfmtName(unsigned Id,const MCSubtargetInfo & STI)1811e8d8bef9SDimitry Andric StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI) {
1812e8d8bef9SDimitry Andric   assert(Id <= NFMT_MAX);
1813e8d8bef9SDimitry Andric   return getNfmtLookupTable(STI)[Id];
1814e8d8bef9SDimitry Andric }
1815e8d8bef9SDimitry Andric 
isValidDfmtNfmt(unsigned Id,const MCSubtargetInfo & STI)1816e8d8bef9SDimitry Andric bool isValidDfmtNfmt(unsigned Id, const MCSubtargetInfo &STI) {
1817e8d8bef9SDimitry Andric   unsigned Dfmt;
1818e8d8bef9SDimitry Andric   unsigned Nfmt;
1819e8d8bef9SDimitry Andric   decodeDfmtNfmt(Id, Dfmt, Nfmt);
1820e8d8bef9SDimitry Andric   return isValidNfmt(Nfmt, STI);
1821e8d8bef9SDimitry Andric }
1822e8d8bef9SDimitry Andric 
isValidNfmt(unsigned Id,const MCSubtargetInfo & STI)1823e8d8bef9SDimitry Andric bool isValidNfmt(unsigned Id, const MCSubtargetInfo &STI) {
1824e8d8bef9SDimitry Andric   return !getNfmtName(Id, STI).empty();
1825e8d8bef9SDimitry Andric }
1826e8d8bef9SDimitry Andric 
encodeDfmtNfmt(unsigned Dfmt,unsigned Nfmt)1827e8d8bef9SDimitry Andric int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt) {
1828e8d8bef9SDimitry Andric   return (Dfmt << DFMT_SHIFT) | (Nfmt << NFMT_SHIFT);
1829e8d8bef9SDimitry Andric }
1830e8d8bef9SDimitry Andric 
decodeDfmtNfmt(unsigned Format,unsigned & Dfmt,unsigned & Nfmt)1831e8d8bef9SDimitry Andric void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt) {
1832e8d8bef9SDimitry Andric   Dfmt = (Format >> DFMT_SHIFT) & DFMT_MASK;
1833e8d8bef9SDimitry Andric   Nfmt = (Format >> NFMT_SHIFT) & NFMT_MASK;
1834e8d8bef9SDimitry Andric }
1835e8d8bef9SDimitry Andric 
getUnifiedFormat(const StringRef Name,const MCSubtargetInfo & STI)183681ad6265SDimitry Andric int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI) {
183781ad6265SDimitry Andric   if (isGFX11Plus(STI)) {
183881ad6265SDimitry Andric     for (int Id = UfmtGFX11::UFMT_FIRST; Id <= UfmtGFX11::UFMT_LAST; ++Id) {
183981ad6265SDimitry Andric       if (Name == UfmtSymbolicGFX11[Id])
1840e8d8bef9SDimitry Andric         return Id;
1841e8d8bef9SDimitry Andric     }
184281ad6265SDimitry Andric   } else {
184381ad6265SDimitry Andric     for (int Id = UfmtGFX10::UFMT_FIRST; Id <= UfmtGFX10::UFMT_LAST; ++Id) {
184481ad6265SDimitry Andric       if (Name == UfmtSymbolicGFX10[Id])
184581ad6265SDimitry Andric         return Id;
184681ad6265SDimitry Andric     }
184781ad6265SDimitry Andric   }
1848e8d8bef9SDimitry Andric   return UFMT_UNDEF;
1849e8d8bef9SDimitry Andric }
1850e8d8bef9SDimitry Andric 
getUnifiedFormatName(unsigned Id,const MCSubtargetInfo & STI)185181ad6265SDimitry Andric StringRef getUnifiedFormatName(unsigned Id, const MCSubtargetInfo &STI) {
185281ad6265SDimitry Andric   if(isValidUnifiedFormat(Id, STI))
185381ad6265SDimitry Andric     return isGFX10(STI) ? UfmtSymbolicGFX10[Id] : UfmtSymbolicGFX11[Id];
185481ad6265SDimitry Andric   return "";
1855e8d8bef9SDimitry Andric }
1856e8d8bef9SDimitry Andric 
isValidUnifiedFormat(unsigned Id,const MCSubtargetInfo & STI)185781ad6265SDimitry Andric bool isValidUnifiedFormat(unsigned Id, const MCSubtargetInfo &STI) {
185881ad6265SDimitry Andric   return isGFX10(STI) ? Id <= UfmtGFX10::UFMT_LAST : Id <= UfmtGFX11::UFMT_LAST;
1859e8d8bef9SDimitry Andric }
1860e8d8bef9SDimitry Andric 
convertDfmtNfmt2Ufmt(unsigned Dfmt,unsigned Nfmt,const MCSubtargetInfo & STI)186181ad6265SDimitry Andric int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt,
186281ad6265SDimitry Andric                              const MCSubtargetInfo &STI) {
1863e8d8bef9SDimitry Andric   int64_t Fmt = encodeDfmtNfmt(Dfmt, Nfmt);
186481ad6265SDimitry Andric   if (isGFX11Plus(STI)) {
186581ad6265SDimitry Andric     for (int Id = UfmtGFX11::UFMT_FIRST; Id <= UfmtGFX11::UFMT_LAST; ++Id) {
186681ad6265SDimitry Andric       if (Fmt == DfmtNfmt2UFmtGFX11[Id])
1867e8d8bef9SDimitry Andric         return Id;
1868e8d8bef9SDimitry Andric     }
186981ad6265SDimitry Andric   } else {
187081ad6265SDimitry Andric     for (int Id = UfmtGFX10::UFMT_FIRST; Id <= UfmtGFX10::UFMT_LAST; ++Id) {
187181ad6265SDimitry Andric       if (Fmt == DfmtNfmt2UFmtGFX10[Id])
187281ad6265SDimitry Andric         return Id;
187381ad6265SDimitry Andric     }
187481ad6265SDimitry Andric   }
1875e8d8bef9SDimitry Andric   return UFMT_UNDEF;
1876e8d8bef9SDimitry Andric }
1877e8d8bef9SDimitry Andric 
isValidFormatEncoding(unsigned Val,const MCSubtargetInfo & STI)1878e8d8bef9SDimitry Andric bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI) {
1879e8d8bef9SDimitry Andric   return isGFX10Plus(STI) ? (Val <= UFMT_MAX) : (Val <= DFMT_NFMT_MAX);
1880e8d8bef9SDimitry Andric }
1881e8d8bef9SDimitry Andric 
getDefaultFormatEncoding(const MCSubtargetInfo & STI)1882e8d8bef9SDimitry Andric unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI) {
1883e8d8bef9SDimitry Andric   if (isGFX10Plus(STI))
1884e8d8bef9SDimitry Andric     return UFMT_DEFAULT;
1885e8d8bef9SDimitry Andric   return DFMT_NFMT_DEFAULT;
1886e8d8bef9SDimitry Andric }
1887e8d8bef9SDimitry Andric 
1888e8d8bef9SDimitry Andric } // namespace MTBUFFormat
1889e8d8bef9SDimitry Andric 
1890e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
18910b57cec5SDimitry Andric // SendMsg
18920b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric namespace SendMsg {
18950b57cec5SDimitry Andric 
getMsgIdMask(const MCSubtargetInfo & STI)189681ad6265SDimitry Andric static uint64_t getMsgIdMask(const MCSubtargetInfo &STI) {
189781ad6265SDimitry Andric   return isGFX11Plus(STI) ? ID_MASK_GFX11Plus_ : ID_MASK_PreGFX11_;
18980b57cec5SDimitry Andric }
18990b57cec5SDimitry Andric 
isValidMsgId(int64_t MsgId,const MCSubtargetInfo & STI)190081ad6265SDimitry Andric bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI) {
190181ad6265SDimitry Andric   return (MsgId & ~(getMsgIdMask(STI))) == 0;
190281ad6265SDimitry Andric }
190381ad6265SDimitry Andric 
isValidMsgOp(int64_t MsgId,int64_t OpId,const MCSubtargetInfo & STI,bool Strict)1904fe6060f1SDimitry Andric bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI,
1905fe6060f1SDimitry Andric                   bool Strict) {
190681ad6265SDimitry Andric   assert(isValidMsgId(MsgId, STI));
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric   if (!Strict)
19090b57cec5SDimitry Andric     return 0 <= OpId && isUInt<OP_WIDTH_>(OpId);
19100b57cec5SDimitry Andric 
1911*0fca6ea1SDimitry Andric   if (msgRequiresOp(MsgId, STI)) {
1912*0fca6ea1SDimitry Andric     if (MsgId == ID_GS_PreGFX11 && OpId == OP_GS_NOP)
1913*0fca6ea1SDimitry Andric       return false;
1914*0fca6ea1SDimitry Andric 
1915*0fca6ea1SDimitry Andric     return !getMsgOpName(MsgId, OpId, STI).empty();
19160b57cec5SDimitry Andric   }
19170b57cec5SDimitry Andric 
1918*0fca6ea1SDimitry Andric   return OpId == OP_NONE_;
19190b57cec5SDimitry Andric }
19200b57cec5SDimitry Andric 
isValidMsgStream(int64_t MsgId,int64_t OpId,int64_t StreamId,const MCSubtargetInfo & STI,bool Strict)1921fe6060f1SDimitry Andric bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId,
1922fe6060f1SDimitry Andric                       const MCSubtargetInfo &STI, bool Strict) {
1923fe6060f1SDimitry Andric   assert(isValidMsgOp(MsgId, OpId, STI, Strict));
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric   if (!Strict)
19260b57cec5SDimitry Andric     return 0 <= StreamId && isUInt<STREAM_ID_WIDTH_>(StreamId);
19270b57cec5SDimitry Andric 
192881ad6265SDimitry Andric   if (!isGFX11Plus(STI)) {
192981ad6265SDimitry Andric     switch (MsgId) {
193081ad6265SDimitry Andric     case ID_GS_PreGFX11:
19310b57cec5SDimitry Andric       return STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_;
193281ad6265SDimitry Andric     case ID_GS_DONE_PreGFX11:
19330b57cec5SDimitry Andric       return (OpId == OP_GS_NOP) ?
19340b57cec5SDimitry Andric           (StreamId == STREAM_ID_NONE_) :
19350b57cec5SDimitry Andric           (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_);
193681ad6265SDimitry Andric     }
193781ad6265SDimitry Andric   }
19380b57cec5SDimitry Andric   return StreamId == STREAM_ID_NONE_;
19390b57cec5SDimitry Andric }
194081ad6265SDimitry Andric 
msgRequiresOp(int64_t MsgId,const MCSubtargetInfo & STI)194181ad6265SDimitry Andric bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI) {
194281ad6265SDimitry Andric   return MsgId == ID_SYSMSG ||
194381ad6265SDimitry Andric       (!isGFX11Plus(STI) &&
194481ad6265SDimitry Andric        (MsgId == ID_GS_PreGFX11 || MsgId == ID_GS_DONE_PreGFX11));
19450b57cec5SDimitry Andric }
19460b57cec5SDimitry Andric 
msgSupportsStream(int64_t MsgId,int64_t OpId,const MCSubtargetInfo & STI)194781ad6265SDimitry Andric bool msgSupportsStream(int64_t MsgId, int64_t OpId,
194881ad6265SDimitry Andric                        const MCSubtargetInfo &STI) {
194981ad6265SDimitry Andric   return !isGFX11Plus(STI) &&
195081ad6265SDimitry Andric       (MsgId == ID_GS_PreGFX11 || MsgId == ID_GS_DONE_PreGFX11) &&
195181ad6265SDimitry Andric       OpId != OP_GS_NOP;
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric 
decodeMsg(unsigned Val,uint16_t & MsgId,uint16_t & OpId,uint16_t & StreamId,const MCSubtargetInfo & STI)195481ad6265SDimitry Andric void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId,
195581ad6265SDimitry Andric                uint16_t &StreamId, const MCSubtargetInfo &STI) {
195681ad6265SDimitry Andric   MsgId = Val & getMsgIdMask(STI);
195781ad6265SDimitry Andric   if (isGFX11Plus(STI)) {
195881ad6265SDimitry Andric     OpId = 0;
195981ad6265SDimitry Andric     StreamId = 0;
196081ad6265SDimitry Andric   } else {
19610b57cec5SDimitry Andric     OpId = (Val & OP_MASK_) >> OP_SHIFT_;
19620b57cec5SDimitry Andric     StreamId = (Val & STREAM_ID_MASK_) >> STREAM_ID_SHIFT_;
19630b57cec5SDimitry Andric   }
196481ad6265SDimitry Andric }
19650b57cec5SDimitry Andric 
encodeMsg(uint64_t MsgId,uint64_t OpId,uint64_t StreamId)19660b57cec5SDimitry Andric uint64_t encodeMsg(uint64_t MsgId,
19670b57cec5SDimitry Andric                    uint64_t OpId,
19680b57cec5SDimitry Andric                    uint64_t StreamId) {
196981ad6265SDimitry Andric   return MsgId | (OpId << OP_SHIFT_) | (StreamId << STREAM_ID_SHIFT_);
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric 
19720b57cec5SDimitry Andric } // namespace SendMsg
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19750b57cec5SDimitry Andric //
19760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19770b57cec5SDimitry Andric 
getInitialPSInputAddr(const Function & F)19780b57cec5SDimitry Andric unsigned getInitialPSInputAddr(const Function &F) {
1979bdd1243dSDimitry Andric   return F.getFnAttributeAsParsedInteger("InitialPSInputAddr", 0);
19800b57cec5SDimitry Andric }
19810b57cec5SDimitry Andric 
getHasColorExport(const Function & F)1982fe6060f1SDimitry Andric bool getHasColorExport(const Function &F) {
1983fe6060f1SDimitry Andric   // As a safe default always respond as if PS has color exports.
1984bdd1243dSDimitry Andric   return F.getFnAttributeAsParsedInteger(
1985bdd1243dSDimitry Andric              "amdgpu-color-export",
1986fe6060f1SDimitry Andric              F.getCallingConv() == CallingConv::AMDGPU_PS ? 1 : 0) != 0;
1987fe6060f1SDimitry Andric }
1988fe6060f1SDimitry Andric 
getHasDepthExport(const Function & F)1989fe6060f1SDimitry Andric bool getHasDepthExport(const Function &F) {
1990bdd1243dSDimitry Andric   return F.getFnAttributeAsParsedInteger("amdgpu-depth-export", 0) != 0;
1991fe6060f1SDimitry Andric }
1992fe6060f1SDimitry Andric 
isShader(CallingConv::ID cc)19930b57cec5SDimitry Andric bool isShader(CallingConv::ID cc) {
19940b57cec5SDimitry Andric   switch(cc) {
19950b57cec5SDimitry Andric     case CallingConv::AMDGPU_VS:
19960b57cec5SDimitry Andric     case CallingConv::AMDGPU_LS:
19970b57cec5SDimitry Andric     case CallingConv::AMDGPU_HS:
19980b57cec5SDimitry Andric     case CallingConv::AMDGPU_ES:
19990b57cec5SDimitry Andric     case CallingConv::AMDGPU_GS:
20000b57cec5SDimitry Andric     case CallingConv::AMDGPU_PS:
20015f757f3fSDimitry Andric     case CallingConv::AMDGPU_CS_Chain:
20025f757f3fSDimitry Andric     case CallingConv::AMDGPU_CS_ChainPreserve:
20030b57cec5SDimitry Andric     case CallingConv::AMDGPU_CS:
20040b57cec5SDimitry Andric       return true;
20050b57cec5SDimitry Andric     default:
20060b57cec5SDimitry Andric       return false;
20070b57cec5SDimitry Andric   }
20080b57cec5SDimitry Andric }
20090b57cec5SDimitry Andric 
isGraphics(CallingConv::ID cc)2010e8d8bef9SDimitry Andric bool isGraphics(CallingConv::ID cc) {
2011e8d8bef9SDimitry Andric   return isShader(cc) || cc == CallingConv::AMDGPU_Gfx;
2012e8d8bef9SDimitry Andric }
2013e8d8bef9SDimitry Andric 
isCompute(CallingConv::ID cc)20140b57cec5SDimitry Andric bool isCompute(CallingConv::ID cc) {
2015e8d8bef9SDimitry Andric   return !isGraphics(cc) || cc == CallingConv::AMDGPU_CS;
20160b57cec5SDimitry Andric }
20170b57cec5SDimitry Andric 
isEntryFunctionCC(CallingConv::ID CC)20180b57cec5SDimitry Andric bool isEntryFunctionCC(CallingConv::ID CC) {
20190b57cec5SDimitry Andric   switch (CC) {
20200b57cec5SDimitry Andric   case CallingConv::AMDGPU_KERNEL:
20210b57cec5SDimitry Andric   case CallingConv::SPIR_KERNEL:
20220b57cec5SDimitry Andric   case CallingConv::AMDGPU_VS:
20230b57cec5SDimitry Andric   case CallingConv::AMDGPU_GS:
20240b57cec5SDimitry Andric   case CallingConv::AMDGPU_PS:
20250b57cec5SDimitry Andric   case CallingConv::AMDGPU_CS:
20260b57cec5SDimitry Andric   case CallingConv::AMDGPU_ES:
20270b57cec5SDimitry Andric   case CallingConv::AMDGPU_HS:
20280b57cec5SDimitry Andric   case CallingConv::AMDGPU_LS:
20290b57cec5SDimitry Andric     return true;
20300b57cec5SDimitry Andric   default:
20310b57cec5SDimitry Andric     return false;
20320b57cec5SDimitry Andric   }
20330b57cec5SDimitry Andric }
20340b57cec5SDimitry Andric 
isModuleEntryFunctionCC(CallingConv::ID CC)2035e8d8bef9SDimitry Andric bool isModuleEntryFunctionCC(CallingConv::ID CC) {
2036e8d8bef9SDimitry Andric   switch (CC) {
2037e8d8bef9SDimitry Andric   case CallingConv::AMDGPU_Gfx:
2038e8d8bef9SDimitry Andric     return true;
2039e8d8bef9SDimitry Andric   default:
20405f757f3fSDimitry Andric     return isEntryFunctionCC(CC) || isChainCC(CC);
20415f757f3fSDimitry Andric   }
20425f757f3fSDimitry Andric }
20435f757f3fSDimitry Andric 
isChainCC(CallingConv::ID CC)20445f757f3fSDimitry Andric bool isChainCC(CallingConv::ID CC) {
20455f757f3fSDimitry Andric   switch (CC) {
20465f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_Chain:
20475f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_ChainPreserve:
20485f757f3fSDimitry Andric     return true;
20495f757f3fSDimitry Andric   default:
20505f757f3fSDimitry Andric     return false;
2051e8d8bef9SDimitry Andric   }
2052e8d8bef9SDimitry Andric }
2053e8d8bef9SDimitry Andric 
isKernelCC(const Function * Func)205481ad6265SDimitry Andric bool isKernelCC(const Function *Func) {
205581ad6265SDimitry Andric   return AMDGPU::isModuleEntryFunctionCC(Func->getCallingConv());
205681ad6265SDimitry Andric }
205781ad6265SDimitry Andric 
hasXNACK(const MCSubtargetInfo & STI)20580b57cec5SDimitry Andric bool hasXNACK(const MCSubtargetInfo &STI) {
205906c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureXNACK);
20600b57cec5SDimitry Andric }
20610b57cec5SDimitry Andric 
hasSRAMECC(const MCSubtargetInfo & STI)20620b57cec5SDimitry Andric bool hasSRAMECC(const MCSubtargetInfo &STI) {
206306c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureSRAMECC);
20640b57cec5SDimitry Andric }
20650b57cec5SDimitry Andric 
hasMIMG_R128(const MCSubtargetInfo & STI)20660b57cec5SDimitry Andric bool hasMIMG_R128(const MCSubtargetInfo &STI) {
206706c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureMIMG_R128) && !STI.hasFeature(AMDGPU::FeatureR128A16);
20685ffd83dbSDimitry Andric }
20695ffd83dbSDimitry Andric 
hasA16(const MCSubtargetInfo & STI)2070bdd1243dSDimitry Andric bool hasA16(const MCSubtargetInfo &STI) {
207106c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureA16);
20725ffd83dbSDimitry Andric }
20735ffd83dbSDimitry Andric 
hasG16(const MCSubtargetInfo & STI)20745ffd83dbSDimitry Andric bool hasG16(const MCSubtargetInfo &STI) {
207506c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureG16);
20760b57cec5SDimitry Andric }
20770b57cec5SDimitry Andric 
hasPackedD16(const MCSubtargetInfo & STI)20780b57cec5SDimitry Andric bool hasPackedD16(const MCSubtargetInfo &STI) {
207906c3fb27SDimitry Andric   return !STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) && !isCI(STI) &&
208081ad6265SDimitry Andric          !isSI(STI);
20810b57cec5SDimitry Andric }
20820b57cec5SDimitry Andric 
hasGDS(const MCSubtargetInfo & STI)20835f757f3fSDimitry Andric bool hasGDS(const MCSubtargetInfo &STI) {
20845f757f3fSDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGDS);
20855f757f3fSDimitry Andric }
20865f757f3fSDimitry Andric 
getNSAMaxSize(const MCSubtargetInfo & STI,bool HasSampler)20875f757f3fSDimitry Andric unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler) {
208806c3fb27SDimitry Andric   auto Version = getIsaVersion(STI.getCPU());
208906c3fb27SDimitry Andric   if (Version.Major == 10)
209006c3fb27SDimitry Andric     return Version.Minor >= 3 ? 13 : 5;
209106c3fb27SDimitry Andric   if (Version.Major == 11)
209206c3fb27SDimitry Andric     return 5;
20935f757f3fSDimitry Andric   if (Version.Major >= 12)
20945f757f3fSDimitry Andric     return HasSampler ? 4 : 5;
209506c3fb27SDimitry Andric   return 0;
209606c3fb27SDimitry Andric }
209706c3fb27SDimitry Andric 
getMaxNumUserSGPRs(const MCSubtargetInfo & STI)20985f757f3fSDimitry Andric unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI) { return 16; }
20995f757f3fSDimitry Andric 
isSI(const MCSubtargetInfo & STI)21000b57cec5SDimitry Andric bool isSI(const MCSubtargetInfo &STI) {
210106c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureSouthernIslands);
21020b57cec5SDimitry Andric }
21030b57cec5SDimitry Andric 
isCI(const MCSubtargetInfo & STI)21040b57cec5SDimitry Andric bool isCI(const MCSubtargetInfo &STI) {
210506c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureSeaIslands);
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric 
isVI(const MCSubtargetInfo & STI)21080b57cec5SDimitry Andric bool isVI(const MCSubtargetInfo &STI) {
210906c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
21100b57cec5SDimitry Andric }
21110b57cec5SDimitry Andric 
isGFX9(const MCSubtargetInfo & STI)21120b57cec5SDimitry Andric bool isGFX9(const MCSubtargetInfo &STI) {
211306c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX9);
21140b57cec5SDimitry Andric }
21150b57cec5SDimitry Andric 
isGFX9_GFX10(const MCSubtargetInfo & STI)211681ad6265SDimitry Andric bool isGFX9_GFX10(const MCSubtargetInfo &STI) {
211781ad6265SDimitry Andric   return isGFX9(STI) || isGFX10(STI);
211881ad6265SDimitry Andric }
211981ad6265SDimitry Andric 
isGFX9_GFX10_GFX11(const MCSubtargetInfo & STI)21205f757f3fSDimitry Andric bool isGFX9_GFX10_GFX11(const MCSubtargetInfo &STI) {
21215f757f3fSDimitry Andric   return isGFX9(STI) || isGFX10(STI) || isGFX11(STI);
21225f757f3fSDimitry Andric }
21235f757f3fSDimitry Andric 
isGFX8_GFX9_GFX10(const MCSubtargetInfo & STI)212481ad6265SDimitry Andric bool isGFX8_GFX9_GFX10(const MCSubtargetInfo &STI) {
212581ad6265SDimitry Andric   return isVI(STI) || isGFX9(STI) || isGFX10(STI);
212681ad6265SDimitry Andric }
212781ad6265SDimitry Andric 
isGFX8Plus(const MCSubtargetInfo & STI)212881ad6265SDimitry Andric bool isGFX8Plus(const MCSubtargetInfo &STI) {
212981ad6265SDimitry Andric   return isVI(STI) || isGFX9Plus(STI);
213081ad6265SDimitry Andric }
213181ad6265SDimitry Andric 
isGFX9Plus(const MCSubtargetInfo & STI)2132e8d8bef9SDimitry Andric bool isGFX9Plus(const MCSubtargetInfo &STI) {
2133e8d8bef9SDimitry Andric   return isGFX9(STI) || isGFX10Plus(STI);
2134e8d8bef9SDimitry Andric }
2135e8d8bef9SDimitry Andric 
isNotGFX9Plus(const MCSubtargetInfo & STI)2136*0fca6ea1SDimitry Andric bool isNotGFX9Plus(const MCSubtargetInfo &STI) { return !isGFX9Plus(STI); }
2137*0fca6ea1SDimitry Andric 
isGFX10(const MCSubtargetInfo & STI)21380b57cec5SDimitry Andric bool isGFX10(const MCSubtargetInfo &STI) {
213906c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX10);
21400b57cec5SDimitry Andric }
21410b57cec5SDimitry Andric 
isGFX10_GFX11(const MCSubtargetInfo & STI)21425f757f3fSDimitry Andric bool isGFX10_GFX11(const MCSubtargetInfo &STI) {
21435f757f3fSDimitry Andric   return isGFX10(STI) || isGFX11(STI);
21445f757f3fSDimitry Andric }
21455f757f3fSDimitry Andric 
isGFX10Plus(const MCSubtargetInfo & STI)214681ad6265SDimitry Andric bool isGFX10Plus(const MCSubtargetInfo &STI) {
214781ad6265SDimitry Andric   return isGFX10(STI) || isGFX11Plus(STI);
214881ad6265SDimitry Andric }
214981ad6265SDimitry Andric 
isGFX11(const MCSubtargetInfo & STI)215081ad6265SDimitry Andric bool isGFX11(const MCSubtargetInfo &STI) {
215106c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX11);
215281ad6265SDimitry Andric }
215381ad6265SDimitry Andric 
isGFX11Plus(const MCSubtargetInfo & STI)215481ad6265SDimitry Andric bool isGFX11Plus(const MCSubtargetInfo &STI) {
21555f757f3fSDimitry Andric   return isGFX11(STI) || isGFX12Plus(STI);
215681ad6265SDimitry Andric }
215781ad6265SDimitry Andric 
isGFX12(const MCSubtargetInfo & STI)21585f757f3fSDimitry Andric bool isGFX12(const MCSubtargetInfo &STI) {
21595f757f3fSDimitry Andric   return STI.getFeatureBits()[AMDGPU::FeatureGFX12];
21605f757f3fSDimitry Andric }
21615f757f3fSDimitry Andric 
isGFX12Plus(const MCSubtargetInfo & STI)21625f757f3fSDimitry Andric bool isGFX12Plus(const MCSubtargetInfo &STI) { return isGFX12(STI); }
21635f757f3fSDimitry Andric 
isNotGFX12Plus(const MCSubtargetInfo & STI)21645f757f3fSDimitry Andric bool isNotGFX12Plus(const MCSubtargetInfo &STI) { return !isGFX12Plus(STI); }
21655f757f3fSDimitry Andric 
isNotGFX11Plus(const MCSubtargetInfo & STI)216681ad6265SDimitry Andric bool isNotGFX11Plus(const MCSubtargetInfo &STI) {
216781ad6265SDimitry Andric   return !isGFX11Plus(STI);
216881ad6265SDimitry Andric }
216981ad6265SDimitry Andric 
isNotGFX10Plus(const MCSubtargetInfo & STI)217081ad6265SDimitry Andric bool isNotGFX10Plus(const MCSubtargetInfo &STI) {
217181ad6265SDimitry Andric   return isSI(STI) || isCI(STI) || isVI(STI) || isGFX9(STI);
217281ad6265SDimitry Andric }
217381ad6265SDimitry Andric 
isGFX10Before1030(const MCSubtargetInfo & STI)217481ad6265SDimitry Andric bool isGFX10Before1030(const MCSubtargetInfo &STI) {
217581ad6265SDimitry Andric   return isGFX10(STI) && !AMDGPU::isGFX10_BEncoding(STI);
217681ad6265SDimitry Andric }
2177e8d8bef9SDimitry Andric 
isGCN3Encoding(const MCSubtargetInfo & STI)21780b57cec5SDimitry Andric bool isGCN3Encoding(const MCSubtargetInfo &STI) {
217906c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGCN3Encoding);
21800b57cec5SDimitry Andric }
21810b57cec5SDimitry Andric 
isGFX10_AEncoding(const MCSubtargetInfo & STI)2182fe6060f1SDimitry Andric bool isGFX10_AEncoding(const MCSubtargetInfo &STI) {
218306c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX10_AEncoding);
2184fe6060f1SDimitry Andric }
2185fe6060f1SDimitry Andric 
isGFX10_BEncoding(const MCSubtargetInfo & STI)21865ffd83dbSDimitry Andric bool isGFX10_BEncoding(const MCSubtargetInfo &STI) {
218706c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding);
21885ffd83dbSDimitry Andric }
21895ffd83dbSDimitry Andric 
hasGFX10_3Insts(const MCSubtargetInfo & STI)21905ffd83dbSDimitry Andric bool hasGFX10_3Insts(const MCSubtargetInfo &STI) {
219106c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX10_3Insts);
21925ffd83dbSDimitry Andric }
21935ffd83dbSDimitry Andric 
isGFX10_3_GFX11(const MCSubtargetInfo & STI)21945f757f3fSDimitry Andric bool isGFX10_3_GFX11(const MCSubtargetInfo &STI) {
21955f757f3fSDimitry Andric   return isGFX10_BEncoding(STI) && !isGFX12Plus(STI);
21965f757f3fSDimitry Andric }
21975f757f3fSDimitry Andric 
isGFX90A(const MCSubtargetInfo & STI)2198fe6060f1SDimitry Andric bool isGFX90A(const MCSubtargetInfo &STI) {
219906c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX90AInsts);
2200fe6060f1SDimitry Andric }
2201fe6060f1SDimitry Andric 
isGFX940(const MCSubtargetInfo & STI)220281ad6265SDimitry Andric bool isGFX940(const MCSubtargetInfo &STI) {
220306c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX940Insts);
220481ad6265SDimitry Andric }
220581ad6265SDimitry Andric 
hasArchitectedFlatScratch(const MCSubtargetInfo & STI)2206fe6060f1SDimitry Andric bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI) {
220706c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch);
2208fe6060f1SDimitry Andric }
2209fe6060f1SDimitry Andric 
hasMAIInsts(const MCSubtargetInfo & STI)221081ad6265SDimitry Andric bool hasMAIInsts(const MCSubtargetInfo &STI) {
221106c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureMAIInsts);
221281ad6265SDimitry Andric }
221381ad6265SDimitry Andric 
hasVOPD(const MCSubtargetInfo & STI)221481ad6265SDimitry Andric bool hasVOPD(const MCSubtargetInfo &STI) {
221506c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureVOPD);
221681ad6265SDimitry Andric }
221781ad6265SDimitry Andric 
hasDPPSrc1SGPR(const MCSubtargetInfo & STI)22185f757f3fSDimitry Andric bool hasDPPSrc1SGPR(const MCSubtargetInfo &STI) {
22195f757f3fSDimitry Andric   return STI.hasFeature(AMDGPU::FeatureDPPSrc1SGPR);
22205f757f3fSDimitry Andric }
22215f757f3fSDimitry Andric 
hasKernargPreload(const MCSubtargetInfo & STI)22225f757f3fSDimitry Andric unsigned hasKernargPreload(const MCSubtargetInfo &STI) {
22235f757f3fSDimitry Andric   return STI.hasFeature(AMDGPU::FeatureKernargPreload);
22245f757f3fSDimitry Andric }
22255f757f3fSDimitry Andric 
getTotalNumVGPRs(bool has90AInsts,int32_t ArgNumAGPR,int32_t ArgNumVGPR)222681ad6265SDimitry Andric int32_t getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR,
222781ad6265SDimitry Andric                          int32_t ArgNumVGPR) {
222881ad6265SDimitry Andric   if (has90AInsts && ArgNumAGPR)
222981ad6265SDimitry Andric     return alignTo(ArgNumVGPR, 4) + ArgNumAGPR;
223081ad6265SDimitry Andric   return std::max(ArgNumVGPR, ArgNumAGPR);
223181ad6265SDimitry Andric }
223281ad6265SDimitry Andric 
isSGPR(unsigned Reg,const MCRegisterInfo * TRI)22330b57cec5SDimitry Andric bool isSGPR(unsigned Reg, const MCRegisterInfo* TRI) {
22340b57cec5SDimitry Andric   const MCRegisterClass SGPRClass = TRI->getRegClass(AMDGPU::SReg_32RegClassID);
22355ffd83dbSDimitry Andric   const unsigned FirstSubReg = TRI->getSubReg(Reg, AMDGPU::sub0);
22360b57cec5SDimitry Andric   return SGPRClass.contains(FirstSubReg != 0 ? FirstSubReg : Reg) ||
22370b57cec5SDimitry Andric     Reg == AMDGPU::SCC;
22380b57cec5SDimitry Andric }
22390b57cec5SDimitry Andric 
isHi(unsigned Reg,const MCRegisterInfo & MRI)22405f757f3fSDimitry Andric bool isHi(unsigned Reg, const MCRegisterInfo &MRI) {
22415f757f3fSDimitry Andric   return MRI.getEncodingValue(Reg) & AMDGPU::HWEncoding::IS_HI;
22425f757f3fSDimitry Andric }
22435f757f3fSDimitry Andric 
22440b57cec5SDimitry Andric #define MAP_REG2REG \
22450b57cec5SDimitry Andric   using namespace AMDGPU; \
22460b57cec5SDimitry Andric   switch(Reg) { \
22470b57cec5SDimitry Andric   default: return Reg; \
22480b57cec5SDimitry Andric   CASE_CI_VI(FLAT_SCR) \
22490b57cec5SDimitry Andric   CASE_CI_VI(FLAT_SCR_LO) \
22500b57cec5SDimitry Andric   CASE_CI_VI(FLAT_SCR_HI) \
2251e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP0) \
2252e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP1) \
2253e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP2) \
2254e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP3) \
2255e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP4) \
2256e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP5) \
2257e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP6) \
2258e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP7) \
2259e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP8) \
2260e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP9) \
2261e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP10) \
2262e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP11) \
2263e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP12) \
2264e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP13) \
2265e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP14) \
2266e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP15) \
2267e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP0_TTMP1) \
2268e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP2_TTMP3) \
2269e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP4_TTMP5) \
2270e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP6_TTMP7) \
2271e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP8_TTMP9) \
2272e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP10_TTMP11) \
2273e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP12_TTMP13) \
2274e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP14_TTMP15) \
2275e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP0_TTMP1_TTMP2_TTMP3) \
2276e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP4_TTMP5_TTMP6_TTMP7) \
2277e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP8_TTMP9_TTMP10_TTMP11) \
2278e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP12_TTMP13_TTMP14_TTMP15) \
2279e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP0_TTMP1_TTMP2_TTMP3_TTMP4_TTMP5_TTMP6_TTMP7) \
2280e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP4_TTMP5_TTMP6_TTMP7_TTMP8_TTMP9_TTMP10_TTMP11) \
2281e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP8_TTMP9_TTMP10_TTMP11_TTMP12_TTMP13_TTMP14_TTMP15) \
2282e8d8bef9SDimitry Andric   CASE_VI_GFX9PLUS(TTMP0_TTMP1_TTMP2_TTMP3_TTMP4_TTMP5_TTMP6_TTMP7_TTMP8_TTMP9_TTMP10_TTMP11_TTMP12_TTMP13_TTMP14_TTMP15) \
228381ad6265SDimitry Andric   CASE_GFXPRE11_GFX11PLUS(M0) \
228481ad6265SDimitry Andric   CASE_GFXPRE11_GFX11PLUS(SGPR_NULL) \
228581ad6265SDimitry Andric   CASE_GFXPRE11_GFX11PLUS_TO(SGPR_NULL64, SGPR_NULL) \
22860b57cec5SDimitry Andric   }
22870b57cec5SDimitry Andric 
22880b57cec5SDimitry Andric #define CASE_CI_VI(node) \
22890b57cec5SDimitry Andric   assert(!isSI(STI)); \
22900b57cec5SDimitry Andric   case node: return isCI(STI) ? node##_ci : node##_vi;
22910b57cec5SDimitry Andric 
2292e8d8bef9SDimitry Andric #define CASE_VI_GFX9PLUS(node) \
2293e8d8bef9SDimitry Andric   case node: return isGFX9Plus(STI) ? node##_gfx9plus : node##_vi;
22940b57cec5SDimitry Andric 
229581ad6265SDimitry Andric #define CASE_GFXPRE11_GFX11PLUS(node) \
229681ad6265SDimitry Andric   case node: return isGFX11Plus(STI) ? node##_gfx11plus : node##_gfxpre11;
229781ad6265SDimitry Andric 
229881ad6265SDimitry Andric #define CASE_GFXPRE11_GFX11PLUS_TO(node, result) \
229981ad6265SDimitry Andric   case node: return isGFX11Plus(STI) ? result##_gfx11plus : result##_gfxpre11;
230081ad6265SDimitry Andric 
getMCReg(unsigned Reg,const MCSubtargetInfo & STI)23010b57cec5SDimitry Andric unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI) {
23020b57cec5SDimitry Andric   if (STI.getTargetTriple().getArch() == Triple::r600)
23030b57cec5SDimitry Andric     return Reg;
23040b57cec5SDimitry Andric   MAP_REG2REG
23050b57cec5SDimitry Andric }
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric #undef CASE_CI_VI
2308e8d8bef9SDimitry Andric #undef CASE_VI_GFX9PLUS
230981ad6265SDimitry Andric #undef CASE_GFXPRE11_GFX11PLUS
231081ad6265SDimitry Andric #undef CASE_GFXPRE11_GFX11PLUS_TO
23110b57cec5SDimitry Andric 
23120b57cec5SDimitry Andric #define CASE_CI_VI(node)   case node##_ci: case node##_vi:   return node;
2313e8d8bef9SDimitry Andric #define CASE_VI_GFX9PLUS(node) case node##_vi: case node##_gfx9plus: return node;
231481ad6265SDimitry Andric #define CASE_GFXPRE11_GFX11PLUS(node) case node##_gfx11plus: case node##_gfxpre11: return node;
231581ad6265SDimitry Andric #define CASE_GFXPRE11_GFX11PLUS_TO(node, result)
23160b57cec5SDimitry Andric 
mc2PseudoReg(unsigned Reg)23170b57cec5SDimitry Andric unsigned mc2PseudoReg(unsigned Reg) {
23180b57cec5SDimitry Andric   MAP_REG2REG
23190b57cec5SDimitry Andric }
23200b57cec5SDimitry Andric 
isInlineValue(unsigned Reg)2321bdd1243dSDimitry Andric bool isInlineValue(unsigned Reg) {
2322bdd1243dSDimitry Andric   switch (Reg) {
2323bdd1243dSDimitry Andric   case AMDGPU::SRC_SHARED_BASE_LO:
2324bdd1243dSDimitry Andric   case AMDGPU::SRC_SHARED_BASE:
2325bdd1243dSDimitry Andric   case AMDGPU::SRC_SHARED_LIMIT_LO:
2326bdd1243dSDimitry Andric   case AMDGPU::SRC_SHARED_LIMIT:
2327bdd1243dSDimitry Andric   case AMDGPU::SRC_PRIVATE_BASE_LO:
2328bdd1243dSDimitry Andric   case AMDGPU::SRC_PRIVATE_BASE:
2329bdd1243dSDimitry Andric   case AMDGPU::SRC_PRIVATE_LIMIT_LO:
2330bdd1243dSDimitry Andric   case AMDGPU::SRC_PRIVATE_LIMIT:
2331bdd1243dSDimitry Andric   case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
2332bdd1243dSDimitry Andric     return true;
2333bdd1243dSDimitry Andric   case AMDGPU::SRC_VCCZ:
2334bdd1243dSDimitry Andric   case AMDGPU::SRC_EXECZ:
2335bdd1243dSDimitry Andric   case AMDGPU::SRC_SCC:
2336bdd1243dSDimitry Andric     return true;
2337bdd1243dSDimitry Andric   case AMDGPU::SGPR_NULL:
2338bdd1243dSDimitry Andric     return true;
2339bdd1243dSDimitry Andric   default:
2340bdd1243dSDimitry Andric     return false;
2341bdd1243dSDimitry Andric   }
2342bdd1243dSDimitry Andric }
2343bdd1243dSDimitry Andric 
23440b57cec5SDimitry Andric #undef CASE_CI_VI
2345e8d8bef9SDimitry Andric #undef CASE_VI_GFX9PLUS
234681ad6265SDimitry Andric #undef CASE_GFXPRE11_GFX11PLUS
234781ad6265SDimitry Andric #undef CASE_GFXPRE11_GFX11PLUS_TO
23480b57cec5SDimitry Andric #undef MAP_REG2REG
23490b57cec5SDimitry Andric 
isSISrcOperand(const MCInstrDesc & Desc,unsigned OpNo)23500b57cec5SDimitry Andric bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo) {
23510b57cec5SDimitry Andric   assert(OpNo < Desc.NumOperands);
2352bdd1243dSDimitry Andric   unsigned OpType = Desc.operands()[OpNo].OperandType;
23530b57cec5SDimitry Andric   return OpType >= AMDGPU::OPERAND_SRC_FIRST &&
23540b57cec5SDimitry Andric          OpType <= AMDGPU::OPERAND_SRC_LAST;
23550b57cec5SDimitry Andric }
23560b57cec5SDimitry Andric 
isKImmOperand(const MCInstrDesc & Desc,unsigned OpNo)2357bdd1243dSDimitry Andric bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo) {
2358bdd1243dSDimitry Andric   assert(OpNo < Desc.NumOperands);
2359bdd1243dSDimitry Andric   unsigned OpType = Desc.operands()[OpNo].OperandType;
2360bdd1243dSDimitry Andric   return OpType >= AMDGPU::OPERAND_KIMM_FIRST &&
2361bdd1243dSDimitry Andric          OpType <= AMDGPU::OPERAND_KIMM_LAST;
2362bdd1243dSDimitry Andric }
2363bdd1243dSDimitry Andric 
isSISrcFPOperand(const MCInstrDesc & Desc,unsigned OpNo)23640b57cec5SDimitry Andric bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo) {
23650b57cec5SDimitry Andric   assert(OpNo < Desc.NumOperands);
2366bdd1243dSDimitry Andric   unsigned OpType = Desc.operands()[OpNo].OperandType;
23670b57cec5SDimitry Andric   switch (OpType) {
23680b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_FP32:
2369349cc55cSDimitry Andric   case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED:
23700b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_FP64:
23710b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_FP16:
2372349cc55cSDimitry Andric   case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED:
23730b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_V2FP16:
23740b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_FP32:
23750b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_FP64:
23760b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_FP16:
23770b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
23780b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
23790b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
23800b57cec5SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
2381fe6060f1SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_V2FP32:
2382fe6060f1SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_V2FP32:
2383fe6060f1SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
23840b57cec5SDimitry Andric     return true;
23850b57cec5SDimitry Andric   default:
23860b57cec5SDimitry Andric     return false;
23870b57cec5SDimitry Andric   }
23880b57cec5SDimitry Andric }
23890b57cec5SDimitry Andric 
isSISrcInlinableOperand(const MCInstrDesc & Desc,unsigned OpNo)23900b57cec5SDimitry Andric bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo) {
23910b57cec5SDimitry Andric   assert(OpNo < Desc.NumOperands);
2392bdd1243dSDimitry Andric   unsigned OpType = Desc.operands()[OpNo].OperandType;
23935f757f3fSDimitry Andric   return (OpType >= AMDGPU::OPERAND_REG_INLINE_C_FIRST &&
23945f757f3fSDimitry Andric           OpType <= AMDGPU::OPERAND_REG_INLINE_C_LAST) ||
23955f757f3fSDimitry Andric          (OpType >= AMDGPU::OPERAND_REG_INLINE_AC_FIRST &&
23965f757f3fSDimitry Andric           OpType <= AMDGPU::OPERAND_REG_INLINE_AC_LAST);
23970b57cec5SDimitry Andric }
23980b57cec5SDimitry Andric 
23990b57cec5SDimitry Andric // Avoid using MCRegisterClass::getSize, since that function will go away
24000b57cec5SDimitry Andric // (move from MC* level to Target* level). Return size in bits.
getRegBitWidth(unsigned RCID)24010b57cec5SDimitry Andric unsigned getRegBitWidth(unsigned RCID) {
24020b57cec5SDimitry Andric   switch (RCID) {
24035ffd83dbSDimitry Andric   case AMDGPU::SGPR_LO16RegClassID:
24045ffd83dbSDimitry Andric   case AMDGPU::AGPR_LO16RegClassID:
24055ffd83dbSDimitry Andric     return 16;
24060b57cec5SDimitry Andric   case AMDGPU::SGPR_32RegClassID:
24070b57cec5SDimitry Andric   case AMDGPU::VGPR_32RegClassID:
24080b57cec5SDimitry Andric   case AMDGPU::VRegOrLds_32RegClassID:
24090b57cec5SDimitry Andric   case AMDGPU::AGPR_32RegClassID:
24100b57cec5SDimitry Andric   case AMDGPU::VS_32RegClassID:
24110b57cec5SDimitry Andric   case AMDGPU::AV_32RegClassID:
24120b57cec5SDimitry Andric   case AMDGPU::SReg_32RegClassID:
24130b57cec5SDimitry Andric   case AMDGPU::SReg_32_XM0RegClassID:
24140b57cec5SDimitry Andric   case AMDGPU::SRegOrLds_32RegClassID:
24150b57cec5SDimitry Andric     return 32;
24160b57cec5SDimitry Andric   case AMDGPU::SGPR_64RegClassID:
24170b57cec5SDimitry Andric   case AMDGPU::VS_64RegClassID:
24180b57cec5SDimitry Andric   case AMDGPU::SReg_64RegClassID:
24190b57cec5SDimitry Andric   case AMDGPU::VReg_64RegClassID:
24200b57cec5SDimitry Andric   case AMDGPU::AReg_64RegClassID:
24210b57cec5SDimitry Andric   case AMDGPU::SReg_64_XEXECRegClassID:
2422fe6060f1SDimitry Andric   case AMDGPU::VReg_64_Align2RegClassID:
2423fe6060f1SDimitry Andric   case AMDGPU::AReg_64_Align2RegClassID:
24244824e7fdSDimitry Andric   case AMDGPU::AV_64RegClassID:
24254824e7fdSDimitry Andric   case AMDGPU::AV_64_Align2RegClassID:
24260b57cec5SDimitry Andric     return 64;
24270b57cec5SDimitry Andric   case AMDGPU::SGPR_96RegClassID:
24280b57cec5SDimitry Andric   case AMDGPU::SReg_96RegClassID:
24290b57cec5SDimitry Andric   case AMDGPU::VReg_96RegClassID:
24305ffd83dbSDimitry Andric   case AMDGPU::AReg_96RegClassID:
2431fe6060f1SDimitry Andric   case AMDGPU::VReg_96_Align2RegClassID:
2432fe6060f1SDimitry Andric   case AMDGPU::AReg_96_Align2RegClassID:
2433fe6060f1SDimitry Andric   case AMDGPU::AV_96RegClassID:
24344824e7fdSDimitry Andric   case AMDGPU::AV_96_Align2RegClassID:
24350b57cec5SDimitry Andric     return 96;
24360b57cec5SDimitry Andric   case AMDGPU::SGPR_128RegClassID:
24370b57cec5SDimitry Andric   case AMDGPU::SReg_128RegClassID:
24380b57cec5SDimitry Andric   case AMDGPU::VReg_128RegClassID:
24390b57cec5SDimitry Andric   case AMDGPU::AReg_128RegClassID:
2440fe6060f1SDimitry Andric   case AMDGPU::VReg_128_Align2RegClassID:
2441fe6060f1SDimitry Andric   case AMDGPU::AReg_128_Align2RegClassID:
2442fe6060f1SDimitry Andric   case AMDGPU::AV_128RegClassID:
24434824e7fdSDimitry Andric   case AMDGPU::AV_128_Align2RegClassID:
24440b57cec5SDimitry Andric     return 128;
24450b57cec5SDimitry Andric   case AMDGPU::SGPR_160RegClassID:
24460b57cec5SDimitry Andric   case AMDGPU::SReg_160RegClassID:
24470b57cec5SDimitry Andric   case AMDGPU::VReg_160RegClassID:
24485ffd83dbSDimitry Andric   case AMDGPU::AReg_160RegClassID:
2449fe6060f1SDimitry Andric   case AMDGPU::VReg_160_Align2RegClassID:
2450fe6060f1SDimitry Andric   case AMDGPU::AReg_160_Align2RegClassID:
2451fe6060f1SDimitry Andric   case AMDGPU::AV_160RegClassID:
24524824e7fdSDimitry Andric   case AMDGPU::AV_160_Align2RegClassID:
24530b57cec5SDimitry Andric     return 160;
24545ffd83dbSDimitry Andric   case AMDGPU::SGPR_192RegClassID:
24555ffd83dbSDimitry Andric   case AMDGPU::SReg_192RegClassID:
24565ffd83dbSDimitry Andric   case AMDGPU::VReg_192RegClassID:
24575ffd83dbSDimitry Andric   case AMDGPU::AReg_192RegClassID:
2458fe6060f1SDimitry Andric   case AMDGPU::VReg_192_Align2RegClassID:
2459fe6060f1SDimitry Andric   case AMDGPU::AReg_192_Align2RegClassID:
24604824e7fdSDimitry Andric   case AMDGPU::AV_192RegClassID:
24614824e7fdSDimitry Andric   case AMDGPU::AV_192_Align2RegClassID:
24625ffd83dbSDimitry Andric     return 192;
2463fe6060f1SDimitry Andric   case AMDGPU::SGPR_224RegClassID:
2464fe6060f1SDimitry Andric   case AMDGPU::SReg_224RegClassID:
2465fe6060f1SDimitry Andric   case AMDGPU::VReg_224RegClassID:
2466fe6060f1SDimitry Andric   case AMDGPU::AReg_224RegClassID:
2467fe6060f1SDimitry Andric   case AMDGPU::VReg_224_Align2RegClassID:
2468fe6060f1SDimitry Andric   case AMDGPU::AReg_224_Align2RegClassID:
24694824e7fdSDimitry Andric   case AMDGPU::AV_224RegClassID:
24704824e7fdSDimitry Andric   case AMDGPU::AV_224_Align2RegClassID:
2471fe6060f1SDimitry Andric     return 224;
24725ffd83dbSDimitry Andric   case AMDGPU::SGPR_256RegClassID:
24730b57cec5SDimitry Andric   case AMDGPU::SReg_256RegClassID:
24740b57cec5SDimitry Andric   case AMDGPU::VReg_256RegClassID:
24755ffd83dbSDimitry Andric   case AMDGPU::AReg_256RegClassID:
2476fe6060f1SDimitry Andric   case AMDGPU::VReg_256_Align2RegClassID:
2477fe6060f1SDimitry Andric   case AMDGPU::AReg_256_Align2RegClassID:
24784824e7fdSDimitry Andric   case AMDGPU::AV_256RegClassID:
24794824e7fdSDimitry Andric   case AMDGPU::AV_256_Align2RegClassID:
24800b57cec5SDimitry Andric     return 256;
2481bdd1243dSDimitry Andric   case AMDGPU::SGPR_288RegClassID:
2482bdd1243dSDimitry Andric   case AMDGPU::SReg_288RegClassID:
2483bdd1243dSDimitry Andric   case AMDGPU::VReg_288RegClassID:
2484bdd1243dSDimitry Andric   case AMDGPU::AReg_288RegClassID:
2485bdd1243dSDimitry Andric   case AMDGPU::VReg_288_Align2RegClassID:
2486bdd1243dSDimitry Andric   case AMDGPU::AReg_288_Align2RegClassID:
2487bdd1243dSDimitry Andric   case AMDGPU::AV_288RegClassID:
2488bdd1243dSDimitry Andric   case AMDGPU::AV_288_Align2RegClassID:
2489bdd1243dSDimitry Andric     return 288;
2490bdd1243dSDimitry Andric   case AMDGPU::SGPR_320RegClassID:
2491bdd1243dSDimitry Andric   case AMDGPU::SReg_320RegClassID:
2492bdd1243dSDimitry Andric   case AMDGPU::VReg_320RegClassID:
2493bdd1243dSDimitry Andric   case AMDGPU::AReg_320RegClassID:
2494bdd1243dSDimitry Andric   case AMDGPU::VReg_320_Align2RegClassID:
2495bdd1243dSDimitry Andric   case AMDGPU::AReg_320_Align2RegClassID:
2496bdd1243dSDimitry Andric   case AMDGPU::AV_320RegClassID:
2497bdd1243dSDimitry Andric   case AMDGPU::AV_320_Align2RegClassID:
2498bdd1243dSDimitry Andric     return 320;
2499bdd1243dSDimitry Andric   case AMDGPU::SGPR_352RegClassID:
2500bdd1243dSDimitry Andric   case AMDGPU::SReg_352RegClassID:
2501bdd1243dSDimitry Andric   case AMDGPU::VReg_352RegClassID:
2502bdd1243dSDimitry Andric   case AMDGPU::AReg_352RegClassID:
2503bdd1243dSDimitry Andric   case AMDGPU::VReg_352_Align2RegClassID:
2504bdd1243dSDimitry Andric   case AMDGPU::AReg_352_Align2RegClassID:
2505bdd1243dSDimitry Andric   case AMDGPU::AV_352RegClassID:
2506bdd1243dSDimitry Andric   case AMDGPU::AV_352_Align2RegClassID:
2507bdd1243dSDimitry Andric     return 352;
2508bdd1243dSDimitry Andric   case AMDGPU::SGPR_384RegClassID:
2509bdd1243dSDimitry Andric   case AMDGPU::SReg_384RegClassID:
2510bdd1243dSDimitry Andric   case AMDGPU::VReg_384RegClassID:
2511bdd1243dSDimitry Andric   case AMDGPU::AReg_384RegClassID:
2512bdd1243dSDimitry Andric   case AMDGPU::VReg_384_Align2RegClassID:
2513bdd1243dSDimitry Andric   case AMDGPU::AReg_384_Align2RegClassID:
2514bdd1243dSDimitry Andric   case AMDGPU::AV_384RegClassID:
2515bdd1243dSDimitry Andric   case AMDGPU::AV_384_Align2RegClassID:
2516bdd1243dSDimitry Andric     return 384;
25175ffd83dbSDimitry Andric   case AMDGPU::SGPR_512RegClassID:
25180b57cec5SDimitry Andric   case AMDGPU::SReg_512RegClassID:
25190b57cec5SDimitry Andric   case AMDGPU::VReg_512RegClassID:
25200b57cec5SDimitry Andric   case AMDGPU::AReg_512RegClassID:
2521fe6060f1SDimitry Andric   case AMDGPU::VReg_512_Align2RegClassID:
2522fe6060f1SDimitry Andric   case AMDGPU::AReg_512_Align2RegClassID:
25234824e7fdSDimitry Andric   case AMDGPU::AV_512RegClassID:
25244824e7fdSDimitry Andric   case AMDGPU::AV_512_Align2RegClassID:
25250b57cec5SDimitry Andric     return 512;
25265ffd83dbSDimitry Andric   case AMDGPU::SGPR_1024RegClassID:
25270b57cec5SDimitry Andric   case AMDGPU::SReg_1024RegClassID:
25280b57cec5SDimitry Andric   case AMDGPU::VReg_1024RegClassID:
25290b57cec5SDimitry Andric   case AMDGPU::AReg_1024RegClassID:
2530fe6060f1SDimitry Andric   case AMDGPU::VReg_1024_Align2RegClassID:
2531fe6060f1SDimitry Andric   case AMDGPU::AReg_1024_Align2RegClassID:
25324824e7fdSDimitry Andric   case AMDGPU::AV_1024RegClassID:
25334824e7fdSDimitry Andric   case AMDGPU::AV_1024_Align2RegClassID:
25340b57cec5SDimitry Andric     return 1024;
25350b57cec5SDimitry Andric   default:
25360b57cec5SDimitry Andric     llvm_unreachable("Unexpected register class");
25370b57cec5SDimitry Andric   }
25380b57cec5SDimitry Andric }
25390b57cec5SDimitry Andric 
getRegBitWidth(const MCRegisterClass & RC)25400b57cec5SDimitry Andric unsigned getRegBitWidth(const MCRegisterClass &RC) {
25410b57cec5SDimitry Andric   return getRegBitWidth(RC.getID());
25420b57cec5SDimitry Andric }
25430b57cec5SDimitry Andric 
getRegOperandSize(const MCRegisterInfo * MRI,const MCInstrDesc & Desc,unsigned OpNo)25440b57cec5SDimitry Andric unsigned getRegOperandSize(const MCRegisterInfo *MRI, const MCInstrDesc &Desc,
25450b57cec5SDimitry Andric                            unsigned OpNo) {
25460b57cec5SDimitry Andric   assert(OpNo < Desc.NumOperands);
2547bdd1243dSDimitry Andric   unsigned RCID = Desc.operands()[OpNo].RegClass;
254806c3fb27SDimitry Andric   return getRegBitWidth(RCID) / 8;
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric 
isInlinableLiteral64(int64_t Literal,bool HasInv2Pi)25510b57cec5SDimitry Andric bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi) {
25525ffd83dbSDimitry Andric   if (isInlinableIntLiteral(Literal))
25530b57cec5SDimitry Andric     return true;
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric   uint64_t Val = static_cast<uint64_t>(Literal);
255606c3fb27SDimitry Andric   return (Val == llvm::bit_cast<uint64_t>(0.0)) ||
255706c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(1.0)) ||
255806c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(-1.0)) ||
255906c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(0.5)) ||
256006c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(-0.5)) ||
256106c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(2.0)) ||
256206c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(-2.0)) ||
256306c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(4.0)) ||
256406c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint64_t>(-4.0)) ||
25650b57cec5SDimitry Andric          (Val == 0x3fc45f306dc9c882 && HasInv2Pi);
25660b57cec5SDimitry Andric }
25670b57cec5SDimitry Andric 
isInlinableLiteral32(int32_t Literal,bool HasInv2Pi)25680b57cec5SDimitry Andric bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi) {
25695ffd83dbSDimitry Andric   if (isInlinableIntLiteral(Literal))
25700b57cec5SDimitry Andric     return true;
25710b57cec5SDimitry Andric 
25720b57cec5SDimitry Andric   // The actual type of the operand does not seem to matter as long
25730b57cec5SDimitry Andric   // as the bits match one of the inline immediate values.  For example:
25740b57cec5SDimitry Andric   //
25750b57cec5SDimitry Andric   // -nan has the hexadecimal encoding of 0xfffffffe which is -2 in decimal,
25760b57cec5SDimitry Andric   // so it is a legal inline immediate.
25770b57cec5SDimitry Andric   //
25780b57cec5SDimitry Andric   // 1065353216 has the hexadecimal encoding 0x3f800000 which is 1.0f in
25790b57cec5SDimitry Andric   // floating-point, so it is a legal inline immediate.
25800b57cec5SDimitry Andric 
25810b57cec5SDimitry Andric   uint32_t Val = static_cast<uint32_t>(Literal);
258206c3fb27SDimitry Andric   return (Val == llvm::bit_cast<uint32_t>(0.0f)) ||
258306c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(1.0f)) ||
258406c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(-1.0f)) ||
258506c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(0.5f)) ||
258606c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(-0.5f)) ||
258706c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(2.0f)) ||
258806c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(-2.0f)) ||
258906c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(4.0f)) ||
259006c3fb27SDimitry Andric          (Val == llvm::bit_cast<uint32_t>(-4.0f)) ||
25910b57cec5SDimitry Andric          (Val == 0x3e22f983 && HasInv2Pi);
25920b57cec5SDimitry Andric }
25930b57cec5SDimitry Andric 
isInlinableLiteralBF16(int16_t Literal,bool HasInv2Pi)2594*0fca6ea1SDimitry Andric bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi) {
25950b57cec5SDimitry Andric   if (!HasInv2Pi)
25960b57cec5SDimitry Andric     return false;
25975ffd83dbSDimitry Andric   if (isInlinableIntLiteral(Literal))
25980b57cec5SDimitry Andric     return true;
2599*0fca6ea1SDimitry Andric   uint16_t Val = static_cast<uint16_t>(Literal);
2600*0fca6ea1SDimitry Andric   return Val == 0x3F00 || // 0.5
2601*0fca6ea1SDimitry Andric          Val == 0xBF00 || // -0.5
2602*0fca6ea1SDimitry Andric          Val == 0x3F80 || // 1.0
2603*0fca6ea1SDimitry Andric          Val == 0xBF80 || // -1.0
2604*0fca6ea1SDimitry Andric          Val == 0x4000 || // 2.0
2605*0fca6ea1SDimitry Andric          Val == 0xC000 || // -2.0
2606*0fca6ea1SDimitry Andric          Val == 0x4080 || // 4.0
2607*0fca6ea1SDimitry Andric          Val == 0xC080 || // -4.0
2608*0fca6ea1SDimitry Andric          Val == 0x3E22;   // 1.0 / (2.0 * pi)
2609*0fca6ea1SDimitry Andric }
26100b57cec5SDimitry Andric 
isInlinableLiteralI16(int32_t Literal,bool HasInv2Pi)2611*0fca6ea1SDimitry Andric bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi) {
2612*0fca6ea1SDimitry Andric   return isInlinableLiteral32(Literal, HasInv2Pi);
2613*0fca6ea1SDimitry Andric }
2614*0fca6ea1SDimitry Andric 
isInlinableLiteralFP16(int16_t Literal,bool HasInv2Pi)2615*0fca6ea1SDimitry Andric bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi) {
2616*0fca6ea1SDimitry Andric   if (!HasInv2Pi)
2617*0fca6ea1SDimitry Andric     return false;
2618*0fca6ea1SDimitry Andric   if (isInlinableIntLiteral(Literal))
2619*0fca6ea1SDimitry Andric     return true;
26200b57cec5SDimitry Andric   uint16_t Val = static_cast<uint16_t>(Literal);
26210b57cec5SDimitry Andric   return Val == 0x3C00 || // 1.0
26220b57cec5SDimitry Andric          Val == 0xBC00 || // -1.0
26230b57cec5SDimitry Andric          Val == 0x3800 || // 0.5
26240b57cec5SDimitry Andric          Val == 0xB800 || // -0.5
26250b57cec5SDimitry Andric          Val == 0x4000 || // 2.0
26260b57cec5SDimitry Andric          Val == 0xC000 || // -2.0
26270b57cec5SDimitry Andric          Val == 0x4400 || // 4.0
26280b57cec5SDimitry Andric          Val == 0xC400 || // -4.0
26290b57cec5SDimitry Andric          Val == 0x3118;   // 1/2pi
26300b57cec5SDimitry Andric }
26310b57cec5SDimitry Andric 
getInlineEncodingV216(bool IsFloat,uint32_t Literal)26321db9f3b2SDimitry Andric std::optional<unsigned> getInlineEncodingV216(bool IsFloat, uint32_t Literal) {
26331db9f3b2SDimitry Andric   // Unfortunately, the Instruction Set Architecture Reference Guide is
26341db9f3b2SDimitry Andric   // misleading about how the inline operands work for (packed) 16-bit
26351db9f3b2SDimitry Andric   // instructions. In a nutshell, the actual HW behavior is:
26361db9f3b2SDimitry Andric   //
26371db9f3b2SDimitry Andric   //  - integer encodings (-16 .. 64) are always produced as sign-extended
26381db9f3b2SDimitry Andric   //    32-bit values
26391db9f3b2SDimitry Andric   //  - float encodings are produced as:
26401db9f3b2SDimitry Andric   //    - for F16 instructions: corresponding half-precision float values in
26411db9f3b2SDimitry Andric   //      the LSBs, 0 in the MSBs
26421db9f3b2SDimitry Andric   //    - for UI16 instructions: corresponding single-precision float value
26431db9f3b2SDimitry Andric   int32_t Signed = static_cast<int32_t>(Literal);
26441db9f3b2SDimitry Andric   if (Signed >= 0 && Signed <= 64)
26451db9f3b2SDimitry Andric     return 128 + Signed;
26460b57cec5SDimitry Andric 
26471db9f3b2SDimitry Andric   if (Signed >= -16 && Signed <= -1)
26481db9f3b2SDimitry Andric     return 192 + std::abs(Signed);
26491db9f3b2SDimitry Andric 
26501db9f3b2SDimitry Andric   if (IsFloat) {
26511db9f3b2SDimitry Andric     // clang-format off
26521db9f3b2SDimitry Andric     switch (Literal) {
26531db9f3b2SDimitry Andric     case 0x3800: return 240; // 0.5
26541db9f3b2SDimitry Andric     case 0xB800: return 241; // -0.5
26551db9f3b2SDimitry Andric     case 0x3C00: return 242; // 1.0
26561db9f3b2SDimitry Andric     case 0xBC00: return 243; // -1.0
26571db9f3b2SDimitry Andric     case 0x4000: return 244; // 2.0
26581db9f3b2SDimitry Andric     case 0xC000: return 245; // -2.0
26591db9f3b2SDimitry Andric     case 0x4400: return 246; // 4.0
26601db9f3b2SDimitry Andric     case 0xC400: return 247; // -4.0
26611db9f3b2SDimitry Andric     case 0x3118: return 248; // 1.0 / (2.0 * pi)
26621db9f3b2SDimitry Andric     default: break;
26630b57cec5SDimitry Andric     }
26641db9f3b2SDimitry Andric     // clang-format on
26651db9f3b2SDimitry Andric   } else {
26661db9f3b2SDimitry Andric     // clang-format off
26671db9f3b2SDimitry Andric     switch (Literal) {
26681db9f3b2SDimitry Andric     case 0x3F000000: return 240; // 0.5
26691db9f3b2SDimitry Andric     case 0xBF000000: return 241; // -0.5
26701db9f3b2SDimitry Andric     case 0x3F800000: return 242; // 1.0
26711db9f3b2SDimitry Andric     case 0xBF800000: return 243; // -1.0
26721db9f3b2SDimitry Andric     case 0x40000000: return 244; // 2.0
26731db9f3b2SDimitry Andric     case 0xC0000000: return 245; // -2.0
26741db9f3b2SDimitry Andric     case 0x40800000: return 246; // 4.0
26751db9f3b2SDimitry Andric     case 0xC0800000: return 247; // -4.0
26761db9f3b2SDimitry Andric     case 0x3E22F983: return 248; // 1.0 / (2.0 * pi)
26771db9f3b2SDimitry Andric     default: break;
26781db9f3b2SDimitry Andric     }
26791db9f3b2SDimitry Andric     // clang-format on
26800b57cec5SDimitry Andric   }
26810b57cec5SDimitry Andric 
26821db9f3b2SDimitry Andric   return {};
26835ffd83dbSDimitry Andric }
26845ffd83dbSDimitry Andric 
26851db9f3b2SDimitry Andric // Encoding of the literal as an inline constant for a V_PK_*_IU16 instruction
26861db9f3b2SDimitry Andric // or nullopt.
getInlineEncodingV2I16(uint32_t Literal)26871db9f3b2SDimitry Andric std::optional<unsigned> getInlineEncodingV2I16(uint32_t Literal) {
26881db9f3b2SDimitry Andric   return getInlineEncodingV216(false, Literal);
26891db9f3b2SDimitry Andric }
26901db9f3b2SDimitry Andric 
2691*0fca6ea1SDimitry Andric // Encoding of the literal as an inline constant for a V_PK_*_BF16 instruction
2692*0fca6ea1SDimitry Andric // or nullopt.
getInlineEncodingV2BF16(uint32_t Literal)2693*0fca6ea1SDimitry Andric std::optional<unsigned> getInlineEncodingV2BF16(uint32_t Literal) {
2694*0fca6ea1SDimitry Andric   int32_t Signed = static_cast<int32_t>(Literal);
2695*0fca6ea1SDimitry Andric   if (Signed >= 0 && Signed <= 64)
2696*0fca6ea1SDimitry Andric     return 128 + Signed;
2697*0fca6ea1SDimitry Andric 
2698*0fca6ea1SDimitry Andric   if (Signed >= -16 && Signed <= -1)
2699*0fca6ea1SDimitry Andric     return 192 + std::abs(Signed);
2700*0fca6ea1SDimitry Andric 
2701*0fca6ea1SDimitry Andric   // clang-format off
2702*0fca6ea1SDimitry Andric   switch (Literal) {
2703*0fca6ea1SDimitry Andric   case 0x3F00: return 240; // 0.5
2704*0fca6ea1SDimitry Andric   case 0xBF00: return 241; // -0.5
2705*0fca6ea1SDimitry Andric   case 0x3F80: return 242; // 1.0
2706*0fca6ea1SDimitry Andric   case 0xBF80: return 243; // -1.0
2707*0fca6ea1SDimitry Andric   case 0x4000: return 244; // 2.0
2708*0fca6ea1SDimitry Andric   case 0xC000: return 245; // -2.0
2709*0fca6ea1SDimitry Andric   case 0x4080: return 246; // 4.0
2710*0fca6ea1SDimitry Andric   case 0xC080: return 247; // -4.0
2711*0fca6ea1SDimitry Andric   case 0x3E22: return 248; // 1.0 / (2.0 * pi)
2712*0fca6ea1SDimitry Andric   default: break;
2713*0fca6ea1SDimitry Andric   }
2714*0fca6ea1SDimitry Andric   // clang-format on
2715*0fca6ea1SDimitry Andric 
2716*0fca6ea1SDimitry Andric   return std::nullopt;
2717*0fca6ea1SDimitry Andric }
2718*0fca6ea1SDimitry Andric 
27191db9f3b2SDimitry Andric // Encoding of the literal as an inline constant for a V_PK_*_F16 instruction
27201db9f3b2SDimitry Andric // or nullopt.
getInlineEncodingV2F16(uint32_t Literal)27211db9f3b2SDimitry Andric std::optional<unsigned> getInlineEncodingV2F16(uint32_t Literal) {
27221db9f3b2SDimitry Andric   return getInlineEncodingV216(true, Literal);
27231db9f3b2SDimitry Andric }
27241db9f3b2SDimitry Andric 
27251db9f3b2SDimitry Andric // Whether the given literal can be inlined for a V_PK_* instruction.
isInlinableLiteralV216(uint32_t Literal,uint8_t OpType)27261db9f3b2SDimitry Andric bool isInlinableLiteralV216(uint32_t Literal, uint8_t OpType) {
27275f757f3fSDimitry Andric   switch (OpType) {
27281db9f3b2SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_V2INT16:
27291db9f3b2SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
27301db9f3b2SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
27311db9f3b2SDimitry Andric     return getInlineEncodingV216(false, Literal).has_value();
27325f757f3fSDimitry Andric   case AMDGPU::OPERAND_REG_IMM_V2FP16:
27335f757f3fSDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
27341db9f3b2SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
27351db9f3b2SDimitry Andric     return getInlineEncodingV216(true, Literal).has_value();
2736*0fca6ea1SDimitry Andric   case AMDGPU::OPERAND_REG_IMM_V2BF16:
2737*0fca6ea1SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
2738*0fca6ea1SDimitry Andric   case AMDGPU::OPERAND_REG_INLINE_AC_V2BF16:
2739*0fca6ea1SDimitry Andric     return isInlinableLiteralV2BF16(Literal);
27405f757f3fSDimitry Andric   default:
27411db9f3b2SDimitry Andric     llvm_unreachable("bad packed operand type");
27425f757f3fSDimitry Andric   }
27435f757f3fSDimitry Andric }
27445f757f3fSDimitry Andric 
27451db9f3b2SDimitry Andric // Whether the given literal can be inlined for a V_PK_*_IU16 instruction.
isInlinableLiteralV2I16(uint32_t Literal)27461db9f3b2SDimitry Andric bool isInlinableLiteralV2I16(uint32_t Literal) {
27471db9f3b2SDimitry Andric   return getInlineEncodingV2I16(Literal).has_value();
27481db9f3b2SDimitry Andric }
274916d6b3b3SDimitry Andric 
2750*0fca6ea1SDimitry Andric // Whether the given literal can be inlined for a V_PK_*_BF16 instruction.
isInlinableLiteralV2BF16(uint32_t Literal)2751*0fca6ea1SDimitry Andric bool isInlinableLiteralV2BF16(uint32_t Literal) {
2752*0fca6ea1SDimitry Andric   return getInlineEncodingV2BF16(Literal).has_value();
2753*0fca6ea1SDimitry Andric }
2754*0fca6ea1SDimitry Andric 
27551db9f3b2SDimitry Andric // Whether the given literal can be inlined for a V_PK_*_F16 instruction.
isInlinableLiteralV2F16(uint32_t Literal)27561db9f3b2SDimitry Andric bool isInlinableLiteralV2F16(uint32_t Literal) {
27571db9f3b2SDimitry Andric   return getInlineEncodingV2F16(Literal).has_value();
275816d6b3b3SDimitry Andric }
275916d6b3b3SDimitry Andric 
isValid32BitLiteral(uint64_t Val,bool IsFP64)27605f757f3fSDimitry Andric bool isValid32BitLiteral(uint64_t Val, bool IsFP64) {
27615f757f3fSDimitry Andric   if (IsFP64)
27625f757f3fSDimitry Andric     return !(Val & 0xffffffffu);
27635f757f3fSDimitry Andric 
27645f757f3fSDimitry Andric   return isUInt<32>(Val) || isInt<32>(Val);
27655f757f3fSDimitry Andric }
27665f757f3fSDimitry Andric 
isArgPassedInSGPR(const Argument * A)27670b57cec5SDimitry Andric bool isArgPassedInSGPR(const Argument *A) {
27680b57cec5SDimitry Andric   const Function *F = A->getParent();
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric   // Arguments to compute shaders are never a source of divergence.
27710b57cec5SDimitry Andric   CallingConv::ID CC = F->getCallingConv();
27720b57cec5SDimitry Andric   switch (CC) {
27730b57cec5SDimitry Andric   case CallingConv::AMDGPU_KERNEL:
27740b57cec5SDimitry Andric   case CallingConv::SPIR_KERNEL:
27750b57cec5SDimitry Andric     return true;
27760b57cec5SDimitry Andric   case CallingConv::AMDGPU_VS:
27770b57cec5SDimitry Andric   case CallingConv::AMDGPU_LS:
27780b57cec5SDimitry Andric   case CallingConv::AMDGPU_HS:
27790b57cec5SDimitry Andric   case CallingConv::AMDGPU_ES:
27800b57cec5SDimitry Andric   case CallingConv::AMDGPU_GS:
27810b57cec5SDimitry Andric   case CallingConv::AMDGPU_PS:
27820b57cec5SDimitry Andric   case CallingConv::AMDGPU_CS:
2783e8d8bef9SDimitry Andric   case CallingConv::AMDGPU_Gfx:
27845f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_Chain:
27855f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_ChainPreserve:
278606c3fb27SDimitry Andric     // For non-compute shaders, SGPR inputs are marked with either inreg or
278706c3fb27SDimitry Andric     // byval. Everything else is in VGPRs.
278806c3fb27SDimitry Andric     return A->hasAttribute(Attribute::InReg) ||
278906c3fb27SDimitry Andric            A->hasAttribute(Attribute::ByVal);
279006c3fb27SDimitry Andric   default:
27915f757f3fSDimitry Andric     // TODO: treat i1 as divergent?
27925f757f3fSDimitry Andric     return A->hasAttribute(Attribute::InReg);
279306c3fb27SDimitry Andric   }
279406c3fb27SDimitry Andric }
279506c3fb27SDimitry Andric 
isArgPassedInSGPR(const CallBase * CB,unsigned ArgNo)279606c3fb27SDimitry Andric bool isArgPassedInSGPR(const CallBase *CB, unsigned ArgNo) {
279706c3fb27SDimitry Andric   // Arguments to compute shaders are never a source of divergence.
279806c3fb27SDimitry Andric   CallingConv::ID CC = CB->getCallingConv();
279906c3fb27SDimitry Andric   switch (CC) {
280006c3fb27SDimitry Andric   case CallingConv::AMDGPU_KERNEL:
280106c3fb27SDimitry Andric   case CallingConv::SPIR_KERNEL:
280206c3fb27SDimitry Andric     return true;
280306c3fb27SDimitry Andric   case CallingConv::AMDGPU_VS:
280406c3fb27SDimitry Andric   case CallingConv::AMDGPU_LS:
280506c3fb27SDimitry Andric   case CallingConv::AMDGPU_HS:
280606c3fb27SDimitry Andric   case CallingConv::AMDGPU_ES:
280706c3fb27SDimitry Andric   case CallingConv::AMDGPU_GS:
280806c3fb27SDimitry Andric   case CallingConv::AMDGPU_PS:
280906c3fb27SDimitry Andric   case CallingConv::AMDGPU_CS:
281006c3fb27SDimitry Andric   case CallingConv::AMDGPU_Gfx:
28115f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_Chain:
28125f757f3fSDimitry Andric   case CallingConv::AMDGPU_CS_ChainPreserve:
281306c3fb27SDimitry Andric     // For non-compute shaders, SGPR inputs are marked with either inreg or
281406c3fb27SDimitry Andric     // byval. Everything else is in VGPRs.
281506c3fb27SDimitry Andric     return CB->paramHasAttr(ArgNo, Attribute::InReg) ||
281606c3fb27SDimitry Andric            CB->paramHasAttr(ArgNo, Attribute::ByVal);
28170b57cec5SDimitry Andric   default:
28185f757f3fSDimitry Andric     return CB->paramHasAttr(ArgNo, Attribute::InReg);
28190b57cec5SDimitry Andric   }
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
hasSMEMByteOffset(const MCSubtargetInfo & ST)28220b57cec5SDimitry Andric static bool hasSMEMByteOffset(const MCSubtargetInfo &ST) {
2823e8d8bef9SDimitry Andric   return isGCN3Encoding(ST) || isGFX10Plus(ST);
28240b57cec5SDimitry Andric }
28250b57cec5SDimitry Andric 
isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo & ST,int64_t EncodedOffset)28265ffd83dbSDimitry Andric bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST,
28275ffd83dbSDimitry Andric                                       int64_t EncodedOffset) {
28285f757f3fSDimitry Andric   if (isGFX12Plus(ST))
28295f757f3fSDimitry Andric     return isUInt<23>(EncodedOffset);
28305f757f3fSDimitry Andric 
28315ffd83dbSDimitry Andric   return hasSMEMByteOffset(ST) ? isUInt<20>(EncodedOffset)
28325ffd83dbSDimitry Andric                                : isUInt<8>(EncodedOffset);
28335ffd83dbSDimitry Andric }
28345ffd83dbSDimitry Andric 
isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo & ST,int64_t EncodedOffset,bool IsBuffer)28355ffd83dbSDimitry Andric bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST,
28365ffd83dbSDimitry Andric                                     int64_t EncodedOffset,
28375ffd83dbSDimitry Andric                                     bool IsBuffer) {
28385f757f3fSDimitry Andric   if (isGFX12Plus(ST))
28395f757f3fSDimitry Andric     return isInt<24>(EncodedOffset);
28405f757f3fSDimitry Andric 
28415ffd83dbSDimitry Andric   return !IsBuffer &&
28425ffd83dbSDimitry Andric          hasSMRDSignedImmOffset(ST) &&
28435ffd83dbSDimitry Andric          isInt<21>(EncodedOffset);
28445ffd83dbSDimitry Andric }
28455ffd83dbSDimitry Andric 
isDwordAligned(uint64_t ByteOffset)28465ffd83dbSDimitry Andric static bool isDwordAligned(uint64_t ByteOffset) {
28475ffd83dbSDimitry Andric   return (ByteOffset & 3) == 0;
28485ffd83dbSDimitry Andric }
28495ffd83dbSDimitry Andric 
convertSMRDOffsetUnits(const MCSubtargetInfo & ST,uint64_t ByteOffset)28505ffd83dbSDimitry Andric uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST,
28515ffd83dbSDimitry Andric                                 uint64_t ByteOffset) {
28520b57cec5SDimitry Andric   if (hasSMEMByteOffset(ST))
28530b57cec5SDimitry Andric     return ByteOffset;
28545ffd83dbSDimitry Andric 
28555ffd83dbSDimitry Andric   assert(isDwordAligned(ByteOffset));
28560b57cec5SDimitry Andric   return ByteOffset >> 2;
28570b57cec5SDimitry Andric }
28580b57cec5SDimitry Andric 
getSMRDEncodedOffset(const MCSubtargetInfo & ST,int64_t ByteOffset,bool IsBuffer,bool HasSOffset)2859bdd1243dSDimitry Andric std::optional<int64_t> getSMRDEncodedOffset(const MCSubtargetInfo &ST,
2860*0fca6ea1SDimitry Andric                                             int64_t ByteOffset, bool IsBuffer,
2861*0fca6ea1SDimitry Andric                                             bool HasSOffset) {
2862*0fca6ea1SDimitry Andric   // For unbuffered smem loads, it is illegal for the Immediate Offset to be
2863*0fca6ea1SDimitry Andric   // negative if the resulting (Offset + (M0 or SOffset or zero) is negative.
2864*0fca6ea1SDimitry Andric   // Handle case where SOffset is not present.
2865*0fca6ea1SDimitry Andric   if (!IsBuffer && !HasSOffset && ByteOffset < 0 && hasSMRDSignedImmOffset(ST))
2866*0fca6ea1SDimitry Andric     return std::nullopt;
2867*0fca6ea1SDimitry Andric 
28685f757f3fSDimitry Andric   if (isGFX12Plus(ST)) // 24 bit signed offsets
28695f757f3fSDimitry Andric     return isInt<24>(ByteOffset) ? std::optional<int64_t>(ByteOffset)
28705f757f3fSDimitry Andric                                  : std::nullopt;
28715f757f3fSDimitry Andric 
28725ffd83dbSDimitry Andric   // The signed version is always a byte offset.
28735ffd83dbSDimitry Andric   if (!IsBuffer && hasSMRDSignedImmOffset(ST)) {
28745ffd83dbSDimitry Andric     assert(hasSMEMByteOffset(ST));
2875bdd1243dSDimitry Andric     return isInt<20>(ByteOffset) ? std::optional<int64_t>(ByteOffset)
2876bdd1243dSDimitry Andric                                  : std::nullopt;
28775ffd83dbSDimitry Andric   }
28785ffd83dbSDimitry Andric 
28795ffd83dbSDimitry Andric   if (!isDwordAligned(ByteOffset) && !hasSMEMByteOffset(ST))
2880bdd1243dSDimitry Andric     return std::nullopt;
28815ffd83dbSDimitry Andric 
28825ffd83dbSDimitry Andric   int64_t EncodedOffset = convertSMRDOffsetUnits(ST, ByteOffset);
28835ffd83dbSDimitry Andric   return isLegalSMRDEncodedUnsignedOffset(ST, EncodedOffset)
2884bdd1243dSDimitry Andric              ? std::optional<int64_t>(EncodedOffset)
2885bdd1243dSDimitry Andric              : std::nullopt;
28865ffd83dbSDimitry Andric }
28875ffd83dbSDimitry Andric 
getSMRDEncodedLiteralOffset32(const MCSubtargetInfo & ST,int64_t ByteOffset)2888bdd1243dSDimitry Andric std::optional<int64_t> getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST,
28895ffd83dbSDimitry Andric                                                      int64_t ByteOffset) {
28905ffd83dbSDimitry Andric   if (!isCI(ST) || !isDwordAligned(ByteOffset))
2891bdd1243dSDimitry Andric     return std::nullopt;
28925ffd83dbSDimitry Andric 
28935ffd83dbSDimitry Andric   int64_t EncodedOffset = convertSMRDOffsetUnits(ST, ByteOffset);
2894bdd1243dSDimitry Andric   return isUInt<32>(EncodedOffset) ? std::optional<int64_t>(EncodedOffset)
2895bdd1243dSDimitry Andric                                    : std::nullopt;
28960b57cec5SDimitry Andric }
28970b57cec5SDimitry Andric 
getNumFlatOffsetBits(const MCSubtargetInfo & ST)2898bdd1243dSDimitry Andric unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST) {
2899e8d8bef9SDimitry Andric   if (AMDGPU::isGFX10(ST))
2900bdd1243dSDimitry Andric     return 12;
2901e8d8bef9SDimitry Andric 
29025f757f3fSDimitry Andric   if (AMDGPU::isGFX12(ST))
29035f757f3fSDimitry Andric     return 24;
2904bdd1243dSDimitry Andric   return 13;
2905e8d8bef9SDimitry Andric }
2906e8d8bef9SDimitry Andric 
29070b57cec5SDimitry Andric namespace {
29080b57cec5SDimitry Andric 
29090b57cec5SDimitry Andric struct SourceOfDivergence {
29100b57cec5SDimitry Andric   unsigned Intr;
29110b57cec5SDimitry Andric };
29120b57cec5SDimitry Andric const SourceOfDivergence *lookupSourceOfDivergence(unsigned Intr);
29130b57cec5SDimitry Andric 
291406c3fb27SDimitry Andric struct AlwaysUniform {
291506c3fb27SDimitry Andric   unsigned Intr;
291606c3fb27SDimitry Andric };
291706c3fb27SDimitry Andric const AlwaysUniform *lookupAlwaysUniform(unsigned Intr);
291806c3fb27SDimitry Andric 
29190b57cec5SDimitry Andric #define GET_SourcesOfDivergence_IMPL
292006c3fb27SDimitry Andric #define GET_UniformIntrinsics_IMPL
2921480093f4SDimitry Andric #define GET_Gfx9BufferFormat_IMPL
292281ad6265SDimitry Andric #define GET_Gfx10BufferFormat_IMPL
292381ad6265SDimitry Andric #define GET_Gfx11PlusBufferFormat_IMPL
29240b57cec5SDimitry Andric #include "AMDGPUGenSearchableTables.inc"
29250b57cec5SDimitry Andric 
29260b57cec5SDimitry Andric } // end anonymous namespace
29270b57cec5SDimitry Andric 
isIntrinsicSourceOfDivergence(unsigned IntrID)29280b57cec5SDimitry Andric bool isIntrinsicSourceOfDivergence(unsigned IntrID) {
29290b57cec5SDimitry Andric   return lookupSourceOfDivergence(IntrID);
29300b57cec5SDimitry Andric }
29310b57cec5SDimitry Andric 
isIntrinsicAlwaysUniform(unsigned IntrID)293206c3fb27SDimitry Andric bool isIntrinsicAlwaysUniform(unsigned IntrID) {
293306c3fb27SDimitry Andric   return lookupAlwaysUniform(IntrID);
293406c3fb27SDimitry Andric }
293506c3fb27SDimitry Andric 
getGcnBufferFormatInfo(uint8_t BitsPerComp,uint8_t NumComponents,uint8_t NumFormat,const MCSubtargetInfo & STI)2936480093f4SDimitry Andric const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t BitsPerComp,
2937480093f4SDimitry Andric                                                   uint8_t NumComponents,
2938480093f4SDimitry Andric                                                   uint8_t NumFormat,
2939480093f4SDimitry Andric                                                   const MCSubtargetInfo &STI) {
294081ad6265SDimitry Andric   return isGFX11Plus(STI)
294181ad6265SDimitry Andric              ? getGfx11PlusBufferFormatInfo(BitsPerComp, NumComponents,
2942480093f4SDimitry Andric                                             NumFormat)
294381ad6265SDimitry Andric              : isGFX10(STI) ? getGfx10BufferFormatInfo(BitsPerComp,
294481ad6265SDimitry Andric                                                        NumComponents, NumFormat)
294581ad6265SDimitry Andric                             : getGfx9BufferFormatInfo(BitsPerComp,
294681ad6265SDimitry Andric                                                       NumComponents, NumFormat);
2947480093f4SDimitry Andric }
2948480093f4SDimitry Andric 
getGcnBufferFormatInfo(uint8_t Format,const MCSubtargetInfo & STI)2949480093f4SDimitry Andric const GcnBufferFormatInfo *getGcnBufferFormatInfo(uint8_t Format,
2950480093f4SDimitry Andric                                                   const MCSubtargetInfo &STI) {
295181ad6265SDimitry Andric   return isGFX11Plus(STI) ? getGfx11PlusBufferFormatInfo(Format)
295281ad6265SDimitry Andric                           : isGFX10(STI) ? getGfx10BufferFormatInfo(Format)
2953480093f4SDimitry Andric                                          : getGfx9BufferFormatInfo(Format);
2954480093f4SDimitry Andric }
2955480093f4SDimitry Andric 
hasAny64BitVGPROperands(const MCInstrDesc & OpDesc)29565f757f3fSDimitry Andric bool hasAny64BitVGPROperands(const MCInstrDesc &OpDesc) {
29575f757f3fSDimitry Andric   for (auto OpName : { OpName::vdst, OpName::src0, OpName::src1,
29585f757f3fSDimitry Andric                        OpName::src2 }) {
29595f757f3fSDimitry Andric     int Idx = getNamedOperandIdx(OpDesc.getOpcode(), OpName);
29605f757f3fSDimitry Andric     if (Idx == -1)
29615f757f3fSDimitry Andric       continue;
29625f757f3fSDimitry Andric 
29635f757f3fSDimitry Andric     if (OpDesc.operands()[Idx].RegClass == AMDGPU::VReg_64RegClassID ||
29645f757f3fSDimitry Andric         OpDesc.operands()[Idx].RegClass == AMDGPU::VReg_64_Align2RegClassID)
29655f757f3fSDimitry Andric       return true;
29665f757f3fSDimitry Andric   }
29675f757f3fSDimitry Andric 
29685f757f3fSDimitry Andric   return false;
29695f757f3fSDimitry Andric }
29705f757f3fSDimitry Andric 
isDPALU_DPP(const MCInstrDesc & OpDesc)29715f757f3fSDimitry Andric bool isDPALU_DPP(const MCInstrDesc &OpDesc) {
29725f757f3fSDimitry Andric   return hasAny64BitVGPROperands(OpDesc);
29735f757f3fSDimitry Andric }
29745f757f3fSDimitry Andric 
getLdsDwGranularity(const MCSubtargetInfo & ST)2975*0fca6ea1SDimitry Andric unsigned getLdsDwGranularity(const MCSubtargetInfo &ST) {
2976*0fca6ea1SDimitry Andric   // Currently this is 128 for all subtargets
2977*0fca6ea1SDimitry Andric   return 128;
2978*0fca6ea1SDimitry Andric }
2979*0fca6ea1SDimitry Andric 
29800b57cec5SDimitry Andric } // namespace AMDGPU
2981e8d8bef9SDimitry Andric 
operator <<(raw_ostream & OS,const AMDGPU::IsaInfo::TargetIDSetting S)2982e8d8bef9SDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2983e8d8bef9SDimitry Andric                         const AMDGPU::IsaInfo::TargetIDSetting S) {
2984e8d8bef9SDimitry Andric   switch (S) {
2985e8d8bef9SDimitry Andric   case (AMDGPU::IsaInfo::TargetIDSetting::Unsupported):
2986e8d8bef9SDimitry Andric     OS << "Unsupported";
2987e8d8bef9SDimitry Andric     break;
2988e8d8bef9SDimitry Andric   case (AMDGPU::IsaInfo::TargetIDSetting::Any):
2989e8d8bef9SDimitry Andric     OS << "Any";
2990e8d8bef9SDimitry Andric     break;
2991e8d8bef9SDimitry Andric   case (AMDGPU::IsaInfo::TargetIDSetting::Off):
2992e8d8bef9SDimitry Andric     OS << "Off";
2993e8d8bef9SDimitry Andric     break;
2994e8d8bef9SDimitry Andric   case (AMDGPU::IsaInfo::TargetIDSetting::On):
2995e8d8bef9SDimitry Andric     OS << "On";
2996e8d8bef9SDimitry Andric     break;
2997e8d8bef9SDimitry Andric   }
2998e8d8bef9SDimitry Andric   return OS;
2999e8d8bef9SDimitry Andric }
3000e8d8bef9SDimitry Andric 
30010b57cec5SDimitry Andric } // namespace llvm
3002