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. 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. 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. 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). 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). 7081ad6265SDimitry Andric unsigned getVmcntBitWidthLo(unsigned VersionMajor) { 7181ad6265SDimitry Andric return VersionMajor >= 11 ? 6 : 4; 7281ad6265SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric /// \returns Expcnt bit shift. 7581ad6265SDimitry Andric unsigned getExpcntBitShift(unsigned VersionMajor) { 7681ad6265SDimitry Andric return VersionMajor >= 11 ? 0 : 4; 7781ad6265SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// \returns Expcnt bit width. 8081ad6265SDimitry Andric unsigned getExpcntBitWidth(unsigned VersionMajor) { return 3; } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /// \returns Lgkmcnt bit shift. 8381ad6265SDimitry Andric unsigned getLgkmcntBitShift(unsigned VersionMajor) { 8481ad6265SDimitry Andric return VersionMajor >= 11 ? 4 : 8; 8581ad6265SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /// \returns Lgkmcnt bit width. 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). 9381ad6265SDimitry Andric unsigned getVmcntBitShiftHi(unsigned VersionMajor) { return 14; } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric /// \returns Vmcnt bit width (higher bits). 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 1017a6dacacSDimitry Andric unsigned getLoadcntBitWidth(unsigned VersionMajor) { 1027a6dacacSDimitry Andric return VersionMajor >= 12 ? 6 : 0; 1037a6dacacSDimitry Andric } 1047a6dacacSDimitry Andric 1057a6dacacSDimitry Andric /// \returns Samplecnt bit width. 1067a6dacacSDimitry Andric unsigned getSamplecntBitWidth(unsigned VersionMajor) { 1077a6dacacSDimitry Andric return VersionMajor >= 12 ? 6 : 0; 1087a6dacacSDimitry Andric } 1097a6dacacSDimitry Andric 1107a6dacacSDimitry Andric /// \returns Bvhcnt bit width. 1117a6dacacSDimitry Andric unsigned getBvhcntBitWidth(unsigned VersionMajor) { 1127a6dacacSDimitry Andric return VersionMajor >= 12 ? 3 : 0; 1137a6dacacSDimitry Andric } 1147a6dacacSDimitry Andric 1157a6dacacSDimitry Andric /// \returns Dscnt bit width. 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. 1217a6dacacSDimitry Andric unsigned getDscntBitShift(unsigned VersionMajor) { return 0; } 1227a6dacacSDimitry Andric 1237a6dacacSDimitry Andric /// \returns Storecnt or Vscnt bit width, depending on VersionMajor. 1247a6dacacSDimitry Andric unsigned getStorecntBitWidth(unsigned VersionMajor) { 1257a6dacacSDimitry Andric return VersionMajor >= 10 ? 6 : 0; 1267a6dacacSDimitry Andric } 1277a6dacacSDimitry Andric 1287a6dacacSDimitry Andric /// \returns Kmcnt bit width. 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. 1347a6dacacSDimitry Andric unsigned getLoadcntStorecntBitShift(unsigned VersionMajor) { 1357a6dacacSDimitry Andric return VersionMajor >= 12 ? 8 : 0; 1367a6dacacSDimitry Andric } 1377a6dacacSDimitry Andric 13806c3fb27SDimitry Andric /// \returns VmVsrc bit width 13906c3fb27SDimitry Andric inline unsigned getVmVsrcBitWidth() { return 3; } 14006c3fb27SDimitry Andric 14106c3fb27SDimitry Andric /// \returns VmVsrc bit shift 14206c3fb27SDimitry Andric inline unsigned getVmVsrcBitShift() { return 2; } 14306c3fb27SDimitry Andric 14406c3fb27SDimitry Andric /// \returns VaVdst bit width 14506c3fb27SDimitry Andric inline unsigned getVaVdstBitWidth() { return 4; } 14606c3fb27SDimitry Andric 14706c3fb27SDimitry Andric /// \returns VaVdst bit shift 14806c3fb27SDimitry Andric inline unsigned getVaVdstBitShift() { return 12; } 14906c3fb27SDimitry Andric 15006c3fb27SDimitry Andric /// \returns SaSdst bit width 15106c3fb27SDimitry Andric inline unsigned getSaSdstBitWidth() { return 1; } 15206c3fb27SDimitry Andric 15306c3fb27SDimitry Andric /// \returns SaSdst bit shift 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. 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. 1695f757f3fSDimitry Andric bool isHsaAbi(const MCSubtargetInfo &STI) { 1705f757f3fSDimitry Andric return STI.getTargetTriple().getOS() == Triple::AMDHSA; 1715f757f3fSDimitry Andric } 1725f757f3fSDimitry Andric 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 1827a6dacacSDimitry Andric unsigned getDefaultAMDHSACodeObjectVersion() { 1837a6dacacSDimitry Andric return DefaultAMDHSACodeObjectVersion; 1847a6dacacSDimitry Andric } 1857a6dacacSDimitry Andric 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 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 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. 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 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 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 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 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 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 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 4228bcb0991SDimitry Andric int getMTBUFBaseOpcode(unsigned Opc) { 4238bcb0991SDimitry Andric const MTBUFInfo *Info = getMTBUFInfoFromOpcode(Opc); 4248bcb0991SDimitry Andric return Info ? Info->BaseOpcode : -1; 4258bcb0991SDimitry Andric } 4268bcb0991SDimitry Andric 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 4328bcb0991SDimitry Andric int getMTBUFElements(unsigned Opc) { 4338bcb0991SDimitry Andric const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc); 4348bcb0991SDimitry Andric return Info ? Info->elements : 0; 4358bcb0991SDimitry Andric } 4368bcb0991SDimitry Andric 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 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 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 4520b57cec5SDimitry Andric int getMUBUFBaseOpcode(unsigned Opc) { 4530b57cec5SDimitry Andric const MUBUFInfo *Info = getMUBUFInfoFromOpcode(Opc); 4540b57cec5SDimitry Andric return Info ? Info->BaseOpcode : -1; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 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 4628bcb0991SDimitry Andric int getMUBUFElements(unsigned Opc) { 4630b57cec5SDimitry Andric const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc); 4648bcb0991SDimitry Andric return Info ? Info->elements : 0; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 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 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 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 482fe6060f1SDimitry Andric bool getMUBUFIsBufferInv(unsigned Opc) { 483fe6060f1SDimitry Andric const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc); 484fe6060f1SDimitry Andric return Info ? Info->IsBufferInv : false; 485fe6060f1SDimitry Andric } 486fe6060f1SDimitry Andric 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 4925ffd83dbSDimitry Andric bool getSMEMIsBuffer(unsigned Opc) { 4935ffd83dbSDimitry Andric const SMInfo *Info = getSMEMOpcodeHelper(Opc); 4945ffd83dbSDimitry Andric return Info ? Info->IsBuffer : false; 4955ffd83dbSDimitry Andric } 4965ffd83dbSDimitry Andric 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 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 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 51281ad6265SDimitry Andric bool isVOPC64DPP(unsigned Opc) { 51381ad6265SDimitry Andric return isVOPC64DPPOpcodeHelper(Opc) || isVOPC64DPP8OpcodeHelper(Opc); 51481ad6265SDimitry Andric } 51581ad6265SDimitry Andric 516*0fca6ea1SDimitry Andric bool isVOPCAsmOnly(unsigned Opc) { return isVOPCAsmOnlyOpcodeHelper(Opc); } 517*0fca6ea1SDimitry Andric 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 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 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 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 543753f127fSDimitry Andric unsigned getVOPDOpcode(unsigned Opc) { 544753f127fSDimitry Andric const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc); 545753f127fSDimitry Andric return Info ? Info->VOPDOp : ~0u; 546753f127fSDimitry Andric } 547753f127fSDimitry Andric 548bdd1243dSDimitry Andric bool isVOPD(unsigned Opc) { 549bdd1243dSDimitry Andric return AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0X); 550bdd1243dSDimitry Andric } 551bdd1243dSDimitry Andric 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 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 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 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 617bdd1243dSDimitry Andric bool isTrue16Inst(unsigned Opc) { 618bdd1243dSDimitry Andric const VOPTrue16Info *Info = getTrue16OpcodeHelper(Opc); 619bdd1243dSDimitry Andric return Info ? Info->IsTrue16 : false; 620bdd1243dSDimitry Andric } 621bdd1243dSDimitry Andric 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 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 63281ad6265SDimitry Andric unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc) { 63381ad6265SDimitry Andric const WMMAOpcodeMappingInfo *Info = getWMMAMappingInfoFrom2AddrOpcode(Opc); 63481ad6265SDimitry Andric return Info ? Info->Opcode3Addr : ~0u; 63581ad6265SDimitry Andric } 63681ad6265SDimitry Andric 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. 6450b57cec5SDimitry Andric int getMCOpcode(uint16_t Opcode, unsigned Gen) { 6460b57cec5SDimitry Andric return getMCOpcodeGen(Opcode, static_cast<Subtarget>(Gen)); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 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 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 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 688bdd1243dSDimitry 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 702bdd1243dSDimitry 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. 729bdd1243dSDimitry 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 751bdd1243dSDimitry Andric VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY) { 752bdd1243dSDimitry Andric return VOPD::InstInfo(OpX, OpY); 753bdd1243dSDimitry Andric } 754bdd1243dSDimitry Andric 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 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 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 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 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 856fe6060f1SDimitry 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 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 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 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 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 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 9620b57cec5SDimitry Andric unsigned getMinWavesPerEU(const MCSubtargetInfo *STI) { 9630b57cec5SDimitry Andric return 1; 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 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 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 9810b57cec5SDimitry Andric unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo *STI) { 9820b57cec5SDimitry Andric return 1; 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric 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 9900b57cec5SDimitry Andric unsigned getWavesPerWorkGroup(const MCSubtargetInfo *STI, 9910b57cec5SDimitry Andric unsigned FlatWorkGroupSize) { 9925ffd83dbSDimitry Andric return divideCeil(FlatWorkGroupSize, getWavefrontSize(STI)); 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 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 10040b57cec5SDimitry Andric unsigned getSGPREncodingGranule(const MCSubtargetInfo *STI) { 10050b57cec5SDimitry Andric return 8; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 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 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 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 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 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 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 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 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 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 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 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 1144*0fca6ea1SDimitry Andric unsigned getAddressableNumArchVGPRs(const MCSubtargetInfo *STI) { return 256; } 1145*0fca6ea1SDimitry Andric 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 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 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 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 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 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 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 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 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 12770b57cec5SDimitry Andric bool isGroupSegment(const GlobalValue *GV) { 1278480093f4SDimitry Andric return GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS; 12790b57cec5SDimitry Andric } 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric bool isGlobalSegment(const GlobalValue *GV) { 1282480093f4SDimitry Andric return GV->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS; 12830b57cec5SDimitry Andric } 12840b57cec5SDimitry Andric 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 12910b57cec5SDimitry Andric bool shouldEmitConstantsToTextSection(const Triple &TT) { 1292e8d8bef9SDimitry Andric return TT.getArch() == Triple::r600; 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric 129506c3fb27SDimitry Andric std::pair<unsigned, unsigned> 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 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 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 13627a6dacacSDimitry Andric unsigned getLoadcntBitMask(const IsaVersion &Version) { 13637a6dacacSDimitry Andric return (1 << getLoadcntBitWidth(Version.Major)) - 1; 13647a6dacacSDimitry Andric } 13657a6dacacSDimitry Andric 13667a6dacacSDimitry Andric unsigned getSamplecntBitMask(const IsaVersion &Version) { 13677a6dacacSDimitry Andric return (1 << getSamplecntBitWidth(Version.Major)) - 1; 13687a6dacacSDimitry Andric } 13697a6dacacSDimitry Andric 13707a6dacacSDimitry Andric unsigned getBvhcntBitMask(const IsaVersion &Version) { 13717a6dacacSDimitry Andric return (1 << getBvhcntBitWidth(Version.Major)) - 1; 13727a6dacacSDimitry Andric } 13737a6dacacSDimitry Andric 13740b57cec5SDimitry Andric unsigned getExpcntBitMask(const IsaVersion &Version) { 137581ad6265SDimitry Andric return (1 << getExpcntBitWidth(Version.Major)) - 1; 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric unsigned getLgkmcntBitMask(const IsaVersion &Version) { 13790b57cec5SDimitry Andric return (1 << getLgkmcntBitWidth(Version.Major)) - 1; 13800b57cec5SDimitry Andric } 13810b57cec5SDimitry Andric 13827a6dacacSDimitry Andric unsigned getDscntBitMask(const IsaVersion &Version) { 13837a6dacacSDimitry Andric return (1 << getDscntBitWidth(Version.Major)) - 1; 13847a6dacacSDimitry Andric } 13857a6dacacSDimitry Andric 13867a6dacacSDimitry Andric unsigned getKmcntBitMask(const IsaVersion &Version) { 13877a6dacacSDimitry Andric return (1 << getKmcntBitWidth(Version.Major)) - 1; 13887a6dacacSDimitry Andric } 13897a6dacacSDimitry Andric 13907a6dacacSDimitry Andric unsigned getStorecntBitMask(const IsaVersion &Version) { 13917a6dacacSDimitry Andric return (1 << getStorecntBitWidth(Version.Major)) - 1; 13927a6dacacSDimitry Andric } 13937a6dacacSDimitry Andric 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 15337a6dacacSDimitry Andric unsigned encodeLoadcntDscnt(const IsaVersion &Version, const Waitcnt &Decoded) { 15347a6dacacSDimitry Andric return encodeLoadcntDscnt(Version, Decoded.LoadCnt, Decoded.DsCnt); 15357a6dacacSDimitry Andric } 15367a6dacacSDimitry Andric 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 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 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 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 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 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 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 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 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 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 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 166206c3fb27SDimitry Andric unsigned decodeFieldVmVsrc(unsigned Encoded) { 166306c3fb27SDimitry Andric return unpackBits(Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth()); 166406c3fb27SDimitry Andric } 166506c3fb27SDimitry Andric 166606c3fb27SDimitry Andric unsigned decodeFieldVaVdst(unsigned Encoded) { 166706c3fb27SDimitry Andric return unpackBits(Encoded, getVaVdstBitShift(), getVaVdstBitWidth()); 166806c3fb27SDimitry Andric } 166906c3fb27SDimitry Andric 167006c3fb27SDimitry Andric unsigned decodeFieldSaSdst(unsigned Encoded) { 167106c3fb27SDimitry Andric return unpackBits(Encoded, getSaSdstBitShift(), getSaSdstBitWidth()); 167206c3fb27SDimitry Andric } 167306c3fb27SDimitry Andric 167406c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned Encoded, unsigned VmVsrc) { 167506c3fb27SDimitry Andric return packBits(VmVsrc, Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth()); 167606c3fb27SDimitry Andric } 167706c3fb27SDimitry Andric 167806c3fb27SDimitry Andric unsigned encodeFieldVmVsrc(unsigned VmVsrc) { 167906c3fb27SDimitry Andric return encodeFieldVmVsrc(0xffff, VmVsrc); 168006c3fb27SDimitry Andric } 168106c3fb27SDimitry Andric 168206c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned Encoded, unsigned VaVdst) { 168306c3fb27SDimitry Andric return packBits(VaVdst, Encoded, getVaVdstBitShift(), getVaVdstBitWidth()); 168406c3fb27SDimitry Andric } 168506c3fb27SDimitry Andric 168606c3fb27SDimitry Andric unsigned encodeFieldVaVdst(unsigned VaVdst) { 168706c3fb27SDimitry Andric return encodeFieldVaVdst(0xffff, VaVdst); 168806c3fb27SDimitry Andric } 168906c3fb27SDimitry Andric 169006c3fb27SDimitry Andric unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst) { 169106c3fb27SDimitry Andric return packBits(SaSdst, Encoded, getSaSdstBitShift(), getSaSdstBitWidth()); 169206c3fb27SDimitry Andric } 169306c3fb27SDimitry Andric 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 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 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 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 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 1789e8d8bef9SDimitry Andric StringRef getDfmtName(unsigned Id) { 1790e8d8bef9SDimitry Andric assert(Id <= DFMT_MAX); 1791e8d8bef9SDimitry Andric return DfmtSymbolic[Id]; 1792e8d8bef9SDimitry Andric } 1793e8d8bef9SDimitry Andric 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 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 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 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 1823e8d8bef9SDimitry Andric bool isValidNfmt(unsigned Id, const MCSubtargetInfo &STI) { 1824e8d8bef9SDimitry Andric return !getNfmtName(Id, STI).empty(); 1825e8d8bef9SDimitry Andric } 1826e8d8bef9SDimitry Andric 1827e8d8bef9SDimitry Andric int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt) { 1828e8d8bef9SDimitry Andric return (Dfmt << DFMT_SHIFT) | (Nfmt << NFMT_SHIFT); 1829e8d8bef9SDimitry Andric } 1830e8d8bef9SDimitry Andric 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 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 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 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 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 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 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 189681ad6265SDimitry Andric static uint64_t getMsgIdMask(const MCSubtargetInfo &STI) { 189781ad6265SDimitry Andric return isGFX11Plus(STI) ? ID_MASK_GFX11Plus_ : ID_MASK_PreGFX11_; 18980b57cec5SDimitry Andric } 18990b57cec5SDimitry Andric 190081ad6265SDimitry Andric bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI) { 190181ad6265SDimitry Andric return (MsgId & ~(getMsgIdMask(STI))) == 0; 190281ad6265SDimitry Andric } 190381ad6265SDimitry Andric 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 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 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 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 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 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 19780b57cec5SDimitry Andric unsigned getInitialPSInputAddr(const Function &F) { 1979bdd1243dSDimitry Andric return F.getFnAttributeAsParsedInteger("InitialPSInputAddr", 0); 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric 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 1989fe6060f1SDimitry Andric bool getHasDepthExport(const Function &F) { 1990bdd1243dSDimitry Andric return F.getFnAttributeAsParsedInteger("amdgpu-depth-export", 0) != 0; 1991fe6060f1SDimitry Andric } 1992fe6060f1SDimitry Andric 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 2010e8d8bef9SDimitry Andric bool isGraphics(CallingConv::ID cc) { 2011e8d8bef9SDimitry Andric return isShader(cc) || cc == CallingConv::AMDGPU_Gfx; 2012e8d8bef9SDimitry Andric } 2013e8d8bef9SDimitry Andric 20140b57cec5SDimitry Andric bool isCompute(CallingConv::ID cc) { 2015e8d8bef9SDimitry Andric return !isGraphics(cc) || cc == CallingConv::AMDGPU_CS; 20160b57cec5SDimitry Andric } 20170b57cec5SDimitry Andric 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 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 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 205481ad6265SDimitry Andric bool isKernelCC(const Function *Func) { 205581ad6265SDimitry Andric return AMDGPU::isModuleEntryFunctionCC(Func->getCallingConv()); 205681ad6265SDimitry Andric } 205781ad6265SDimitry Andric 20580b57cec5SDimitry Andric bool hasXNACK(const MCSubtargetInfo &STI) { 205906c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureXNACK); 20600b57cec5SDimitry Andric } 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric bool hasSRAMECC(const MCSubtargetInfo &STI) { 206306c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureSRAMECC); 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric bool hasMIMG_R128(const MCSubtargetInfo &STI) { 206706c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureMIMG_R128) && !STI.hasFeature(AMDGPU::FeatureR128A16); 20685ffd83dbSDimitry Andric } 20695ffd83dbSDimitry Andric 2070bdd1243dSDimitry Andric bool hasA16(const MCSubtargetInfo &STI) { 207106c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureA16); 20725ffd83dbSDimitry Andric } 20735ffd83dbSDimitry Andric 20745ffd83dbSDimitry Andric bool hasG16(const MCSubtargetInfo &STI) { 207506c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureG16); 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric bool hasPackedD16(const MCSubtargetInfo &STI) { 207906c3fb27SDimitry Andric return !STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) && !isCI(STI) && 208081ad6265SDimitry Andric !isSI(STI); 20810b57cec5SDimitry Andric } 20820b57cec5SDimitry Andric 20835f757f3fSDimitry Andric bool hasGDS(const MCSubtargetInfo &STI) { 20845f757f3fSDimitry Andric return STI.hasFeature(AMDGPU::FeatureGDS); 20855f757f3fSDimitry Andric } 20865f757f3fSDimitry Andric 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 20985f757f3fSDimitry Andric unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI) { return 16; } 20995f757f3fSDimitry Andric 21000b57cec5SDimitry Andric bool isSI(const MCSubtargetInfo &STI) { 210106c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureSouthernIslands); 21020b57cec5SDimitry Andric } 21030b57cec5SDimitry Andric 21040b57cec5SDimitry Andric bool isCI(const MCSubtargetInfo &STI) { 210506c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureSeaIslands); 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric 21080b57cec5SDimitry Andric bool isVI(const MCSubtargetInfo &STI) { 210906c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureVolcanicIslands); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric bool isGFX9(const MCSubtargetInfo &STI) { 211306c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX9); 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric 211681ad6265SDimitry Andric bool isGFX9_GFX10(const MCSubtargetInfo &STI) { 211781ad6265SDimitry Andric return isGFX9(STI) || isGFX10(STI); 211881ad6265SDimitry Andric } 211981ad6265SDimitry Andric 21205f757f3fSDimitry Andric bool isGFX9_GFX10_GFX11(const MCSubtargetInfo &STI) { 21215f757f3fSDimitry Andric return isGFX9(STI) || isGFX10(STI) || isGFX11(STI); 21225f757f3fSDimitry Andric } 21235f757f3fSDimitry Andric 212481ad6265SDimitry Andric bool isGFX8_GFX9_GFX10(const MCSubtargetInfo &STI) { 212581ad6265SDimitry Andric return isVI(STI) || isGFX9(STI) || isGFX10(STI); 212681ad6265SDimitry Andric } 212781ad6265SDimitry Andric 212881ad6265SDimitry Andric bool isGFX8Plus(const MCSubtargetInfo &STI) { 212981ad6265SDimitry Andric return isVI(STI) || isGFX9Plus(STI); 213081ad6265SDimitry Andric } 213181ad6265SDimitry Andric 2132e8d8bef9SDimitry Andric bool isGFX9Plus(const MCSubtargetInfo &STI) { 2133e8d8bef9SDimitry Andric return isGFX9(STI) || isGFX10Plus(STI); 2134e8d8bef9SDimitry Andric } 2135e8d8bef9SDimitry Andric 2136*0fca6ea1SDimitry Andric bool isNotGFX9Plus(const MCSubtargetInfo &STI) { return !isGFX9Plus(STI); } 2137*0fca6ea1SDimitry Andric 21380b57cec5SDimitry Andric bool isGFX10(const MCSubtargetInfo &STI) { 213906c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX10); 21400b57cec5SDimitry Andric } 21410b57cec5SDimitry Andric 21425f757f3fSDimitry Andric bool isGFX10_GFX11(const MCSubtargetInfo &STI) { 21435f757f3fSDimitry Andric return isGFX10(STI) || isGFX11(STI); 21445f757f3fSDimitry Andric } 21455f757f3fSDimitry Andric 214681ad6265SDimitry Andric bool isGFX10Plus(const MCSubtargetInfo &STI) { 214781ad6265SDimitry Andric return isGFX10(STI) || isGFX11Plus(STI); 214881ad6265SDimitry Andric } 214981ad6265SDimitry Andric 215081ad6265SDimitry Andric bool isGFX11(const MCSubtargetInfo &STI) { 215106c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX11); 215281ad6265SDimitry Andric } 215381ad6265SDimitry Andric 215481ad6265SDimitry Andric bool isGFX11Plus(const MCSubtargetInfo &STI) { 21555f757f3fSDimitry Andric return isGFX11(STI) || isGFX12Plus(STI); 215681ad6265SDimitry Andric } 215781ad6265SDimitry Andric 21585f757f3fSDimitry Andric bool isGFX12(const MCSubtargetInfo &STI) { 21595f757f3fSDimitry Andric return STI.getFeatureBits()[AMDGPU::FeatureGFX12]; 21605f757f3fSDimitry Andric } 21615f757f3fSDimitry Andric 21625f757f3fSDimitry Andric bool isGFX12Plus(const MCSubtargetInfo &STI) { return isGFX12(STI); } 21635f757f3fSDimitry Andric 21645f757f3fSDimitry Andric bool isNotGFX12Plus(const MCSubtargetInfo &STI) { return !isGFX12Plus(STI); } 21655f757f3fSDimitry Andric 216681ad6265SDimitry Andric bool isNotGFX11Plus(const MCSubtargetInfo &STI) { 216781ad6265SDimitry Andric return !isGFX11Plus(STI); 216881ad6265SDimitry Andric } 216981ad6265SDimitry Andric 217081ad6265SDimitry Andric bool isNotGFX10Plus(const MCSubtargetInfo &STI) { 217181ad6265SDimitry Andric return isSI(STI) || isCI(STI) || isVI(STI) || isGFX9(STI); 217281ad6265SDimitry Andric } 217381ad6265SDimitry Andric 217481ad6265SDimitry Andric bool isGFX10Before1030(const MCSubtargetInfo &STI) { 217581ad6265SDimitry Andric return isGFX10(STI) && !AMDGPU::isGFX10_BEncoding(STI); 217681ad6265SDimitry Andric } 2177e8d8bef9SDimitry Andric 21780b57cec5SDimitry Andric bool isGCN3Encoding(const MCSubtargetInfo &STI) { 217906c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGCN3Encoding); 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric 2182fe6060f1SDimitry Andric bool isGFX10_AEncoding(const MCSubtargetInfo &STI) { 218306c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX10_AEncoding); 2184fe6060f1SDimitry Andric } 2185fe6060f1SDimitry Andric 21865ffd83dbSDimitry Andric bool isGFX10_BEncoding(const MCSubtargetInfo &STI) { 218706c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding); 21885ffd83dbSDimitry Andric } 21895ffd83dbSDimitry Andric 21905ffd83dbSDimitry Andric bool hasGFX10_3Insts(const MCSubtargetInfo &STI) { 219106c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX10_3Insts); 21925ffd83dbSDimitry Andric } 21935ffd83dbSDimitry Andric 21945f757f3fSDimitry Andric bool isGFX10_3_GFX11(const MCSubtargetInfo &STI) { 21955f757f3fSDimitry Andric return isGFX10_BEncoding(STI) && !isGFX12Plus(STI); 21965f757f3fSDimitry Andric } 21975f757f3fSDimitry Andric 2198fe6060f1SDimitry Andric bool isGFX90A(const MCSubtargetInfo &STI) { 219906c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX90AInsts); 2200fe6060f1SDimitry Andric } 2201fe6060f1SDimitry Andric 220281ad6265SDimitry Andric bool isGFX940(const MCSubtargetInfo &STI) { 220306c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX940Insts); 220481ad6265SDimitry Andric } 220581ad6265SDimitry Andric 2206fe6060f1SDimitry Andric bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI) { 220706c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch); 2208fe6060f1SDimitry Andric } 2209fe6060f1SDimitry Andric 221081ad6265SDimitry Andric bool hasMAIInsts(const MCSubtargetInfo &STI) { 221106c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureMAIInsts); 221281ad6265SDimitry Andric } 221381ad6265SDimitry Andric 221481ad6265SDimitry Andric bool hasVOPD(const MCSubtargetInfo &STI) { 221506c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureVOPD); 221681ad6265SDimitry Andric } 221781ad6265SDimitry Andric 22185f757f3fSDimitry Andric bool hasDPPSrc1SGPR(const MCSubtargetInfo &STI) { 22195f757f3fSDimitry Andric return STI.hasFeature(AMDGPU::FeatureDPPSrc1SGPR); 22205f757f3fSDimitry Andric } 22215f757f3fSDimitry Andric 22225f757f3fSDimitry Andric unsigned hasKernargPreload(const MCSubtargetInfo &STI) { 22235f757f3fSDimitry Andric return STI.hasFeature(AMDGPU::FeatureKernargPreload); 22245f757f3fSDimitry Andric } 22255f757f3fSDimitry Andric 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 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 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 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 23170b57cec5SDimitry Andric unsigned mc2PseudoReg(unsigned Reg) { 23180b57cec5SDimitry Andric MAP_REG2REG 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 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 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 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 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 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. 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 25400b57cec5SDimitry Andric unsigned getRegBitWidth(const MCRegisterClass &RC) { 25410b57cec5SDimitry Andric return getRegBitWidth(RC.getID()); 25420b57cec5SDimitry Andric } 25430b57cec5SDimitry Andric 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 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 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 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 2611*0fca6ea1SDimitry Andric bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi) { 2612*0fca6ea1SDimitry Andric return isInlinableLiteral32(Literal, HasInv2Pi); 2613*0fca6ea1SDimitry Andric } 2614*0fca6ea1SDimitry Andric 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 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. 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. 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. 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. 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. 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. 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. 27561db9f3b2SDimitry Andric bool isInlinableLiteralV2F16(uint32_t Literal) { 27571db9f3b2SDimitry Andric return getInlineEncodingV2F16(Literal).has_value(); 275816d6b3b3SDimitry Andric } 275916d6b3b3SDimitry Andric 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 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 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 28220b57cec5SDimitry Andric static bool hasSMEMByteOffset(const MCSubtargetInfo &ST) { 2823e8d8bef9SDimitry Andric return isGCN3Encoding(ST) || isGFX10Plus(ST); 28240b57cec5SDimitry Andric } 28250b57cec5SDimitry Andric 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 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 28465ffd83dbSDimitry Andric static bool isDwordAligned(uint64_t ByteOffset) { 28475ffd83dbSDimitry Andric return (ByteOffset & 3) == 0; 28485ffd83dbSDimitry Andric } 28495ffd83dbSDimitry Andric 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 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 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 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 29280b57cec5SDimitry Andric bool isIntrinsicSourceOfDivergence(unsigned IntrID) { 29290b57cec5SDimitry Andric return lookupSourceOfDivergence(IntrID); 29300b57cec5SDimitry Andric } 29310b57cec5SDimitry Andric 293206c3fb27SDimitry Andric bool isIntrinsicAlwaysUniform(unsigned IntrID) { 293306c3fb27SDimitry Andric return lookupAlwaysUniform(IntrID); 293406c3fb27SDimitry Andric } 293506c3fb27SDimitry Andric 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 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 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 29715f757f3fSDimitry Andric bool isDPALU_DPP(const MCInstrDesc &OpDesc) { 29725f757f3fSDimitry Andric return hasAny64BitVGPROperands(OpDesc); 29735f757f3fSDimitry Andric } 29745f757f3fSDimitry Andric 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 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