LLVM 24.0.0git
AMDGPUBaseInfo.cpp
Go to the documentation of this file.
1//===- AMDGPUBaseInfo.cpp - AMDGPU Base encoding information --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AMDGPUBaseInfo.h"
10#include "AMDGPU.h"
11#include "AMDGPUAsmUtils.h"
12#include "AMDKernelCodeT.h"
17#include "llvm/IR/Attributes.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalValue.h"
21#include "llvm/IR/IntrinsicsAMDGPU.h"
22#include "llvm/IR/IntrinsicsR600.h"
23#include "llvm/IR/LLVMContext.h"
24#include "llvm/IR/Metadata.h"
25#include "llvm/MC/MCInstrInfo.h"
30#include <optional>
31
32#define GET_INSTRINFO_NAMED_OPS
33#define GET_INSTRMAP_INFO
34#include "AMDGPUGenInstrInfo.inc"
35
37 "amdhsa-code-object-version", llvm::cl::Hidden,
39 llvm::cl::desc("Set default AMDHSA Code Object Version (module flag "
40 "or asm directive still take priority if present)"));
41
42namespace {
43
44/// \returns Bit mask for given bit \p Shift and bit \p Width.
45unsigned getBitMask(unsigned Shift, unsigned Width) {
46 return ((1 << Width) - 1) << Shift;
47}
48
49/// Packs \p Src into \p Dst for given bit \p Shift and bit \p Width.
50///
51/// \returns Packed \p Dst.
52unsigned packBits(unsigned Src, unsigned Dst, unsigned Shift, unsigned Width) {
53 unsigned Mask = getBitMask(Shift, Width);
54 return ((Src << Shift) & Mask) | (Dst & ~Mask);
55}
56
57/// Unpacks bits from \p Src for given bit \p Shift and bit \p Width.
58///
59/// \returns Unpacked bits.
60unsigned unpackBits(unsigned Src, unsigned Shift, unsigned Width) {
61 return (Src & getBitMask(Shift, Width)) >> Shift;
62}
63
64/// \returns Vmcnt bit shift (lower bits).
65unsigned getVmcntBitShiftLo(unsigned VersionMajor) {
66 return VersionMajor >= 11 ? 10 : 0;
67}
68
69/// \returns Vmcnt bit width (lower bits).
70unsigned getVmcntBitWidthLo(unsigned VersionMajor) {
71 return VersionMajor >= 11 ? 6 : 4;
72}
73
74/// \returns Expcnt bit shift.
75unsigned getExpcntBitShift(unsigned VersionMajor) {
76 return VersionMajor >= 11 ? 0 : 4;
77}
78
79/// \returns Expcnt bit width.
80unsigned getExpcntBitWidth(unsigned VersionMajor) { return 3; }
81
82/// \returns Lgkmcnt bit shift.
83unsigned getLgkmcntBitShift(unsigned VersionMajor) {
84 return VersionMajor >= 11 ? 4 : 8;
85}
86
87/// \returns Lgkmcnt bit width.
88unsigned getLgkmcntBitWidth(unsigned VersionMajor) {
89 return VersionMajor >= 10 ? 6 : 4;
90}
91
92/// \returns Vmcnt bit shift (higher bits).
93unsigned getVmcntBitShiftHi(unsigned VersionMajor) { return 14; }
94
95/// \returns Vmcnt bit width (higher bits).
96unsigned getVmcntBitWidthHi(unsigned VersionMajor) {
97 return (VersionMajor == 9 || VersionMajor == 10) ? 2 : 0;
98}
99
100/// \returns Loadcnt bit width
101unsigned getLoadcntBitWidth(unsigned VersionMajor) {
102 return VersionMajor >= 12 ? 6 : 0;
103}
104
105/// \returns Samplecnt bit width.
106unsigned getSamplecntBitWidth(unsigned VersionMajor) {
107 return VersionMajor >= 12 ? 6 : 0;
108}
109
110/// \returns Bvhcnt bit width.
111unsigned getBvhcntBitWidth(unsigned VersionMajor) {
112 return VersionMajor >= 12 ? 3 : 0;
113}
114
115/// \returns Dscnt bit width.
116unsigned getDscntBitWidth(unsigned VersionMajor) {
117 return VersionMajor >= 12 ? 6 : 0;
118}
119
120/// \returns Dscnt bit shift in combined S_WAIT instructions.
121unsigned getDscntBitShift(unsigned VersionMajor) { return 0; }
122
123/// \returns Storecnt or Vscnt bit width, depending on VersionMajor.
124unsigned getStorecntBitWidth(unsigned VersionMajor) {
125 return VersionMajor >= 10 ? 6 : 0;
126}
127
128/// \returns Kmcnt bit width.
129unsigned getKmcntBitWidth(unsigned VersionMajor) {
130 return VersionMajor >= 12 ? 5 : 0;
131}
132
133/// \returns Xcnt bit width.
134unsigned getXcntBitWidth(unsigned VersionMajor, unsigned VersionMinor) {
135 return VersionMajor == 12 && VersionMinor == 5 ? 6 : 0;
136}
137
138/// \returns Asynccnt bit width.
139unsigned getAsynccntBitWidth(unsigned VersionMajor, unsigned VersionMinor) {
140 return VersionMajor == 12 && VersionMinor == 5 ? 6 : 0;
141}
142
143/// \returns shift for Loadcnt/Storecnt in combined S_WAIT instructions.
144unsigned getLoadcntStorecntBitShift(unsigned VersionMajor) {
145 return VersionMajor >= 12 ? 8 : 0;
146}
147
148/// \returns VaSdst bit width
149inline unsigned getVaSdstBitWidth() { return 3; }
150
151/// \returns VaSdst bit shift
152inline unsigned getVaSdstBitShift() { return 9; }
153
154/// \returns VmVsrc bit width
155inline unsigned getVmVsrcBitWidth() { return 3; }
156
157/// \returns VmVsrc bit shift
158inline unsigned getVmVsrcBitShift() { return 2; }
159
160/// \returns VaVdst bit width
161inline unsigned getVaVdstBitWidth() { return 4; }
162
163/// \returns VaVdst bit shift
164inline unsigned getVaVdstBitShift() { return 12; }
165
166/// \returns VaVcc bit width
167inline unsigned getVaVccBitWidth() { return 1; }
168
169/// \returns VaVcc bit shift
170inline unsigned getVaVccBitShift() { return 1; }
171
172/// \returns SaSdst bit width
173inline unsigned getSaSdstBitWidth() { return 1; }
174
175/// \returns SaSdst bit shift
176inline unsigned getSaSdstBitShift() { return 0; }
177
178/// \returns VaSsrc width
179inline unsigned getVaSsrcBitWidth() { return 1; }
180
181/// \returns VaSsrc bit shift
182inline unsigned getVaSsrcBitShift() { return 8; }
183
184/// \returns HoldCnt bit shift
185inline unsigned getHoldCntWidth(unsigned VersionMajor, unsigned VersionMinor) {
186 static constexpr const unsigned MinMajor = 10;
187 static constexpr const unsigned MinMinor = 3;
188 return std::tie(VersionMajor, VersionMinor) >= std::tie(MinMajor, MinMinor)
189 ? 1
190 : 0;
191}
192
193/// \returns HoldCnt bit shift
194inline unsigned getHoldCntBitShift() { return 7; }
195
196} // end anonymous namespace
197
198namespace llvm {
199
200namespace AMDGPU {
201
202/// \returns true if the target supports signed immediate offset for SMRD
203/// instructions.
205 return isGFX9Plus(ST);
206}
207
208/// \returns True if \p STI is AMDHSA.
209bool isHsaAbi(const MCSubtargetInfo &STI) {
210 return STI.getTargetTriple().getOS() == Triple::AMDHSA;
211}
212
215 M.getModuleFlag("amdhsa_code_object_version"))) {
216 return (unsigned)Ver->getZExtValue() / 100;
217 }
218
220}
221
225
226unsigned getAMDHSACodeObjectVersion(unsigned ABIVersion) {
227 switch (ABIVersion) {
229 return 4;
231 return 5;
233 return 6;
234 default:
236 }
237}
238
239uint8_t getELFABIVersion(const Triple &T, unsigned CodeObjectVersion) {
240 if (T.getOS() != Triple::AMDHSA)
241 return 0;
242
243 switch (CodeObjectVersion) {
244 case 4:
246 case 5:
248 case 6:
250 default:
251 report_fatal_error("Unsupported AMDHSA Code Object Version " +
252 Twine(CodeObjectVersion));
253 }
254}
255
256unsigned getMultigridSyncArgImplicitArgPosition(unsigned CodeObjectVersion) {
257 switch (CodeObjectVersion) {
258 case AMDHSA_COV4:
259 return 48;
260 case AMDHSA_COV5:
261 case AMDHSA_COV6:
262 default:
264 }
265}
266
267// FIXME: All such magic numbers about the ABI should be in a
268// central TD file.
269unsigned getHostcallImplicitArgPosition(unsigned CodeObjectVersion) {
270 switch (CodeObjectVersion) {
271 case AMDHSA_COV4:
272 return 24;
273 case AMDHSA_COV5:
274 case AMDHSA_COV6:
275 default:
277 }
278}
279
280unsigned getDefaultQueueImplicitArgPosition(unsigned CodeObjectVersion) {
281 switch (CodeObjectVersion) {
282 case AMDHSA_COV4:
283 return 32;
284 case AMDHSA_COV5:
285 case AMDHSA_COV6:
286 default:
288 }
289}
290
291unsigned getCompletionActionImplicitArgPosition(unsigned CodeObjectVersion) {
292 switch (CodeObjectVersion) {
293 case AMDHSA_COV4:
294 return 40;
295 case AMDHSA_COV5:
296 case AMDHSA_COV6:
297 default:
299 }
300}
301
302#define GET_MIMGBaseOpcodesTable_IMPL
303#define GET_MIMGDimInfoTable_IMPL
304#define GET_MIMGInfoTable_IMPL
305#define GET_MIMGLZMappingTable_IMPL
306#define GET_MIMGMIPMappingTable_IMPL
307#define GET_MIMGBiasMappingTable_IMPL
308#define GET_MIMGOffsetMappingTable_IMPL
309#define GET_MIMGG16MappingTable_IMPL
310#define GET_MAIInstInfoTable_IMPL
311#define GET_WMMAInstInfoTable_IMPL
312#include "AMDGPUGenSearchableTables.inc"
313
314int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding,
315 unsigned VDataDwords, unsigned VAddrDwords) {
316 const MIMGInfo *Info =
317 getMIMGOpcodeHelper(BaseOpcode, MIMGEncoding, VDataDwords, VAddrDwords);
318 return Info ? Info->Opcode : -1;
319}
320
322 const MIMGInfo *Info = getMIMGInfo(Opc);
323 return Info ? getMIMGBaseOpcodeInfo(Info->BaseOpcode) : nullptr;
324}
325
326int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels) {
327 const MIMGInfo *OrigInfo = getMIMGInfo(Opc);
328 const MIMGInfo *NewInfo =
329 getMIMGOpcodeHelper(OrigInfo->BaseOpcode, OrigInfo->MIMGEncoding,
330 NewChannels, OrigInfo->VAddrDwords);
331 return NewInfo ? NewInfo->Opcode : -1;
332}
333
334unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode,
335 const MIMGDimInfo *Dim, bool IsA16,
336 bool IsG16Supported) {
337 unsigned AddrWords = BaseOpcode->NumExtraArgs;
338 unsigned AddrComponents = (BaseOpcode->Coordinates ? Dim->NumCoords : 0) +
339 (BaseOpcode->LodOrClampOrMip ? 1 : 0);
340 if (IsA16)
341 AddrWords += divideCeil(AddrComponents, 2);
342 else
343 AddrWords += AddrComponents;
344
345 // Note: For subtargets that support A16 but not G16, enabling A16 also
346 // enables 16 bit gradients.
347 // For subtargets that support A16 (operand) and G16 (done with a different
348 // instruction encoding), they are independent.
349
350 if (BaseOpcode->Gradients) {
351 if ((IsA16 && !IsG16Supported) || BaseOpcode->G16)
352 // There are two gradients per coordinate, we pack them separately.
353 // For the 3d case,
354 // we get (dy/du, dx/du) (-, dz/du) (dy/dv, dx/dv) (-, dz/dv)
355 AddrWords += alignTo<2>(Dim->NumGradients / 2);
356 else
357 AddrWords += Dim->NumGradients;
358 }
359 return AddrWords;
360}
361
372
381
386
391
395
399
403
408
416
421
424 bool IsX;
425 bool IsY;
426};
427
428#define GET_FP4FP8DstByteSelTable_DECL
429#define GET_FP4FP8DstByteSelTable_IMPL
430
435
441
442#define GET_DPMACCInstructionTable_DECL
443#define GET_DPMACCInstructionTable_IMPL
444#define GET_MTBUFInfoTable_DECL
445#define GET_MTBUFInfoTable_IMPL
446#define GET_MUBUFInfoTable_DECL
447#define GET_MUBUFInfoTable_IMPL
448#define GET_SMInfoTable_DECL
449#define GET_SMInfoTable_IMPL
450#define GET_VOP1InfoTable_DECL
451#define GET_VOP1InfoTable_IMPL
452#define GET_VOP2InfoTable_DECL
453#define GET_VOP2InfoTable_IMPL
454#define GET_VOP3InfoTable_DECL
455#define GET_VOP3InfoTable_IMPL
456#define GET_VOPC64DPPTable_DECL
457#define GET_VOPC64DPPTable_IMPL
458#define GET_VOPC64DPP8Table_DECL
459#define GET_VOPC64DPP8Table_IMPL
460#define GET_VOPCAsmOnlyInfoTable_DECL
461#define GET_VOPCAsmOnlyInfoTable_IMPL
462#define GET_VOP3CAsmOnlyInfoTable_DECL
463#define GET_VOP3CAsmOnlyInfoTable_IMPL
464#define GET_VOPDComponentTable_DECL
465#define GET_VOPDComponentTable_IMPL
466#define GET_VOPDPairs_DECL
467#define GET_VOPDPairs_IMPL
468#define GET_VOPDXYTable_DECL
469#define GET_VOPDXYTable_IMPL
470#define GET_VOPTrue16Table_DECL
471#define GET_VOPTrue16Table_IMPL
472#define GET_True16D16Table_IMPL
473#define GET_WMMAOpcode2AddrMappingTable_DECL
474#define GET_WMMAOpcode2AddrMappingTable_IMPL
475#define GET_WMMAOpcode3AddrMappingTable_DECL
476#define GET_WMMAOpcode3AddrMappingTable_IMPL
477#define GET_getMFMA_F8F6F4_WithSize_DECL
478#define GET_getMFMA_F8F6F4_WithSize_IMPL
479#define GET_isMFMA_F8F6F4Table_IMPL
480#define GET_isCvtScaleF32_F32F16ToF8F4Table_IMPL
481
482#include "AMDGPUGenSearchableTables.inc"
483
484int getMTBUFBaseOpcode(unsigned Opc) {
485 const MTBUFInfo *Info = getMTBUFInfoFromOpcode(Opc);
486 return Info ? Info->BaseOpcode : -1;
487}
488
489int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements) {
490 const MTBUFInfo *Info =
491 getMTBUFInfoFromBaseOpcodeAndElements(BaseOpc, Elements);
492 return Info ? Info->Opcode : -1;
493}
494
495int getMTBUFElements(unsigned Opc) {
496 const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
497 return Info ? Info->elements : 0;
498}
499
500bool getMTBUFHasVAddr(unsigned Opc) {
501 const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
502 return Info && Info->has_vaddr;
503}
504
505bool getMTBUFHasSrsrc(unsigned Opc) {
506 const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
507 return Info && Info->has_srsrc;
508}
509
510bool getMTBUFHasSoffset(unsigned Opc) {
511 const MTBUFInfo *Info = getMTBUFOpcodeHelper(Opc);
512 return Info && Info->has_soffset;
513}
514
515int getMUBUFBaseOpcode(unsigned Opc) {
516 const MUBUFInfo *Info = getMUBUFInfoFromOpcode(Opc);
517 return Info ? Info->BaseOpcode : -1;
518}
519
520int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements) {
521 const MUBUFInfo *Info =
522 getMUBUFInfoFromBaseOpcodeAndElements(BaseOpc, Elements);
523 return Info ? Info->Opcode : -1;
524}
525
526int getMUBUFElements(unsigned Opc) {
527 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
528 return Info ? Info->elements : 0;
529}
530
531bool getMUBUFHasVAddr(unsigned Opc) {
532 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
533 return Info && Info->has_vaddr;
534}
535
536bool getMUBUFHasSrsrc(unsigned Opc) {
537 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
538 return Info && Info->has_srsrc;
539}
540
541bool getMUBUFHasSoffset(unsigned Opc) {
542 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
543 return Info && Info->has_soffset;
544}
545
546bool getMUBUFIsBufferInv(unsigned Opc) {
547 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
548 return Info && Info->IsBufferInv;
549}
550
551bool getMUBUFTfe(unsigned Opc) {
552 const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc);
553 return Info && Info->tfe;
554}
555
556bool getSMEMIsBuffer(unsigned Opc) {
557 const SMInfo *Info = getSMEMOpcodeHelper(Opc);
558 return Info && Info->IsBuffer;
559}
560
561bool getVOP1IsSingle(unsigned Opc) {
562 const VOPInfo *Info = getVOP1OpcodeHelper(Opc);
563 return !Info || Info->IsSingle;
564}
565
566bool getVOP2IsSingle(unsigned Opc) {
567 const VOPInfo *Info = getVOP2OpcodeHelper(Opc);
568 return !Info || Info->IsSingle;
569}
570
571bool getVOP3IsSingle(unsigned Opc) {
572 const VOPInfo *Info = getVOP3OpcodeHelper(Opc);
573 return !Info || Info->IsSingle;
574}
575
576bool isVOPC64DPP(unsigned Opc) {
577 return isVOPC64DPPOpcodeHelper(Opc) || isVOPC64DPP8OpcodeHelper(Opc);
578}
579
580bool isVOPCAsmOnly(unsigned Opc) { return isVOPCAsmOnlyOpcodeHelper(Opc); }
581
582bool getMAIIsDGEMM(unsigned Opc) {
583 const MAIInstInfo *Info = getMAIInstInfoHelper(Opc);
584 return Info && Info->is_dgemm;
585}
586
587bool getMAIIsGFX940XDL(unsigned Opc) {
588 const MAIInstInfo *Info = getMAIInstInfoHelper(Opc);
589 return Info && Info->is_gfx940_xdl;
590}
591
592bool getWMMAIsXDL(unsigned Opc) {
593 const WMMAInstInfo *Info = getWMMAInstInfoHelper(Opc);
594 return Info ? Info->is_wmma_xdl : false;
595}
596
597bool getHasMatrixScale(unsigned Opc) {
598 const WMMAInstInfo *Info = getWMMAInstInfoHelper(Opc);
599 return Info && Info->HasMatrixScale;
600}
601
603 switch (EncodingVal) {
606 return 6;
608 return 4;
611 default:
612 return 8;
613 }
614
615 llvm_unreachable("covered switch over mfma scale formats");
616}
617
619 unsigned BLGP,
620 unsigned F8F8Opcode) {
621 uint8_t SrcANumRegs = mfmaScaleF8F6F4FormatToNumRegs(CBSZ);
622 uint8_t SrcBNumRegs = mfmaScaleF8F6F4FormatToNumRegs(BLGP);
623 return getMFMA_F8F6F4_InstWithNumRegs(SrcANumRegs, SrcBNumRegs, F8F8Opcode);
624}
625
627 switch (Fmt) {
630 return 16;
633 return 12;
635 return 8;
636 }
637
638 llvm_unreachable("covered switch over wmma scale formats");
639}
640
642 unsigned FmtB,
643 unsigned F8F8Opcode) {
644 uint8_t SrcANumRegs = wmmaScaleF8F6F4FormatToNumRegs(FmtA);
645 uint8_t SrcBNumRegs = wmmaScaleF8F6F4FormatToNumRegs(FmtB);
646 return getMFMA_F8F6F4_InstWithNumRegs(SrcANumRegs, SrcBNumRegs, F8F8Opcode);
647}
648
649bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale,
650 unsigned BFmt, unsigned BScale) {
651 auto isValid = [](unsigned Fmt, unsigned Scale) -> bool {
652 switch (Fmt) {
657 if (Scale != WMMA::MATRIX_SCALE_FMT_E8)
658 return false;
659 break;
661 if (Scale != WMMA::MATRIX_SCALE_FMT_E8 &&
664 return false;
665 break;
666 }
667 return true;
668 };
669
670 if (!isValid(AFmt, AScale) || !isValid(BFmt, BScale))
671 return false;
672
673 if (AFmt == WMMA::MATRIX_FMT_FP4 && BFmt == WMMA::MATRIX_FMT_FP4 &&
674 AScale != BScale)
675 return false;
676
677 return true;
678}
679
681 if (ST.hasFeature(AMDGPU::FeatureGFX13Insts))
683 if (ST.hasFeature(AMDGPU::FeatureGFX1250Insts))
685 if (ST.hasFeature(AMDGPU::FeatureGFX12Insts))
687 if (ST.hasFeature(AMDGPU::FeatureGFX11_7Insts))
689 if (ST.hasFeature(AMDGPU::FeatureGFX11Insts))
691 llvm_unreachable("Subtarget generation does not support VOPD!");
692}
693
694CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3) {
695 bool IsConvertibleToBitOp = VOPD3 ? getBitOp2(Opc) : 0;
696 Opc = IsConvertibleToBitOp ? (unsigned)AMDGPU::V_BITOP3_B32_e64 : Opc;
697 // Normalize through VOPDComponentTable so that e32 and e64 variants
698 // of the same logical opcode all share a single entry.
699 const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc);
700 if (!Info)
701 return {false, false};
702 unsigned Key =
703 (Info->VOPDOp << 5) | (EncodingFamily << 1) | (VOPD3 ? 1u : 0u);
704 const VOPDXYInfo *XYInfo = getVOPDXYInfo(Key);
705 if (!XYInfo)
706 return {false, false};
707 return {XYInfo->IsX, XYInfo->IsY};
708}
709
710unsigned getVOPDOpcode(unsigned Opc, bool VOPD3) {
711 bool IsConvertibleToBitOp = VOPD3 ? getBitOp2(Opc) : 0;
712 Opc = IsConvertibleToBitOp ? (unsigned)AMDGPU::V_BITOP3_B32_e64 : Opc;
713 const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc);
714 return Info ? Info->VOPDOp : ~0u;
715}
716
717bool isVOPD(unsigned Opc) {
718 return AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0X);
719}
720
721bool isMAC(unsigned Opc) {
722 return Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 ||
723 Opc == AMDGPU::V_MAC_F32_e64_gfx10 ||
724 Opc == AMDGPU::V_MAC_F32_e64_vi ||
725 Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx6_gfx7 ||
726 Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx10 ||
727 Opc == AMDGPU::V_MAC_F16_e64_vi ||
728 Opc == AMDGPU::V_FMAC_F64_e64_gfx90a ||
729 Opc == AMDGPU::V_FMAC_F64_e64_gfx12 ||
730 Opc == AMDGPU::V_FMAC_F64_e64_gfx13 ||
731 Opc == AMDGPU::V_FMAC_F32_e64_gfx10 ||
732 Opc == AMDGPU::V_FMAC_F32_e64_gfx11 ||
733 Opc == AMDGPU::V_FMAC_F32_e64_gfx12 ||
734 Opc == AMDGPU::V_FMAC_F32_e64_gfx13 ||
735 Opc == AMDGPU::V_FMAC_F32_e64_vi ||
736 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64_gfx10 ||
737 Opc == AMDGPU::V_FMAC_DX9_ZERO_F32_e64_gfx11 ||
738 Opc == AMDGPU::V_FMAC_F16_e64_gfx10 ||
739 Opc == AMDGPU::V_FMAC_F16_t16_e64_gfx11 ||
740 Opc == AMDGPU::V_FMAC_F16_fake16_e64_gfx11 ||
741 Opc == AMDGPU::V_FMAC_F16_t16_e64_gfx12 ||
742 Opc == AMDGPU::V_FMAC_F16_fake16_e64_gfx12 ||
743 Opc == AMDGPU::V_FMAC_F16_t16_e64_gfx13 ||
744 Opc == AMDGPU::V_FMAC_F16_fake16_e64_gfx13 ||
745 Opc == AMDGPU::V_DOT2C_F32_F16_e64_vi ||
746 Opc == AMDGPU::V_DOT2C_F32_BF16_e64_vi ||
747 Opc == AMDGPU::V_DOT2C_I32_I16_e64_vi ||
748 Opc == AMDGPU::V_DOT4C_I32_I8_e64_vi ||
749 Opc == AMDGPU::V_DOT8C_I32_I4_e64_vi;
750}
751
752bool isPermlane16(unsigned Opc) {
753 return Opc == AMDGPU::V_PERMLANE16_B32_gfx10 ||
754 Opc == AMDGPU::V_PERMLANEX16_B32_gfx10 ||
755 Opc == AMDGPU::V_PERMLANE16_B32_e64_gfx11 ||
756 Opc == AMDGPU::V_PERMLANEX16_B32_e64_gfx11 ||
757 Opc == AMDGPU::V_PERMLANE16_B32_e64_gfx12 ||
758 Opc == AMDGPU::V_PERMLANE16_B32_e64_gfx13 ||
759 Opc == AMDGPU::V_PERMLANEX16_B32_e64_gfx12 ||
760 Opc == AMDGPU::V_PERMLANEX16_B32_e64_gfx13 ||
761 Opc == AMDGPU::V_PERMLANE16_VAR_B32_e64_gfx12 ||
762 Opc == AMDGPU::V_PERMLANE16_VAR_B32_e64_gfx13 ||
763 Opc == AMDGPU::V_PERMLANEX16_VAR_B32_e64_gfx12 ||
764 Opc == AMDGPU::V_PERMLANEX16_VAR_B32_e64_gfx13;
765}
766
768 return Opc == AMDGPU::V_CVT_F32_BF8_e64_gfx12 ||
769 Opc == AMDGPU::V_CVT_F32_FP8_e64_gfx12 ||
770 Opc == AMDGPU::V_CVT_F32_BF8_e64_dpp_gfx12 ||
771 Opc == AMDGPU::V_CVT_F32_FP8_e64_dpp_gfx12 ||
772 Opc == AMDGPU::V_CVT_F32_BF8_e64_dpp8_gfx12 ||
773 Opc == AMDGPU::V_CVT_F32_FP8_e64_dpp8_gfx12 ||
774 Opc == AMDGPU::V_CVT_PK_F32_BF8_fake16_e64_gfx12 ||
775 Opc == AMDGPU::V_CVT_PK_F32_FP8_fake16_e64_gfx12 ||
776 Opc == AMDGPU::V_CVT_PK_F32_BF8_t16_e64_gfx12 ||
777 Opc == AMDGPU::V_CVT_PK_F32_FP8_t16_e64_gfx12;
778}
779
780bool isGenericAtomic(unsigned Opc) {
781 return Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP ||
782 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD ||
783 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB ||
784 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN ||
785 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN ||
786 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX ||
787 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX ||
788 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND ||
789 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR ||
790 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR ||
791 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC ||
792 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC ||
793 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD ||
794 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN ||
795 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX ||
796 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP ||
797 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32 ||
798 Opc == AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32 ||
799 Opc == AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG;
800}
801
802bool isAsyncStore(unsigned Opc) {
803 return Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B8_gfx1250 ||
804 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B32_gfx1250 ||
805 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B64_gfx1250 ||
806 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B128_gfx1250 ||
807 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B8_SADDR_gfx1250 ||
808 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B32_SADDR_gfx1250 ||
809 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B64_SADDR_gfx1250 ||
810 Opc == GLOBAL_STORE_ASYNC_FROM_LDS_B128_SADDR_gfx1250;
811}
812
813bool isTensorStore(unsigned Opc) {
814 return Opc == TENSOR_STORE_FROM_LDS_d2_gfx1250 ||
815 Opc == TENSOR_STORE_FROM_LDS_d4_gfx1250;
816}
817
818unsigned getTemporalHintType(const MCInstrDesc TID) {
819 if (SIInstrFlags::isAtomic(TID))
821 unsigned Opc = TID.getOpcode();
822 // Async and Tensor store should have the temporal hint type of TH_TYPE_STORE
823 if (TID.mayStore() &&
824 (isAsyncStore(Opc) || isTensorStore(Opc) || !TID.mayLoad()))
825 return CPol::TH_TYPE_STORE;
826
827 // This will default to returning TH_TYPE_LOAD when neither MayStore nor
828 // MayLoad flag is present which is the case with instructions like
829 // image_get_resinfo.
830 return CPol::TH_TYPE_LOAD;
831}
832
833bool isTrue16Inst(unsigned Opc) {
834 const VOPTrue16Info *Info = getTrue16OpcodeHelper(Opc);
835 return Info && Info->IsTrue16;
836}
837
839 const FP4FP8DstByteSelInfo *Info = getFP4FP8DstByteSelHelper(Opc);
840 if (!Info)
841 return FPType::None;
842 if (Info->HasFP8DstByteSel)
843 return FPType::FP8;
844 if (Info->HasFP4DstByteSel)
845 return FPType::FP4;
846
847 return FPType::None;
848}
849
850bool isDPMACCInstruction(unsigned Opc) {
851 const DPMACCInstructionInfo *Info = getDPMACCInstructionHelper(Opc);
852 return Info && Info->IsDPMACCInstruction;
853}
854
855unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc) {
856 const WMMAOpcodeMappingInfo *Info = getWMMAMappingInfoFrom2AddrOpcode(Opc);
857 return Info ? Info->Opcode3Addr : ~0u;
858}
859
860unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc) {
861 const WMMAOpcodeMappingInfo *Info = getWMMAMappingInfoFrom3AddrOpcode(Opc);
862 return Info ? Info->Opcode2Addr : ~0u;
863}
864
865// Wrapper for Tablegen'd function. enum Subtarget is not defined in any
866// header files, so we need to wrap it in a function that takes unsigned
867// instead.
868int32_t getMCOpcode(uint32_t Opcode, unsigned Gen) {
869 return getMCOpcodeGen(Opcode, static_cast<Subtarget>(Gen));
870}
871
872unsigned getBitOp2(unsigned Opc) {
873 switch (Opc) {
874 default:
875 return 0;
876 case AMDGPU::V_AND_B32_e32:
877 return 0x40;
878 case AMDGPU::V_OR_B32_e32:
879 return 0x54;
880 case AMDGPU::V_XOR_B32_e32:
881 return 0x14;
882 case AMDGPU::V_XNOR_B32_e32:
883 return 0x41;
884 }
885}
886
887int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily,
888 bool VOPD3) {
889 bool IsConvertibleToBitOp = VOPD3 ? getBitOp2(OpY) : 0;
890 OpY = IsConvertibleToBitOp ? (unsigned)AMDGPU::V_BITOP3_B32_e64 : OpY;
891 const VOPDInfo *Info =
892 getVOPDInfoFromComponentOpcodes(OpX, OpY, EncodingFamily, VOPD3);
893 return Info ? Info->Opcode : -1;
894}
895
896std::pair<unsigned, unsigned> getVOPDComponents(unsigned VOPDOpcode) {
897 const VOPDInfo *Info = getVOPDOpcodeHelper(VOPDOpcode);
898 assert(Info);
899 const auto *OpX = getVOPDBaseFromComponent(Info->OpX);
900 const auto *OpY = getVOPDBaseFromComponent(Info->OpY);
901 assert(OpX && OpY);
902 return {OpX->BaseVOP, OpY->BaseVOP};
903}
904
905namespace VOPD {
906
907ComponentProps::ComponentProps(const MCInstrDesc &OpDesc, bool VOP3Layout) {
909
912 auto TiedIdx = OpDesc.getOperandConstraint(Component::SRC2, MCOI::TIED_TO);
913 assert(TiedIdx == -1 || TiedIdx == Component::DST);
914 HasSrc2Acc = TiedIdx != -1;
915 Opcode = OpDesc.getOpcode();
916
917 IsVOP3 = VOP3Layout || SIInstrFlags::isVOP3(OpDesc);
918 SrcOperandsNum = AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2) ? 3
919 : AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::imm) ? 3
920 : AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src1) ? 2
921 : 1;
922 assert(SrcOperandsNum <= Component::MAX_SRC_NUM);
923
924 if (Opcode == AMDGPU::V_CNDMASK_B32_e32 ||
925 Opcode == AMDGPU::V_CNDMASK_B32_e64) {
926 // CNDMASK is an awkward exception, it has FP modifiers, but not FP
927 // operands.
928 NumVOPD3Mods = 2;
929 if (IsVOP3)
930 SrcOperandsNum = 3;
931 } else if (Opcode == AMDGPU::V_DOT2_F32_F16 ||
932 Opcode == AMDGPU::V_DOT2_F32_BF16) {
933 // VOP3P opcodes that have VOPD but don't have VOP2 version. Using VOPD3
934 // path in getIndexOfSrcInMCOperands to get correct src operand indexes,
935 // but generating VOPD, not VOPD3.
936 NumVOPD3Mods = SrcOperandsNum;
937 } else if (isSISrcFPOperand(OpDesc,
938 getNamedOperandIdx(Opcode, OpName::src0))) {
939 // All FP VOPD instructions have Neg modifiers for all operands except
940 // for tied src2.
941 NumVOPD3Mods = SrcOperandsNum;
942 if (HasSrc2Acc)
943 --NumVOPD3Mods;
944 }
945
946 if (SIInstrFlags::isVOP3(OpDesc))
947 return;
948
949 auto OperandsNum = OpDesc.getNumOperands();
950 unsigned CompOprIdx;
951 for (CompOprIdx = Component::SRC1; CompOprIdx < OperandsNum; ++CompOprIdx) {
952 if (OpDesc.operands()[CompOprIdx].OperandType == AMDGPU::OPERAND_KIMM32) {
953 MandatoryLiteralIdx = CompOprIdx;
954 break;
955 }
956 }
957}
958
960 return getNamedOperandIdx(Opcode, OpName::bitop3);
961}
962
963unsigned ComponentInfo::getIndexInParsedOperands(unsigned CompOprIdx) const {
964 assert(CompOprIdx < Component::MAX_OPR_NUM);
965
966 if (CompOprIdx == Component::DST)
968
969 auto CompSrcIdx = CompOprIdx - Component::DST_NUM;
970 if (CompSrcIdx < getCompParsedSrcOperandsNum())
971 return getIndexOfSrcInParsedOperands(CompSrcIdx);
972
973 // The specified operand does not exist.
974 return 0;
975}
976
978 std::function<MCRegister(unsigned, unsigned)> GetRegIdx,
979 const MCRegisterInfo &MRI, bool SkipSrc, bool AllowSameVGPR,
980 bool VOPD3) const {
981
982 auto OpXRegs = getRegIndices(ComponentIndex::X, GetRegIdx,
983 CompInfo[ComponentIndex::X].isVOP3());
984 auto OpYRegs = getRegIndices(ComponentIndex::Y, GetRegIdx,
985 CompInfo[ComponentIndex::Y].isVOP3());
986
987 const auto banksOverlap = [&MRI](MCRegister X, MCRegister Y,
988 unsigned BanksMask) -> bool {
989 MCRegister BaseX = MRI.getSubReg(X, AMDGPU::sub0);
990 MCRegister BaseY = MRI.getSubReg(Y, AMDGPU::sub0);
991 if (!BaseX)
992 BaseX = X;
993 if (!BaseY)
994 BaseY = Y;
995 if ((BaseX.id() & BanksMask) == (BaseY.id() & BanksMask))
996 return true;
997 if (BaseX != X /* This is 64-bit register */ &&
998 ((BaseX.id() + 1) & BanksMask) == (BaseY.id() & BanksMask))
999 return true;
1000 if (BaseY != Y &&
1001 (BaseX.id() & BanksMask) == ((BaseY.id() + 1) & BanksMask))
1002 return true;
1003
1004 // If both are 64-bit bank conflict will be detected yet while checking
1005 // the first subreg.
1006 return false;
1007 };
1008
1009 unsigned CompOprIdx;
1010 for (CompOprIdx = 0; CompOprIdx < Component::MAX_OPR_NUM; ++CompOprIdx) {
1011 unsigned BanksMasks = VOPD3 ? VOPD3_VGPR_BANK_MASKS[CompOprIdx]
1012 : VOPD_VGPR_BANK_MASKS[CompOprIdx];
1013 if (!OpXRegs[CompOprIdx] || !OpYRegs[CompOprIdx])
1014 continue;
1015
1016 if (getVGPREncodingMSBs(OpXRegs[CompOprIdx], MRI) !=
1017 getVGPREncodingMSBs(OpYRegs[CompOprIdx], MRI))
1018 return CompOprIdx;
1019
1020 if (SkipSrc && CompOprIdx >= Component::DST_NUM)
1021 continue;
1022
1023 if (CompOprIdx < Component::DST_NUM) {
1024 // Even if we do not check vdst parity, vdst operands still shall not
1025 // overlap.
1026 if (MRI.regsOverlap(OpXRegs[CompOprIdx], OpYRegs[CompOprIdx]))
1027 return CompOprIdx;
1028 if (VOPD3) // No need to check dst parity.
1029 continue;
1030 }
1031
1032 if (banksOverlap(OpXRegs[CompOprIdx], OpYRegs[CompOprIdx], BanksMasks) &&
1033 (!AllowSameVGPR || CompOprIdx < Component::DST_NUM ||
1034 OpXRegs[CompOprIdx] != OpYRegs[CompOprIdx]))
1035 return CompOprIdx;
1036 }
1037
1038 return {};
1039}
1040
1041// Return an array of VGPR registers [DST,SRC0,SRC1,SRC2] used
1042// by the specified component. If an operand is unused
1043// or is not a VGPR, the corresponding value is 0.
1044//
1045// GetRegIdx(Component, MCOperandIdx) must return a VGPR register index
1046// for the specified component and MC operand. The callback must return 0
1047// if the operand is not a register or not a VGPR.
1049InstInfo::getRegIndices(unsigned CompIdx,
1050 std::function<MCRegister(unsigned, unsigned)> GetRegIdx,
1051 bool VOPD3) const {
1052 assert(CompIdx < COMPONENTS_NUM);
1053
1054 const auto &Comp = CompInfo[CompIdx];
1056
1057 RegIndices[DST] = GetRegIdx(CompIdx, Comp.getIndexOfDstInMCOperands());
1058
1059 for (unsigned CompOprIdx : {SRC0, SRC1, SRC2}) {
1060 unsigned CompSrcIdx = CompOprIdx - DST_NUM;
1061 RegIndices[CompOprIdx] =
1062 Comp.hasRegSrcOperand(CompSrcIdx)
1063 ? GetRegIdx(CompIdx,
1064 Comp.getIndexOfSrcInMCOperands(CompSrcIdx, VOPD3))
1065 : MCRegister();
1066 }
1067 return RegIndices;
1068}
1069
1070} // namespace VOPD
1071
1073 return VOPD::InstInfo(OpX, OpY);
1074}
1075
1077 const MCInstrInfo *InstrInfo) {
1078 auto [OpX, OpY] = getVOPDComponents(VOPDOpcode);
1079 const auto &OpXDesc = InstrInfo->get(OpX);
1080 const auto &OpYDesc = InstrInfo->get(OpY);
1081 bool VOPD3 = SIInstrFlags::isVOPD3(*InstrInfo, VOPDOpcode);
1083 VOPD::ComponentInfo OpYInfo(OpYDesc, OpXInfo, VOPD3);
1084 return VOPD::InstInfo(OpXInfo, OpYInfo);
1085}
1086
1088 StringRef FeatureString) {
1090 STI.getFeatureBits().test(FeatureXNACKOnOffModes)
1091 ? TargetIDSetting::Any
1092 : TargetIDSetting::Unsupported,
1093 STI.getFeatureBits().test(FeatureSupportsSRAMECC)
1094 ? TargetIDSetting::Any
1095 : TargetIDSetting::Unsupported);
1096
1097 // Check if xnack or sramecc is explicitly enabled or disabled. In the
1098 // absence of the target features we assume we must generate code that can run
1099 // in any environment.
1100 SubtargetFeatures Features(FeatureString);
1101 std::optional<bool> XnackRequested;
1102 std::optional<bool> SramEccRequested;
1103
1104 for (const std::string &Feature : Features.getFeatures()) {
1105 if (Feature == "+xnack")
1106 XnackRequested = true;
1107 else if (Feature == "-xnack")
1108 XnackRequested = false;
1109 else if (Feature == "+sramecc")
1110 SramEccRequested = true;
1111 else if (Feature == "-sramecc")
1112 SramEccRequested = false;
1113 }
1114
1115 // Only allow changing xnack setting if the target supports on/off modes.
1116 // Targets without on/off mode support keep their initial setting
1117 // (Unsupported).
1118
1119 bool XnackSupported = STI.getFeatureBits().test(FeatureXNACKOnOffModes);
1120 bool SramEccSupported = TargetID.isSramEccSupported();
1121
1122 if (XnackRequested) {
1123 if (XnackSupported) {
1124 TargetID.setXnackSetting(*XnackRequested ? TargetIDSetting::On
1125 : TargetIDSetting::Off);
1126 } else {
1127 // If a specific xnack setting was requested and this GPU does not support
1128 // xnack emit a warning. Setting will remain set to "Unsupported".
1129 if (*XnackRequested) {
1130 errs() << "warning: xnack 'On' was requested for a processor that does "
1131 "not support it!\n";
1132 } else {
1133 errs() << "warning: xnack 'Off' was requested for a processor that "
1134 "does not support it!\n";
1135 }
1136 }
1137 }
1138
1139 if (SramEccRequested) {
1140 if (SramEccSupported) {
1141 TargetID.setSramEccSetting(*SramEccRequested ? TargetIDSetting::On
1142 : TargetIDSetting::Off);
1143 } else {
1144 // If a specific sramecc setting was requested and this GPU does not
1145 // support sramecc emit a warning. Setting will remain set to
1146 // "Unsupported".
1147 if (*SramEccRequested) {
1148 errs() << "warning: sramecc 'On' was requested for a processor that "
1149 "does not support it!\n";
1150 } else {
1151 errs() << "warning: sramecc 'Off' was requested for a processor that "
1152 "does not support it!\n";
1153 }
1154 }
1155 }
1156
1157 return TargetID;
1158}
1159
1160namespace IsaInfo {
1161
1163 if (STI.getFeatureBits().test(FeatureInstCacheLineSize128))
1164 return 128;
1165 if (STI.getFeatureBits().test(FeatureInstCacheLineSize64))
1166 return 64;
1167 return 64;
1168}
1169
1170unsigned getWavefrontSize(const MCSubtargetInfo &STI) {
1171 if (STI.getFeatureBits().test(FeatureWavefrontSize16))
1172 return 16;
1173 if (STI.getFeatureBits().test(FeatureWavefrontSize32))
1174 return 32;
1175
1176 return 64;
1177}
1178
1179// Maximum LDS a single work-group can address. This is a fixed HW cap. It does
1180// not depend on how many SIMDs a work-group runs on.
1182 if (STI.getFeatureBits().test(FeatureAddressableLocalMemorySize32768))
1183 return 32768;
1184 if (STI.getFeatureBits().test(FeatureAddressableLocalMemorySize65536))
1185 return 65536;
1186 if (STI.getFeatureBits().test(FeatureAddressableLocalMemorySize163840))
1187 return 163840;
1188 if (STI.getFeatureBits().test(FeatureAddressableLocalMemorySize196608))
1189 return 196608;
1190 if (STI.getFeatureBits().test(FeatureAddressableLocalMemorySize327680))
1191 return 327680;
1192 return 32768;
1193}
1194
1195// Total physical size of LDS on the block, in bytes. On targets with
1196// FeatureHalfAddressablePhysicalLocalMemory the physical block is twice the
1197// addressable size (gfx10/11/12, 128k physical and 64k addressable). On other
1198// targets it is equal to the addressable size.
1199static unsigned getPhysicalLocalMemorySize(const MCSubtargetInfo &STI) {
1200 unsigned Addressable = getMaxHWAddressableLocalMemorySize(STI);
1201 if (STI.getFeatureBits().test(FeatureHalfAddressablePhysicalLocalMemory))
1202 return 2 * Addressable;
1203 return Addressable;
1204}
1205
1206// Sizes in use, by generation (addressable / physical block):
1207// gfx6 : 32 KiB
1208// gfx7 / gfx8 / gfx9: 64 KiB
1209// gfx9.5 (gfx950) : 160 KiB
1210// gfx10 / 11 / 12 : 64 KiB addressable, 128 KiB physical block
1211// gfx12.5 (gfx1250) : 320 KiB (always runs on four SIMDs)
1212// gfx13 : 192 KiB on four SIMDs, 96 KiB on two
1213// Total available in the current mode. The physical size is halved when a
1214// work-group runs on two SIMDs.
1216 unsigned Size = getPhysicalLocalMemorySize(STI);
1217 if (!isFullSIMDMode(STI))
1218 Size /= 2;
1219 return Size;
1220}
1221
1222// What one work-group can allocate in the current mode. This is the HW
1223// addressable cap, but never more than the total available in the current mode.
1225 return std::min(getMaxHWAddressableLocalMemorySize(STI),
1226 getLocalMemorySize(STI));
1227}
1228
1229unsigned getEUsPerCU(const MCSubtargetInfo &STI) {
1230 // Four SIMD32s when a work-group runs on all of them, two otherwise.
1231 return isFullSIMDMode(STI) ? 4 : 2;
1232}
1233
1235 unsigned FlatWorkGroupSize) {
1236 assert(FlatWorkGroupSize != 0);
1237 if (!STI.getTargetTriple().isAMDGCN())
1238 return 8;
1239 unsigned MaxWaves = getMaxWavesPerEU(STI) * getEUsPerCU(STI);
1240 unsigned N = getWavesPerWorkGroup(STI, FlatWorkGroupSize);
1241 if (N == 1) {
1242 // Single-wave workgroups don't consume barrier resources.
1243 return MaxWaves;
1244 }
1245
1246 unsigned MaxBarriers = 16;
1247 if (isGFX10Plus(STI) && !STI.getFeatureBits().test(FeatureCuMode))
1248 MaxBarriers = 32;
1249
1250 return std::min(MaxWaves / N, MaxBarriers);
1251}
1252
1253unsigned getMinWavesPerEU(const MCSubtargetInfo &STI) { return 1; }
1254
1255unsigned getMaxWavesPerEU(const MCSubtargetInfo &STI) {
1256 // FIXME: Need to take scratch memory into account.
1257 if (isGFX90A(STI))
1258 return 8;
1259 if (!isGFX10Plus(STI))
1260 return 10;
1261 return hasGFX10_3Insts(STI) ? 16 : 20;
1262}
1263
1265 unsigned FlatWorkGroupSize) {
1266 return divideCeil(getWavesPerWorkGroup(STI, FlatWorkGroupSize),
1267 getEUsPerCU(STI));
1268}
1269
1270unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo &STI) { return 1; }
1271
1273 unsigned FlatWorkGroupSize) {
1274 return divideCeil(FlatWorkGroupSize, getWavefrontSize(STI));
1275}
1276
1277unsigned getSGPREncodingGranule(const MCSubtargetInfo &STI) { return 8; }
1278
1279// Per-wave SGPRs reserved for the trap handler when enabled.
1280static unsigned getSGPRTrapHandlerReserve(const MCSubtargetInfo &STI) {
1281 return STI.getFeatureBits().test(FeatureTrapHandler) ? TRAP_NUM_SGPRS : 0;
1282}
1283
1284// Per-wave SGPR budget (before the addressable clamp): take off the trap
1285// reserve, round down to \p Granule. Shared by getMinNumSGPRs() and
1286// getMaxNumSGPRs(); getOccupancyWithNumSGPRs() is the closed-form algebraic
1287// inverse of this same budget (it does not call this helper), so the two encode
1288// one model.
1289static unsigned getSGPRBudgetPerWave(unsigned TotalNumSGPRs,
1290 unsigned WavesPerEU, unsigned TrapReserve,
1291 unsigned Granule) {
1292 assert(WavesPerEU != 0 && Granule != 0);
1293 unsigned Budget = TotalNumSGPRs / WavesPerEU;
1294 Budget -= std::min(Budget, TrapReserve);
1295 return alignDown(Budget, Granule);
1296}
1297
1298unsigned getMinNumSGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU) {
1299 assert(WavesPerEU != 0);
1300
1302 if (Version.Major >= 10)
1303 return 0;
1304
1305 if (WavesPerEU >= getMaxWavesPerEU(STI))
1306 return 0;
1307
1308 GPUKind Kind = parseArchAMDGCN(STI.getCPU());
1309 unsigned MinNumSGPRs =
1310 getSGPRBudgetPerWave(getTotalNumSGPRs(Kind), WavesPerEU + 1,
1312 getSGPRAllocGranule(Kind)) +
1313 1;
1314 return std::min(MinNumSGPRs, getAddressableNumSGPRs(Kind));
1315}
1316
1317unsigned getMaxNumSGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU,
1318 bool Addressable) {
1319 assert(WavesPerEU != 0);
1320
1321 GPUKind Kind = parseArchAMDGCN(STI.getCPU());
1322 unsigned AddressableNumSGPRs = getAddressableNumSGPRs(Kind);
1324 if (Version.Major >= 10)
1325 return Addressable ? AddressableNumSGPRs : 108;
1326 if (Version.Major >= 8 && !Addressable)
1327 AddressableNumSGPRs = 112;
1328 unsigned MaxNumSGPRs = getSGPRBudgetPerWave(
1329 getTotalNumSGPRs(Kind), WavesPerEU, getSGPRTrapHandlerReserve(STI),
1330 getSGPRAllocGranule(Kind));
1331 return std::min(MaxNumSGPRs, AddressableNumSGPRs);
1332}
1333
1335 // From GFX10 on the SGPR file is large enough that SGPRs never limit
1336 // occupancy. Kept as one capability so callers don't each test the version.
1337 return getIsaVersion(STI.getCPU()).Major < 10;
1338}
1339
1340unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed,
1341 bool FlatScrUsed, bool XNACKUsed) {
1342 unsigned ExtraSGPRs = 0;
1343 if (VCCUsed)
1344 ExtraSGPRs = 2;
1345
1347 if (Version.Major >= 10)
1348 return ExtraSGPRs;
1349
1350 if (Version.Major < 8) {
1351 if (FlatScrUsed)
1352 ExtraSGPRs = 4;
1353 } else {
1354 if (XNACKUsed)
1355 ExtraSGPRs = 4;
1356
1357 if (FlatScrUsed ||
1358 STI.getFeatureBits().test(AMDGPU::FeatureArchitectedFlatScratch))
1359 ExtraSGPRs = 6;
1360 }
1361
1362 return ExtraSGPRs;
1363}
1364
1365unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed,
1366 bool FlatScrUsed) {
1367 return getNumExtraSGPRs(STI, VCCUsed, FlatScrUsed,
1368 STI.getFeatureBits().test(AMDGPU::FeatureXNACK));
1369}
1370
1371static unsigned getGranulatedNumRegisterBlocks(unsigned NumRegs,
1372 unsigned Granule) {
1373 return divideCeil(std::max(1u, NumRegs), Granule);
1374}
1375
1376unsigned getNumSGPRBlocks(const MCSubtargetInfo &STI, unsigned NumSGPRs) {
1377 // SGPRBlocks is actual number of SGPR blocks minus 1.
1379 1;
1380}
1381
1383 unsigned DynamicVGPRBlockSize,
1384 std::optional<bool> EnableWavefrontSize32) {
1385 if (STI.getFeatureBits().test(FeatureGFX90AInsts))
1386 return 8;
1387
1388 if (DynamicVGPRBlockSize != 0)
1389 return DynamicVGPRBlockSize;
1390
1391 bool IsWave32 = EnableWavefrontSize32
1392 ? *EnableWavefrontSize32
1393 : STI.getFeatureBits().test(FeatureWavefrontSize32);
1394
1395 if (STI.getFeatureBits().test(Feature1536VGPRs))
1396 return IsWave32 ? 24 : 12;
1397
1398 if (hasGFX10_3Insts(STI))
1399 return IsWave32 ? 16 : 8;
1400
1401 return IsWave32 ? 8 : 4;
1402}
1403
1405 std::optional<bool> EnableWavefrontSize32) {
1406 if (STI.getFeatureBits().test(FeatureGFX90AInsts))
1407 return 8;
1408
1409 bool IsWave32 = EnableWavefrontSize32
1410 ? *EnableWavefrontSize32
1411 : STI.getFeatureBits().test(FeatureWavefrontSize32);
1412
1413 if (STI.getFeatureBits().test(Feature1024AddressableVGPRs))
1414 return IsWave32 ? 16 : 8;
1415
1416 return IsWave32 ? 8 : 4;
1417}
1418
1419unsigned getArchVGPRAllocGranule() { return 4; }
1420
1421unsigned getTotalNumVGPRs(const MCSubtargetInfo &STI) {
1422 if (STI.getFeatureBits().test(FeatureGFX90AInsts))
1423 return 512;
1424 if (!isGFX10Plus(STI))
1425 return 256;
1426 bool IsWave32 = STI.getFeatureBits().test(FeatureWavefrontSize32);
1427 if (STI.getFeatureBits().test(Feature1536VGPRs))
1428 return IsWave32 ? 1536 : 768;
1429 return IsWave32 ? 1024 : 512;
1430}
1431
1433 const auto &Features = STI.getFeatureBits();
1434 if (Features.test(Feature1024AddressableVGPRs))
1435 return Features.test(FeatureWavefrontSize32) ? 1024 : 512;
1436 return 256;
1437}
1438
1440 unsigned DynamicVGPRBlockSize) {
1441 const auto &Features = STI.getFeatureBits();
1442 if (Features.test(FeatureGFX90AInsts))
1443 return 512;
1444
1445 if (DynamicVGPRBlockSize != 0) {
1446 // On GFX12 we can allocate at most MaxDynamicVGPRBlocks blocks of VGPRs.
1447 return MaxDynamicVGPRBlocks *
1448 getVGPRAllocGranule(STI, DynamicVGPRBlockSize);
1449 }
1450 return getAddressableNumArchVGPRs(STI);
1451}
1452
1454 unsigned NumVGPRs,
1455 unsigned DynamicVGPRBlockSize) {
1457 NumVGPRs, getVGPRAllocGranule(STI, DynamicVGPRBlockSize),
1459}
1460
1461unsigned getNumWavesPerEUWithNumVGPRs(unsigned NumVGPRs, unsigned Granule,
1462 unsigned MaxWaves,
1463 unsigned TotalNumVGPRs) {
1464 if (NumVGPRs < Granule)
1465 return MaxWaves;
1466 unsigned RoundedRegs = alignTo(NumVGPRs, Granule);
1467 return std::min(std::max(TotalNumVGPRs / RoundedRegs, 1u), MaxWaves);
1468}
1469
1470unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves,
1471 unsigned TotalNumSGPRs, unsigned Granule,
1472 unsigned TrapReserve) {
1473 // Closed-form inverse of getMaxNumSGPRs(): the budget condition
1474 // SGPRs <= alignDown(TotalNumSGPRs / W - TrapReserve, Granule)
1475 // solves to W <= TotalNumSGPRs / (alignTo(SGPRs, Granule) + TrapReserve).
1476 unsigned PerWave = alignTo(SGPRs, Granule) + TrapReserve;
1477 return PerWave ? std::clamp(TotalNumSGPRs / PerWave, 1u, MaxWaves) : MaxWaves;
1478}
1479
1480unsigned getOccupancyWithNumSGPRs(const MCSubtargetInfo &STI, unsigned SGPRs) {
1481 unsigned MaxWaves = getMaxWavesPerEU(STI);
1482
1483 if (!isSGPROccupancyLimited(STI))
1484 return MaxWaves;
1485
1486 GPUKind Kind = parseArchAMDGCN(STI.getCPU());
1487 return getOccupancyWithNumSGPRs(SGPRs, MaxWaves, getTotalNumSGPRs(Kind),
1488 getSGPRAllocGranule(Kind),
1490}
1491
1492unsigned getMinNumVGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU,
1493 unsigned DynamicVGPRBlockSize) {
1494 assert(WavesPerEU != 0);
1495
1496 // In dynamic VGPR mode, (static) occupancy does not depend on VGPR usage,
1497 // so getMaxNumVGPRs does not depend on WavesPerEU, and thus we need to return
1498 // zero because there is no nonzero VGPR usage N where going below N
1499 // achieves higher (static) occupancy.
1500 bool DynamicVGPREnabled = (DynamicVGPRBlockSize != 0);
1501 if (DynamicVGPREnabled)
1502 return 0;
1503
1504 unsigned MaxWavesPerEU = getMaxWavesPerEU(STI);
1505 if (WavesPerEU >= MaxWavesPerEU)
1506 return 0;
1507
1508 unsigned TotNumVGPRs = getTotalNumVGPRs(STI);
1509 unsigned AddrsableNumVGPRs =
1510 getAddressableNumVGPRs(STI, DynamicVGPRBlockSize);
1511 unsigned Granule = getVGPRAllocGranule(STI, DynamicVGPRBlockSize);
1512 unsigned MaxNumVGPRs = alignDown(TotNumVGPRs / WavesPerEU, Granule);
1513
1514 if (MaxNumVGPRs == alignDown(TotNumVGPRs / MaxWavesPerEU, Granule))
1515 return 0;
1516
1517 unsigned MinWavesPerEU = getNumWavesPerEUWithNumVGPRs(STI, AddrsableNumVGPRs,
1518 DynamicVGPRBlockSize);
1519 if (WavesPerEU < MinWavesPerEU)
1520 return getMinNumVGPRs(STI, MinWavesPerEU, DynamicVGPRBlockSize);
1521
1522 unsigned MaxNumVGPRsNext = alignDown(TotNumVGPRs / (WavesPerEU + 1), Granule);
1523 unsigned MinNumVGPRs = 1 + std::min(MaxNumVGPRs - Granule, MaxNumVGPRsNext);
1524 return std::min(MinNumVGPRs, AddrsableNumVGPRs);
1525}
1526
1527unsigned getMaxNumVGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU,
1528 unsigned DynamicVGPRBlockSize) {
1529 assert(WavesPerEU != 0);
1530
1531 // In dynamic VGPR mode, WavesPerEU does not imply a VGPR limit.
1532 bool DynamicVGPREnabled = (DynamicVGPRBlockSize != 0);
1533 unsigned MaxNumVGPRs =
1534 DynamicVGPREnabled
1535 ? getTotalNumVGPRs(STI)
1536 : alignDown(getTotalNumVGPRs(STI) / WavesPerEU,
1537 getVGPRAllocGranule(STI, DynamicVGPRBlockSize));
1538 unsigned AddressableNumVGPRs =
1539 getAddressableNumVGPRs(STI, DynamicVGPRBlockSize);
1540 return std::min(MaxNumVGPRs, AddressableNumVGPRs);
1541}
1542
1543unsigned getEncodedNumVGPRBlocks(const MCSubtargetInfo &STI, unsigned NumVGPRs,
1544 std::optional<bool> EnableWavefrontSize32) {
1546 NumVGPRs, getVGPREncodingGranule(STI, EnableWavefrontSize32)) -
1547 1;
1548}
1549
1551 unsigned NumVGPRs,
1552 unsigned DynamicVGPRBlockSize,
1553 std::optional<bool> EnableWavefrontSize32) {
1555 NumVGPRs,
1556 getVGPRAllocGranule(STI, DynamicVGPRBlockSize, EnableWavefrontSize32));
1557}
1558} // end namespace IsaInfo
1559
1561 const MCSubtargetInfo &STI) {
1563 KernelCode.amd_kernel_code_version_major = 1;
1564 KernelCode.amd_kernel_code_version_minor = 2;
1565 KernelCode.amd_machine_kind = 1; // AMD_MACHINE_KIND_AMDGPU
1566 KernelCode.amd_machine_version_major = Version.Major;
1567 KernelCode.amd_machine_version_minor = Version.Minor;
1568 KernelCode.amd_machine_version_stepping = Version.Stepping;
1570 if (STI.getFeatureBits().test(FeatureWavefrontSize32)) {
1571 KernelCode.wavefront_size = 5;
1573 } else {
1574 KernelCode.wavefront_size = 6;
1575 }
1576
1577 // If the code object does not support indirect functions, then the value must
1578 // be 0xffffffff.
1579 KernelCode.call_convention = -1;
1580
1581 // These alignment values are specified in powers of two, so alignment =
1582 // 2^n. The minimum alignment is 2^4 = 16.
1583 KernelCode.kernarg_segment_alignment = 4;
1584 KernelCode.group_segment_alignment = 4;
1585 KernelCode.private_segment_alignment = 4;
1586
1587 if (Version.Major >= 10) {
1588 KernelCode.compute_pgm_resource_registers |=
1589 S_00B848_WGP_MODE(STI.getFeatureBits().test(FeatureCuMode) ? 0 : 1) |
1591 }
1592}
1593
1596}
1597
1600}
1601
1603 unsigned AS = GV->getAddressSpace();
1604 return AS == AMDGPUAS::CONSTANT_ADDRESS ||
1606}
1607
1609 return TT.getArch() == Triple::r600;
1610}
1611
1612static bool isValidRegPrefix(char C) {
1613 return C == 'v' || C == 's' || C == 'a';
1614}
1615
1616std::tuple<char, unsigned, unsigned> parseAsmPhysRegName(StringRef RegName) {
1617 char Kind = RegName.front();
1618 if (!isValidRegPrefix(Kind))
1619 return {};
1620
1621 RegName = RegName.drop_front();
1622 if (RegName.consume_front("[")) {
1623 unsigned Idx, End;
1624 bool Failed = RegName.consumeInteger(10, Idx);
1625 Failed |= !RegName.consume_front(":");
1626 Failed |= RegName.consumeInteger(10, End);
1627 Failed |= !RegName.consume_back("]");
1628 if (!Failed) {
1629 unsigned NumRegs = End - Idx + 1;
1630 if (NumRegs > 1)
1631 return {Kind, Idx, NumRegs};
1632 }
1633 } else {
1634 unsigned Idx;
1635 bool Failed = RegName.getAsInteger(10, Idx);
1636 if (!Failed)
1637 return {Kind, Idx, 1};
1638 }
1639
1640 return {};
1641}
1642
1643std::tuple<char, unsigned, unsigned>
1645 StringRef RegName = Constraint;
1646 if (!RegName.consume_front("{") || !RegName.consume_back("}"))
1647 return {};
1649}
1650
1651std::pair<unsigned, unsigned>
1653 std::pair<unsigned, unsigned> Default,
1654 bool OnlyFirstRequired) {
1655 if (auto Attr = getIntegerPairAttribute(F, Name, OnlyFirstRequired))
1656 return {Attr->first, Attr->second.value_or(Default.second)};
1657 return Default;
1658}
1659
1660std::optional<std::pair<unsigned, std::optional<unsigned>>>
1662 bool OnlyFirstRequired) {
1663 Attribute A = F.getFnAttribute(Name);
1664 if (!A.isStringAttribute())
1665 return std::nullopt;
1666
1667 LLVMContext &Ctx = F.getContext();
1668 std::pair<unsigned, std::optional<unsigned>> Ints;
1669 std::pair<StringRef, StringRef> Strs = A.getValueAsString().split(',');
1670 if (Strs.first.trim().getAsInteger(0, Ints.first)) {
1671 Ctx.emitError("can't parse first integer attribute " + Name);
1672 return std::nullopt;
1673 }
1674 unsigned Second = 0;
1675 if (Strs.second.trim().getAsInteger(0, Second)) {
1676 if (!OnlyFirstRequired || !Strs.second.trim().empty()) {
1677 Ctx.emitError("can't parse second integer attribute " + Name);
1678 return std::nullopt;
1679 }
1680 } else {
1681 Ints.second = Second;
1682 }
1683
1684 return Ints;
1685}
1686
1688 unsigned Size,
1689 unsigned DefaultVal) {
1690 std::optional<SmallVector<unsigned>> R =
1692 return R.has_value() ? *R : SmallVector<unsigned>(Size, DefaultVal);
1693}
1694
1695std::optional<SmallVector<unsigned>>
1697 assert(Size > 2);
1698 LLVMContext &Ctx = F.getContext();
1699
1700 Attribute A = F.getFnAttribute(Name);
1701 if (!A.isValid())
1702 return std::nullopt;
1703 if (!A.isStringAttribute()) {
1704 Ctx.emitError(Name + " is not a string attribute");
1705 return std::nullopt;
1706 }
1707
1709
1710 StringRef S = A.getValueAsString();
1711 unsigned i = 0;
1712 for (; !S.empty() && i < Size; i++) {
1713 std::pair<StringRef, StringRef> Strs = S.split(',');
1714 unsigned IntVal;
1715 if (Strs.first.trim().getAsInteger(0, IntVal)) {
1716 Ctx.emitError("can't parse integer attribute " + Strs.first + " in " +
1717 Name);
1718 return std::nullopt;
1719 }
1720 Vals[i] = IntVal;
1721 S = Strs.second;
1722 }
1723
1724 if (!S.empty() || i < Size) {
1725 Ctx.emitError("attribute " + Name +
1726 " has incorrect number of integers; expected " +
1728 return std::nullopt;
1729 }
1730 return Vals;
1731}
1732
1734 return getIntegerVecAttribute(F, "amdgpu-max-num-workgroups", 3,
1735 std::numeric_limits<uint32_t>::max());
1736}
1737
1738bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val) {
1739 assert((MD.getNumOperands() % 2 == 0) && "invalid number of operands!");
1740 for (unsigned I = 0, E = MD.getNumOperands() / 2; I != E; ++I) {
1741 auto Low =
1742 mdconst::extract<ConstantInt>(MD.getOperand(2 * I + 0))->getValue();
1743 auto High =
1744 mdconst::extract<ConstantInt>(MD.getOperand(2 * I + 1))->getValue();
1745 // There are two types of [A; B) ranges:
1746 // A < B, e.g. [4; 5) which is a range that only includes 4.
1747 // A > B, e.g. [5; 4) which is a range that wraps around and includes
1748 // everything except 4.
1749 if (Low.ult(High)) {
1750 if (Low.ule(Val) && High.ugt(Val))
1751 return true;
1752 } else {
1753 if (Low.uge(Val) && High.ult(Val))
1754 return true;
1755 }
1756 }
1757
1758 return false;
1759}
1760
1762 return (1 << (getVmcntBitWidthLo(Version.Major) +
1763 getVmcntBitWidthHi(Version.Major))) -
1764 1;
1765}
1766
1768 return (1 << getLoadcntBitWidth(Version.Major)) - 1;
1769}
1770
1772 return (1 << getSamplecntBitWidth(Version.Major)) - 1;
1773}
1774
1776 return (1 << getBvhcntBitWidth(Version.Major)) - 1;
1777}
1778
1780 return (1 << getExpcntBitWidth(Version.Major)) - 1;
1781}
1782
1784 return (1 << getLgkmcntBitWidth(Version.Major)) - 1;
1785}
1786
1788 return (1 << getDscntBitWidth(Version.Major)) - 1;
1789}
1790
1792 return (1 << getKmcntBitWidth(Version.Major)) - 1;
1793}
1794
1796 return (1 << getXcntBitWidth(Version.Major, Version.Minor)) - 1;
1797}
1798
1800 return (1 << getAsynccntBitWidth(Version.Major, Version.Minor)) - 1;
1801}
1802
1804 return (1 << getStorecntBitWidth(Version.Major)) - 1;
1805}
1806
1808 unsigned VmcntLo = getBitMask(getVmcntBitShiftLo(Version.Major),
1809 getVmcntBitWidthLo(Version.Major));
1810 unsigned Expcnt = getBitMask(getExpcntBitShift(Version.Major),
1811 getExpcntBitWidth(Version.Major));
1812 unsigned Lgkmcnt = getBitMask(getLgkmcntBitShift(Version.Major),
1813 getLgkmcntBitWidth(Version.Major));
1814 unsigned VmcntHi = getBitMask(getVmcntBitShiftHi(Version.Major),
1815 getVmcntBitWidthHi(Version.Major));
1816 return VmcntLo | Expcnt | Lgkmcnt | VmcntHi;
1817}
1818
1819unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt) {
1820 unsigned VmcntLo = unpackBits(Waitcnt, getVmcntBitShiftLo(Version.Major),
1821 getVmcntBitWidthLo(Version.Major));
1822 unsigned VmcntHi = unpackBits(Waitcnt, getVmcntBitShiftHi(Version.Major),
1823 getVmcntBitWidthHi(Version.Major));
1824 return VmcntLo | VmcntHi << getVmcntBitWidthLo(Version.Major);
1825}
1826
1827unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt) {
1828 return unpackBits(Waitcnt, getExpcntBitShift(Version.Major),
1829 getExpcntBitWidth(Version.Major));
1830}
1831
1832unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt) {
1833 return unpackBits(Waitcnt, getLgkmcntBitShift(Version.Major),
1834 getLgkmcntBitWidth(Version.Major));
1835}
1836
1837unsigned decodeLoadcnt(const IsaVersion &Version, unsigned Waitcnt) {
1838 return unpackBits(Waitcnt, getLoadcntStorecntBitShift(Version.Major),
1839 getLoadcntBitWidth(Version.Major));
1840}
1841
1842unsigned decodeStorecnt(const IsaVersion &Version, unsigned Waitcnt) {
1843 return unpackBits(Waitcnt, getLoadcntStorecntBitShift(Version.Major),
1844 getStorecntBitWidth(Version.Major));
1845}
1846
1847unsigned decodeDscnt(const IsaVersion &Version, unsigned Waitcnt) {
1848 return unpackBits(Waitcnt, getDscntBitShift(Version.Major),
1849 getDscntBitWidth(Version.Major));
1850}
1851
1852void decodeWaitcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned &Vmcnt,
1853 unsigned &Expcnt, unsigned &Lgkmcnt) {
1854 Vmcnt = decodeVmcnt(Version, Waitcnt);
1855 Expcnt = decodeExpcnt(Version, Waitcnt);
1856 Lgkmcnt = decodeLgkmcnt(Version, Waitcnt);
1857}
1858
1859unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt,
1860 unsigned Vmcnt) {
1861 Waitcnt = packBits(Vmcnt, Waitcnt, getVmcntBitShiftLo(Version.Major),
1862 getVmcntBitWidthLo(Version.Major));
1863 return packBits(Vmcnt >> getVmcntBitWidthLo(Version.Major), Waitcnt,
1864 getVmcntBitShiftHi(Version.Major),
1865 getVmcntBitWidthHi(Version.Major));
1866}
1867
1868unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt,
1869 unsigned Expcnt) {
1870 return packBits(Expcnt, Waitcnt, getExpcntBitShift(Version.Major),
1871 getExpcntBitWidth(Version.Major));
1872}
1873
1874unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt,
1875 unsigned Lgkmcnt) {
1876 return packBits(Lgkmcnt, Waitcnt, getLgkmcntBitShift(Version.Major),
1877 getLgkmcntBitWidth(Version.Major));
1878}
1879
1880unsigned encodeWaitcnt(const IsaVersion &Version, unsigned Vmcnt,
1881 unsigned Expcnt, unsigned Lgkmcnt) {
1882 unsigned Waitcnt = getWaitcntBitMask(Version);
1884 Waitcnt = encodeExpcnt(Version, Waitcnt, Expcnt);
1885 Waitcnt = encodeLgkmcnt(Version, Waitcnt, Lgkmcnt);
1886 return Waitcnt;
1887}
1888
1890 bool IsStore) {
1891 unsigned Dscnt = getBitMask(getDscntBitShift(Version.Major),
1892 getDscntBitWidth(Version.Major));
1893 if (IsStore) {
1894 unsigned Storecnt = getBitMask(getLoadcntStorecntBitShift(Version.Major),
1895 getStorecntBitWidth(Version.Major));
1896 return Dscnt | Storecnt;
1897 }
1898 unsigned Loadcnt = getBitMask(getLoadcntStorecntBitShift(Version.Major),
1899 getLoadcntBitWidth(Version.Major));
1900 return Dscnt | Loadcnt;
1901}
1902
1903static unsigned encodeLoadcnt(const IsaVersion &Version, unsigned Waitcnt,
1904 unsigned Loadcnt) {
1905 return packBits(Loadcnt, Waitcnt, getLoadcntStorecntBitShift(Version.Major),
1906 getLoadcntBitWidth(Version.Major));
1907}
1908
1909static unsigned encodeStorecnt(const IsaVersion &Version, unsigned Waitcnt,
1910 unsigned Storecnt) {
1911 return packBits(Storecnt, Waitcnt, getLoadcntStorecntBitShift(Version.Major),
1912 getStorecntBitWidth(Version.Major));
1913}
1914
1915static unsigned encodeDscnt(const IsaVersion &Version, unsigned Waitcnt,
1916 unsigned Dscnt) {
1917 return packBits(Dscnt, Waitcnt, getDscntBitShift(Version.Major),
1918 getDscntBitWidth(Version.Major));
1919}
1920
1921unsigned encodeLoadcntDscnt(const IsaVersion &Version, unsigned Loadcnt,
1922 unsigned Dscnt) {
1923 unsigned Waitcnt = getCombinedCountBitMask(Version, false);
1924 Waitcnt = encodeLoadcnt(Version, Waitcnt, Loadcnt);
1926 return Waitcnt;
1927}
1928
1929unsigned encodeStorecntDscnt(const IsaVersion &Version, unsigned Storecnt,
1930 unsigned Dscnt) {
1931 unsigned Waitcnt = getCombinedCountBitMask(Version, true);
1932 Waitcnt = encodeStorecnt(Version, Waitcnt, Storecnt);
1934 return Waitcnt;
1935}
1936
1937//===----------------------------------------------------------------------===//
1938// Custom Operand Values
1939//===----------------------------------------------------------------------===//
1940
1942 int Size,
1943 const MCSubtargetInfo &STI) {
1944 unsigned Enc = 0;
1945 for (int Idx = 0; Idx < Size; ++Idx) {
1946 const auto &Op = Opr[Idx];
1947 if (Op.isSupported(STI))
1948 Enc |= Op.encode(Op.Default);
1949 }
1950 return Enc;
1951}
1952
1954 int Size, unsigned Code,
1955 bool &HasNonDefaultVal,
1956 const MCSubtargetInfo &STI) {
1957 unsigned UsedOprMask = 0;
1958 HasNonDefaultVal = false;
1959 for (int Idx = 0; Idx < Size; ++Idx) {
1960 const auto &Op = Opr[Idx];
1961 if (!Op.isSupported(STI))
1962 continue;
1963 UsedOprMask |= Op.getMask();
1964 unsigned Val = Op.decode(Code);
1965 if (!Op.isValid(Val))
1966 return false;
1967 HasNonDefaultVal |= (Val != Op.Default);
1968 }
1969 return (Code & ~UsedOprMask) == 0;
1970}
1971
1972static bool decodeCustomOperand(const CustomOperandVal *Opr, int Size,
1973 unsigned Code, int &Idx, StringRef &Name,
1974 unsigned &Val, bool &IsDefault,
1975 const MCSubtargetInfo &STI) {
1976 while (Idx < Size) {
1977 const auto &Op = Opr[Idx++];
1978 if (Op.isSupported(STI)) {
1979 Name = Op.Name;
1980 Val = Op.decode(Code);
1981 IsDefault = (Val == Op.Default);
1982 return true;
1983 }
1984 }
1985
1986 return false;
1987}
1988
1990 int64_t InputVal) {
1991 if (InputVal < 0 || InputVal > Op.Max)
1992 return OPR_VAL_INVALID;
1993 return Op.encode(InputVal);
1994}
1995
1996static int encodeCustomOperand(const CustomOperandVal *Opr, int Size,
1997 const StringRef Name, int64_t InputVal,
1998 unsigned &UsedOprMask,
1999 const MCSubtargetInfo &STI) {
2000 int InvalidId = OPR_ID_UNKNOWN;
2001 for (int Idx = 0; Idx < Size; ++Idx) {
2002 const auto &Op = Opr[Idx];
2003 if (Op.Name == Name) {
2004 if (!Op.isSupported(STI)) {
2005 InvalidId = OPR_ID_UNSUPPORTED;
2006 continue;
2007 }
2008 auto OprMask = Op.getMask();
2009 if (OprMask & UsedOprMask)
2010 return OPR_ID_DUPLICATE;
2011 UsedOprMask |= OprMask;
2012 return encodeCustomOperandVal(Op, InputVal);
2013 }
2014 }
2015 return InvalidId;
2016}
2017
2018//===----------------------------------------------------------------------===//
2019// DepCtr
2020//===----------------------------------------------------------------------===//
2021
2022namespace DepCtr {
2023
2025 static int Default = -1;
2026 if (Default == -1)
2028 return Default;
2029}
2030
2031bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal,
2032 const MCSubtargetInfo &STI) {
2034 HasNonDefaultVal, STI);
2035}
2036
2037bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val,
2038 bool &IsDefault, const MCSubtargetInfo &STI) {
2039 return decodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Code, Id, Name, Val,
2040 IsDefault, STI);
2041}
2042
2043int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask,
2044 const MCSubtargetInfo &STI) {
2045 return encodeCustomOperand(DepCtrInfo, DEP_CTR_SIZE, Name, Val, UsedOprMask,
2046 STI);
2047}
2048
2049unsigned getVaVdstBitMask() { return (1 << getVaVdstBitWidth()) - 1; }
2050
2051unsigned getVaSdstBitMask() { return (1 << getVaSdstBitWidth()) - 1; }
2052
2053unsigned getVaSsrcBitMask() { return (1 << getVaSsrcBitWidth()) - 1; }
2054
2056 return (1 << getHoldCntWidth(Version.Major, Version.Minor)) - 1;
2057}
2058
2059unsigned getVmVsrcBitMask() { return (1 << getVmVsrcBitWidth()) - 1; }
2060
2061unsigned getVaVccBitMask() { return (1 << getVaVccBitWidth()) - 1; }
2062
2063unsigned getSaSdstBitMask() { return (1 << getSaSdstBitWidth()) - 1; }
2064
2065unsigned decodeFieldVmVsrc(unsigned Encoded) {
2066 return unpackBits(Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth());
2067}
2068
2069unsigned decodeFieldVaVdst(unsigned Encoded) {
2070 return unpackBits(Encoded, getVaVdstBitShift(), getVaVdstBitWidth());
2071}
2072
2073unsigned decodeFieldSaSdst(unsigned Encoded) {
2074 return unpackBits(Encoded, getSaSdstBitShift(), getSaSdstBitWidth());
2075}
2076
2077unsigned decodeFieldVaSdst(unsigned Encoded) {
2078 return unpackBits(Encoded, getVaSdstBitShift(), getVaSdstBitWidth());
2079}
2080
2081unsigned decodeFieldVaVcc(unsigned Encoded) {
2082 return unpackBits(Encoded, getVaVccBitShift(), getVaVccBitWidth());
2083}
2084
2085unsigned decodeFieldVaSsrc(unsigned Encoded) {
2086 return unpackBits(Encoded, getVaSsrcBitShift(), getVaSsrcBitWidth());
2087}
2088
2089unsigned decodeFieldHoldCnt(unsigned Encoded, const IsaVersion &Version) {
2090 return unpackBits(Encoded, getHoldCntBitShift(),
2091 getHoldCntWidth(Version.Major, Version.Minor));
2092}
2093
2094unsigned encodeFieldVmVsrc(unsigned Encoded, unsigned VmVsrc) {
2095 return packBits(VmVsrc, Encoded, getVmVsrcBitShift(), getVmVsrcBitWidth());
2096}
2097
2098unsigned encodeFieldVmVsrc(unsigned VmVsrc, const MCSubtargetInfo &STI) {
2099 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2100 return encodeFieldVmVsrc(Encoded, VmVsrc);
2101}
2102
2103unsigned encodeFieldVaVdst(unsigned Encoded, unsigned VaVdst) {
2104 return packBits(VaVdst, Encoded, getVaVdstBitShift(), getVaVdstBitWidth());
2105}
2106
2107unsigned encodeFieldVaVdst(unsigned VaVdst, const MCSubtargetInfo &STI) {
2108 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2109 return encodeFieldVaVdst(Encoded, VaVdst);
2110}
2111
2112unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst) {
2113 return packBits(SaSdst, Encoded, getSaSdstBitShift(), getSaSdstBitWidth());
2114}
2115
2116unsigned encodeFieldSaSdst(unsigned SaSdst, const MCSubtargetInfo &STI) {
2117 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2118 return encodeFieldSaSdst(Encoded, SaSdst);
2119}
2120
2121unsigned encodeFieldVaSdst(unsigned Encoded, unsigned VaSdst) {
2122 return packBits(VaSdst, Encoded, getVaSdstBitShift(), getVaSdstBitWidth());
2123}
2124
2125unsigned encodeFieldVaSdst(unsigned VaSdst, const MCSubtargetInfo &STI) {
2126 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2127 return encodeFieldVaSdst(Encoded, VaSdst);
2128}
2129
2130unsigned encodeFieldVaVcc(unsigned Encoded, unsigned VaVcc) {
2131 return packBits(VaVcc, Encoded, getVaVccBitShift(), getVaVccBitWidth());
2132}
2133
2134unsigned encodeFieldVaVcc(unsigned VaVcc, const MCSubtargetInfo &STI) {
2135 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2136 return encodeFieldVaVcc(Encoded, VaVcc);
2137}
2138
2139unsigned encodeFieldVaSsrc(unsigned Encoded, unsigned VaSsrc) {
2140 return packBits(VaSsrc, Encoded, getVaSsrcBitShift(), getVaSsrcBitWidth());
2141}
2142
2143unsigned encodeFieldVaSsrc(unsigned VaSsrc, const MCSubtargetInfo &STI) {
2144 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2145 return encodeFieldVaSsrc(Encoded, VaSsrc);
2146}
2147
2148unsigned encodeFieldHoldCnt(unsigned Encoded, unsigned HoldCnt,
2149 const IsaVersion &Version) {
2150 return packBits(HoldCnt, Encoded, getHoldCntBitShift(),
2151 getHoldCntWidth(Version.Major, Version.Minor));
2152}
2153
2154unsigned encodeFieldHoldCnt(unsigned HoldCnt, const MCSubtargetInfo &STI) {
2155 unsigned Encoded = getDefaultDepCtrEncoding(STI);
2156 return encodeFieldHoldCnt(Encoded, HoldCnt, getIsaVersion(STI.getCPU()));
2157}
2158
2159} // namespace DepCtr
2160
2161//===----------------------------------------------------------------------===//
2162// exp tgt
2163//===----------------------------------------------------------------------===//
2164
2165namespace Exp {
2166
2167struct ExpTgt {
2169 unsigned Tgt;
2170 unsigned MaxIndex;
2171};
2172
2173// clang-format off
2174static constexpr ExpTgt ExpTgtInfo[] = {
2175 {{"null"}, ET_NULL, ET_NULL_MAX_IDX},
2176 {{"mrtz"}, ET_MRTZ, ET_MRTZ_MAX_IDX},
2177 {{"prim"}, ET_PRIM, ET_PRIM_MAX_IDX},
2178 {{"mrt"}, ET_MRT0, ET_MRT_MAX_IDX},
2179 {{"pos"}, ET_POS0, ET_POS_MAX_IDX},
2180 {{"dual_src_blend"},ET_DUAL_SRC_BLEND0, ET_DUAL_SRC_BLEND_MAX_IDX},
2181 {{"param"}, ET_PARAM0, ET_PARAM_MAX_IDX},
2182};
2183// clang-format on
2184
2185bool getTgtName(unsigned Id, StringRef &Name, int &Index) {
2186 for (const ExpTgt &Val : ExpTgtInfo) {
2187 if (Val.Tgt <= Id && Id <= Val.Tgt + Val.MaxIndex) {
2188 Index = (Val.MaxIndex == 0) ? -1 : (Id - Val.Tgt);
2189 Name = Val.Name;
2190 return true;
2191 }
2192 }
2193 return false;
2194}
2195
2196unsigned getTgtId(const StringRef Name) {
2197
2198 for (const ExpTgt &Val : ExpTgtInfo) {
2199 if (Val.MaxIndex == 0 && Name == Val.Name)
2200 return Val.Tgt;
2201
2202 if (Val.MaxIndex > 0 && Name.starts_with(Val.Name)) {
2203 StringRef Suffix = Name.drop_front(Val.Name.size());
2204
2205 unsigned Id;
2206 if (Suffix.getAsInteger(10, Id) || Id > Val.MaxIndex)
2207 return ET_INVALID;
2208
2209 // Disable leading zeroes
2210 if (Suffix.size() > 1 && Suffix[0] == '0')
2211 return ET_INVALID;
2212
2213 return Val.Tgt + Id;
2214 }
2215 }
2216 return ET_INVALID;
2217}
2218
2219bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI) {
2220 switch (Id) {
2221 case ET_NULL:
2222 return !isGFX11Plus(STI);
2223 case ET_POS4:
2224 case ET_PRIM:
2225 return isGFX10Plus(STI);
2226 case ET_DUAL_SRC_BLEND0:
2227 case ET_DUAL_SRC_BLEND1:
2228 return isGFX11Plus(STI);
2229 default:
2230 if (Id >= ET_PARAM0 && Id <= ET_PARAM31)
2231 return !isGFX11Plus(STI) || isGFX13Plus(STI);
2232 return true;
2233 }
2234}
2235
2236} // namespace Exp
2237
2238//===----------------------------------------------------------------------===//
2239// MTBUF Format
2240//===----------------------------------------------------------------------===//
2241
2242namespace MTBUFFormat {
2243
2244int64_t getDfmt(const StringRef Name) {
2245 for (int Id = DFMT_MIN; Id <= DFMT_MAX; ++Id) {
2246 if (Name == DfmtSymbolic[Id])
2247 return Id;
2248 }
2249 return DFMT_UNDEF;
2250}
2251
2253 assert(Id <= DFMT_MAX);
2254 return DfmtSymbolic[Id];
2255}
2256
2258 if (isSI(STI) || isCI(STI))
2259 return NfmtSymbolicSICI;
2260 if (isVI(STI) || isGFX9(STI))
2261 return NfmtSymbolicVI;
2262 return NfmtSymbolicGFX10;
2263}
2264
2265int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI) {
2266 const auto *lookupTable = getNfmtLookupTable(STI);
2267 for (int Id = NFMT_MIN; Id <= NFMT_MAX; ++Id) {
2268 if (Name == lookupTable[Id])
2269 return Id;
2270 }
2271 return NFMT_UNDEF;
2272}
2273
2274StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI) {
2275 assert(Id <= NFMT_MAX);
2276 return getNfmtLookupTable(STI)[Id];
2277}
2278
2279bool isValidDfmtNfmt(unsigned Id, const MCSubtargetInfo &STI) {
2280 unsigned Dfmt;
2281 unsigned Nfmt;
2282 decodeDfmtNfmt(Id, Dfmt, Nfmt);
2283 return isValidNfmt(Nfmt, STI);
2284}
2285
2286bool isValidNfmt(unsigned Id, const MCSubtargetInfo &STI) {
2287 return !getNfmtName(Id, STI).empty();
2288}
2289
2290int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt) {
2291 return (Dfmt << DFMT_SHIFT) | (Nfmt << NFMT_SHIFT);
2292}
2293
2294void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt) {
2295 Dfmt = (Format >> DFMT_SHIFT) & DFMT_MASK;
2296 Nfmt = (Format >> NFMT_SHIFT) & NFMT_MASK;
2297}
2298
2299int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI) {
2300 if (isGFX11Plus(STI)) {
2301 for (int Id = UfmtGFX11::UFMT_FIRST; Id <= UfmtGFX11::UFMT_LAST; ++Id) {
2302 if (Name == UfmtSymbolicGFX11[Id])
2303 return Id;
2304 }
2305 } else {
2306 for (int Id = UfmtGFX10::UFMT_FIRST; Id <= UfmtGFX10::UFMT_LAST; ++Id) {
2307 if (Name == UfmtSymbolicGFX10[Id])
2308 return Id;
2309 }
2310 }
2311 return UFMT_UNDEF;
2312}
2313
2315 if (isValidUnifiedFormat(Id, STI))
2316 return isGFX10(STI) ? UfmtSymbolicGFX10[Id] : UfmtSymbolicGFX11[Id];
2317 return "";
2318}
2319
2320bool isValidUnifiedFormat(unsigned Id, const MCSubtargetInfo &STI) {
2321 return isGFX10(STI) ? Id <= UfmtGFX10::UFMT_LAST : Id <= UfmtGFX11::UFMT_LAST;
2322}
2323
2324int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt,
2325 const MCSubtargetInfo &STI) {
2326 int64_t Fmt = encodeDfmtNfmt(Dfmt, Nfmt);
2327 if (isGFX11Plus(STI)) {
2328 for (int Id = UfmtGFX11::UFMT_FIRST; Id <= UfmtGFX11::UFMT_LAST; ++Id) {
2329 if (Fmt == DfmtNfmt2UFmtGFX11[Id])
2330 return Id;
2331 }
2332 } else {
2333 for (int Id = UfmtGFX10::UFMT_FIRST; Id <= UfmtGFX10::UFMT_LAST; ++Id) {
2334 if (Fmt == DfmtNfmt2UFmtGFX10[Id])
2335 return Id;
2336 }
2337 }
2338 return UFMT_UNDEF;
2339}
2340
2341bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI) {
2342 return isGFX10Plus(STI) ? (Val <= UFMT_MAX) : (Val <= DFMT_NFMT_MAX);
2343}
2344
2346 if (isGFX10Plus(STI))
2347 return UFMT_DEFAULT;
2348 return DFMT_NFMT_DEFAULT;
2349}
2350
2351} // namespace MTBUFFormat
2352
2353//===----------------------------------------------------------------------===//
2354// SendMsg
2355//===----------------------------------------------------------------------===//
2356
2357namespace SendMsg {
2358
2362
2363bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI) {
2364 return (MsgId & ~(getMsgIdMask(STI))) == 0;
2365}
2366
2367bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI,
2368 bool Strict) {
2369 assert(isValidMsgId(MsgId, STI));
2370
2371 if (!Strict)
2372 return 0 <= OpId && isUInt<OP_WIDTH_>(OpId);
2373
2374 if (msgRequiresOp(MsgId, STI)) {
2375 if (MsgId == ID_GS_PreGFX11 && OpId == OP_GS_NOP)
2376 return false;
2377
2378 return !getMsgOpName(MsgId, OpId, STI).empty();
2379 }
2380
2381 return OpId == OP_NONE_;
2382}
2383
2384bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId,
2385 const MCSubtargetInfo &STI, bool Strict) {
2386 assert(isValidMsgOp(MsgId, OpId, STI, Strict));
2387
2388 if (!Strict)
2390
2391 if (!isGFX11Plus(STI)) {
2392 switch (MsgId) {
2393 case ID_GS_PreGFX11:
2396 return (OpId == OP_GS_NOP)
2399 }
2400 }
2401 return StreamId == STREAM_ID_NONE_;
2402}
2403
2404bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI) {
2405 return MsgId == ID_SYSMSG ||
2406 (!isGFX11Plus(STI) &&
2407 (MsgId == ID_GS_PreGFX11 || MsgId == ID_GS_DONE_PreGFX11));
2408}
2409
2410bool msgSupportsStream(int64_t MsgId, int64_t OpId,
2411 const MCSubtargetInfo &STI) {
2412 return !isGFX11Plus(STI) &&
2413 (MsgId == ID_GS_PreGFX11 || MsgId == ID_GS_DONE_PreGFX11) &&
2414 OpId != OP_GS_NOP;
2415}
2416
2417void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId,
2418 uint16_t &StreamId, const MCSubtargetInfo &STI) {
2419 MsgId = Val & getMsgIdMask(STI);
2420 if (isGFX11Plus(STI)) {
2421 OpId = 0;
2422 StreamId = 0;
2423 } else {
2424 OpId = (Val & OP_MASK_) >> OP_SHIFT_;
2426 }
2427}
2428
2430 return MsgId | (OpId << OP_SHIFT_) | (StreamId << STREAM_ID_SHIFT_);
2431}
2432
2433bool msgDoesNotUseM0(int64_t MsgId, const MCSubtargetInfo &STI) {
2434 // Explicitly list message types that are known to not use m0.
2435 // This is safer than excluding only GS_ALLOC_REQ, in case new message
2436 // types are added in the future that do use m0.
2437 if (isGFX11Plus(STI)) {
2438 switch (MsgId) {
2440 return true;
2441 default:
2442 break;
2443 }
2444 }
2445 switch (MsgId) {
2446 case ID_SAVEWAVE:
2447 case ID_STALL_WAVE_GEN:
2448 case ID_HALT_WAVES:
2449 case ID_ORDERED_PS_DONE:
2451 case ID_GET_DOORBELL:
2452 case ID_GET_DDID:
2453 case ID_SYSMSG:
2454 return true;
2455 default:
2456 return false;
2457 }
2458}
2459
2460} // namespace SendMsg
2461
2462//===----------------------------------------------------------------------===//
2463//
2464//===----------------------------------------------------------------------===//
2465
2467 return F.getFnAttributeAsParsedInteger("InitialPSInputAddr", 0);
2468}
2469
2471 // As a safe default always respond as if PS has color exports.
2472 return F.getFnAttributeAsParsedInteger(
2473 "amdgpu-color-export",
2474 F.getCallingConv() == CallingConv::AMDGPU_PS ? 1 : 0) != 0;
2475}
2476
2478 return F.getFnAttributeAsParsedInteger("amdgpu-depth-export", 0) != 0;
2479}
2480
2482 unsigned BlockSize =
2483 F.getFnAttributeAsParsedInteger("amdgpu-dynamic-vgpr-block-size", 0);
2484
2485 if (BlockSize == 16 || BlockSize == 32)
2486 return BlockSize;
2487
2488 return 0;
2489}
2490
2491bool hasXNACK(const MCSubtargetInfo &STI) {
2492 return STI.hasFeature(AMDGPU::FeatureXNACK);
2493}
2494
2496 return STI.hasFeature(AMDGPU::FeatureMIMG_R128) &&
2497 !STI.hasFeature(AMDGPU::FeatureR128A16);
2498}
2499
2500bool hasA16(const MCSubtargetInfo &STI) {
2501 return STI.hasFeature(AMDGPU::FeatureA16);
2502}
2503
2504bool hasG16(const MCSubtargetInfo &STI) {
2505 return STI.hasFeature(AMDGPU::FeatureG16);
2506}
2507
2509 return !STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) && !isCI(STI) &&
2510 !isSI(STI);
2511}
2512
2513bool hasGDS(const MCSubtargetInfo &STI) {
2514 return STI.hasFeature(AMDGPU::FeatureGDS);
2515}
2516
2517unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler) {
2518 auto Version = getIsaVersion(STI.getCPU());
2519 if (Version.Major == 10)
2520 return Version.Minor >= 3 ? 13 : 5;
2521 if (Version.Major == 11)
2522 return 5;
2523 if (Version.Major >= 12)
2524 return HasSampler ? 4 : 5;
2525 return 0;
2526}
2527
2529 if (isGFX1250Plus(STI))
2530 return 32;
2531 return 16;
2532}
2533
2534bool isSI(const MCSubtargetInfo &STI) {
2535 return STI.hasFeature(AMDGPU::FeatureSouthernIslands);
2536}
2537
2538bool isCI(const MCSubtargetInfo &STI) {
2539 return STI.hasFeature(AMDGPU::FeatureSeaIslands);
2540}
2541
2542bool isVI(const MCSubtargetInfo &STI) {
2543 return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
2544}
2545
2546bool isGFX9(const MCSubtargetInfo &STI) {
2547 return STI.hasFeature(AMDGPU::FeatureGFX9);
2548}
2549
2551 return isGFX9(STI) || isGFX10(STI);
2552}
2553
2555 return isGFX9(STI) || isGFX10(STI) || isGFX11(STI);
2556}
2557
2559 return isVI(STI) || isGFX9(STI) || isGFX10(STI);
2560}
2561
2562bool isGFX8Plus(const MCSubtargetInfo &STI) {
2563 return isVI(STI) || isGFX9Plus(STI);
2564}
2565
2566bool isGFX9Plus(const MCSubtargetInfo &STI) {
2567 return isGFX9(STI) || isGFX10Plus(STI);
2568}
2569
2570bool isNotGFX9Plus(const MCSubtargetInfo &STI) { return !isGFX9Plus(STI); }
2571
2573 return STI.hasFeature(AMDGPU::FeaturePopsExitingWaveID);
2574}
2575
2577 return STI.hasFeature(AMDGPU::FeatureApertureRegs) &&
2578 !STI.hasFeature(AMDGPU::FeatureGloballyAddressableScratch);
2579}
2580
2581bool isGFX10(const MCSubtargetInfo &STI) {
2582 return STI.hasFeature(AMDGPU::FeatureGFX10);
2583}
2584
2586 return isGFX10(STI) || isGFX11(STI);
2587}
2588
2590 return isGFX10(STI) || isGFX11Plus(STI);
2591}
2592
2593bool isGFX11(const MCSubtargetInfo &STI) {
2594 return STI.hasFeature(AMDGPU::FeatureGFX11);
2595}
2596
2598 return isGFX11(STI) || isGFX12Plus(STI);
2599}
2600
2601bool isGFX12(const MCSubtargetInfo &STI) {
2602 return STI.getFeatureBits()[AMDGPU::FeatureGFX12];
2603}
2604
2606 return isGFX12(STI) || isGFX13Plus(STI);
2607}
2608
2609bool isNotGFX12Plus(const MCSubtargetInfo &STI) { return !isGFX12Plus(STI); }
2610
2611bool isGFX1250(const MCSubtargetInfo &STI) {
2612 return STI.getFeatureBits()[AMDGPU::FeatureGFX1250Insts] && !isGFX13(STI);
2613}
2614
2616 return isGFX1250(STI) || !STI.getFeatureBits().test(FeatureCuMode);
2617}
2618
2620 return STI.getFeatureBits()[AMDGPU::FeatureGFX1250Insts];
2621}
2622
2623bool isGFX13(const MCSubtargetInfo &STI) {
2624 return STI.getFeatureBits()[AMDGPU::FeatureGFX13];
2625}
2626
2627bool isGFX13Plus(const MCSubtargetInfo &STI) { return isGFX13(STI); }
2628
2630 if (isGFX1250(STI))
2631 return false;
2632 return isGFX10Plus(STI);
2633}
2634
2635bool isNotGFX11Plus(const MCSubtargetInfo &STI) { return !isGFX11Plus(STI); }
2636
2638 return isSI(STI) || isCI(STI) || isVI(STI) || isGFX9(STI);
2639}
2640
2642 return isGFX10(STI) && !AMDGPU::isGFX10_BEncoding(STI);
2643}
2644
2646 return STI.hasFeature(AMDGPU::FeatureGCN3Encoding);
2647}
2648
2650 return STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding);
2651}
2652
2654 return STI.hasFeature(AMDGPU::FeatureGFX10_3Insts);
2655}
2656
2658 return isGFX10_BEncoding(STI) && !isGFX12Plus(STI);
2659}
2660
2661bool isGFX90A(const MCSubtargetInfo &STI) {
2662 return STI.hasFeature(AMDGPU::FeatureGFX90AInsts);
2663}
2664
2665bool isGFX940(const MCSubtargetInfo &STI) {
2666 return STI.hasFeature(AMDGPU::FeatureGFX940Insts);
2667}
2668
2670 return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch);
2671}
2672
2674 return STI.hasFeature(AMDGPU::FeatureMAIInsts);
2675}
2676
2677bool hasVOPD(const MCSubtargetInfo &STI) {
2678 return STI.hasFeature(AMDGPU::FeatureVOPDInsts);
2679}
2680
2682 return STI.hasFeature(AMDGPU::FeatureDPPSrc1SGPR);
2683}
2684
2686 return STI.hasFeature(AMDGPU::FeatureKernargPreload);
2687}
2688
2689int32_t getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR,
2690 int32_t ArgNumVGPR) {
2691 if (has90AInsts && ArgNumAGPR)
2692 return alignTo(ArgNumVGPR, 4) + ArgNumAGPR;
2693 return std::max(ArgNumVGPR, ArgNumAGPR);
2694}
2695
2697 const MCRegisterClass &SGPRClass =
2698 TRI->getRegClass(AMDGPU::SReg_32RegClassID);
2699 const MCRegister FirstSubReg = TRI->getSubReg(Reg, AMDGPU::sub0);
2700 return SGPRClass.contains(FirstSubReg != 0 ? FirstSubReg : Reg) ||
2701 Reg == AMDGPU::SCC;
2702}
2703
2707
2708#define MAP_REG2REG \
2709 using namespace AMDGPU; \
2710 switch (Reg.id()) { \
2711 default: \
2712 return Reg; \
2713 CASE_CI_VI(FLAT_SCR) \
2714 CASE_CI_VI(FLAT_SCR_LO) \
2715 CASE_CI_VI(FLAT_SCR_HI) \
2716 CASE_VI_GFX9PLUS(TTMP0) \
2717 CASE_VI_GFX9PLUS(TTMP1) \
2718 CASE_VI_GFX9PLUS(TTMP2) \
2719 CASE_VI_GFX9PLUS(TTMP3) \
2720 CASE_VI_GFX9PLUS(TTMP4) \
2721 CASE_VI_GFX9PLUS(TTMP5) \
2722 CASE_VI_GFX9PLUS(TTMP6) \
2723 CASE_VI_GFX9PLUS(TTMP7) \
2724 CASE_VI_GFX9PLUS(TTMP8) \
2725 CASE_VI_GFX9PLUS(TTMP9) \
2726 CASE_VI_GFX9PLUS(TTMP10) \
2727 CASE_VI_GFX9PLUS(TTMP11) \
2728 CASE_VI_GFX9PLUS(TTMP12) \
2729 CASE_VI_GFX9PLUS(TTMP13) \
2730 CASE_VI_GFX9PLUS(TTMP14) \
2731 CASE_VI_GFX9PLUS(TTMP15) \
2732 CASE_VI_GFX9PLUS(TTMP0_TTMP1) \
2733 CASE_VI_GFX9PLUS(TTMP2_TTMP3) \
2734 CASE_VI_GFX9PLUS(TTMP4_TTMP5) \
2735 CASE_VI_GFX9PLUS(TTMP6_TTMP7) \
2736 CASE_VI_GFX9PLUS(TTMP8_TTMP9) \
2737 CASE_VI_GFX9PLUS(TTMP10_TTMP11) \
2738 CASE_VI_GFX9PLUS(TTMP12_TTMP13) \
2739 CASE_VI_GFX9PLUS(TTMP14_TTMP15) \
2740 CASE_VI_GFX9PLUS(TTMP0_TTMP1_TTMP2_TTMP3) \
2741 CASE_VI_GFX9PLUS(TTMP4_TTMP5_TTMP6_TTMP7) \
2742 CASE_VI_GFX9PLUS(TTMP8_TTMP9_TTMP10_TTMP11) \
2743 CASE_VI_GFX9PLUS(TTMP12_TTMP13_TTMP14_TTMP15) \
2744 CASE_VI_GFX9PLUS(TTMP0_TTMP1_TTMP2_TTMP3_TTMP4_TTMP5_TTMP6_TTMP7) \
2745 CASE_VI_GFX9PLUS(TTMP4_TTMP5_TTMP6_TTMP7_TTMP8_TTMP9_TTMP10_TTMP11) \
2746 CASE_VI_GFX9PLUS(TTMP8_TTMP9_TTMP10_TTMP11_TTMP12_TTMP13_TTMP14_TTMP15) \
2747 CASE_VI_GFX9PLUS( \
2748 TTMP0_TTMP1_TTMP2_TTMP3_TTMP4_TTMP5_TTMP6_TTMP7_TTMP8_TTMP9_TTMP10_TTMP11_TTMP12_TTMP13_TTMP14_TTMP15) \
2749 CASE_GFXPRE11_GFX11PLUS(M0) \
2750 CASE_GFXPRE11_GFX11PLUS(SGPR_NULL) \
2751 CASE_GFXPRE11_GFX11PLUS_TO(SGPR_NULL64, SGPR_NULL) \
2752 }
2753
2754#define CASE_CI_VI(node) \
2755 assert(!isSI(STI)); \
2756 case node: \
2757 return isCI(STI) ? node##_ci : node##_vi;
2758
2759#define CASE_VI_GFX9PLUS(node) \
2760 case node: \
2761 return isGFX9Plus(STI) ? node##_gfx9plus : node##_vi;
2762
2763#define CASE_GFXPRE11_GFX11PLUS(node) \
2764 case node: \
2765 return isGFX11Plus(STI) ? node##_gfx11plus : node##_gfxpre11;
2766
2767#define CASE_GFXPRE11_GFX11PLUS_TO(node, result) \
2768 case node: \
2769 return isGFX11Plus(STI) ? result##_gfx11plus : result##_gfxpre11;
2770
2772 if (STI.getTargetTriple().getArch() == Triple::r600)
2773 return Reg;
2775}
2776
2777#undef CASE_CI_VI
2778#undef CASE_VI_GFX9PLUS
2779#undef CASE_GFXPRE11_GFX11PLUS
2780#undef CASE_GFXPRE11_GFX11PLUS_TO
2781
2782#define CASE_CI_VI(node) \
2783 case node##_ci: \
2784 case node##_vi: \
2785 return node;
2786#define CASE_VI_GFX9PLUS(node) \
2787 case node##_vi: \
2788 case node##_gfx9plus: \
2789 return node;
2790#define CASE_GFXPRE11_GFX11PLUS(node) \
2791 case node##_gfx11plus: \
2792 case node##_gfxpre11: \
2793 return node;
2794#define CASE_GFXPRE11_GFX11PLUS_TO(node, result)
2795
2797
2799 switch (Reg.id()) {
2800 case AMDGPU::SRC_SHARED_BASE_LO:
2801 case AMDGPU::SRC_SHARED_BASE:
2802 case AMDGPU::SRC_SHARED_LIMIT_LO:
2803 case AMDGPU::SRC_SHARED_LIMIT:
2804 case AMDGPU::SRC_PRIVATE_BASE_LO:
2805 case AMDGPU::SRC_PRIVATE_BASE:
2806 case AMDGPU::SRC_PRIVATE_LIMIT_LO:
2807 case AMDGPU::SRC_PRIVATE_LIMIT:
2808 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
2809 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
2810 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
2811 return true;
2812 case AMDGPU::SRC_VCCZ:
2813 case AMDGPU::SRC_EXECZ:
2814 case AMDGPU::SRC_SCC:
2815 return true;
2816 case AMDGPU::SGPR_NULL:
2817 return true;
2818 default:
2819 return false;
2820 }
2821}
2822
2823#undef CASE_CI_VI
2824#undef CASE_VI_GFX9PLUS
2825#undef CASE_GFXPRE11_GFX11PLUS
2826#undef CASE_GFXPRE11_GFX11PLUS_TO
2827#undef MAP_REG2REG
2828
2829bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo) {
2830 assert(OpNo < Desc.NumOperands);
2831 unsigned OpType = Desc.operands()[OpNo].OperandType;
2832 return OpType >= AMDGPU::OPERAND_KIMM_FIRST &&
2833 OpType <= AMDGPU::OPERAND_KIMM_LAST;
2834}
2835
2836bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo) {
2837 assert(OpNo < Desc.NumOperands);
2838 unsigned OpType = Desc.operands()[OpNo].OperandType;
2839 switch (OpType) {
2854 return true;
2855 default:
2856 return false;
2857 }
2858}
2859
2860bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo) {
2861 assert(OpNo < Desc.NumOperands);
2862 unsigned OpType = Desc.operands()[OpNo].OperandType;
2863 return (OpType >= AMDGPU::OPERAND_REG_INLINE_C_FIRST &&
2867}
2868
2869// Avoid using MCRegisterClass::getSize, since that function will go away
2870// (move from MC* level to Target* level). Return size in bits.
2871unsigned getRegBitWidth(unsigned RCID) {
2872 switch (RCID) {
2873 case AMDGPU::VGPR_16RegClassID:
2874 case AMDGPU::VGPR_16_Lo128RegClassID:
2875 case AMDGPU::SGPR_LO16RegClassID:
2876 case AMDGPU::AGPR_LO16RegClassID:
2877 return 16;
2878 case AMDGPU::SGPR_32RegClassID:
2879 case AMDGPU::VGPR_32RegClassID:
2880 case AMDGPU::VGPR_32_Lo256RegClassID:
2881 case AMDGPU::VRegOrLds_32RegClassID:
2882 case AMDGPU::AGPR_32RegClassID:
2883 case AMDGPU::VS_32RegClassID:
2884 case AMDGPU::AV_32RegClassID:
2885 case AMDGPU::SReg_32RegClassID:
2886 case AMDGPU::SReg_32_XM0RegClassID:
2887 case AMDGPU::SRegOrLds_32RegClassID:
2888 return 32;
2889 case AMDGPU::SGPR_64RegClassID:
2890 case AMDGPU::VS_64RegClassID:
2891 case AMDGPU::SReg_64RegClassID:
2892 case AMDGPU::VReg_64RegClassID:
2893 case AMDGPU::AReg_64RegClassID:
2894 case AMDGPU::SReg_64_XEXECRegClassID:
2895 case AMDGPU::VReg_64_Align2RegClassID:
2896 case AMDGPU::AReg_64_Align2RegClassID:
2897 case AMDGPU::AV_64RegClassID:
2898 case AMDGPU::AV_64_Align2RegClassID:
2899 case AMDGPU::VReg_64_Lo256_Align2RegClassID:
2900 case AMDGPU::VS_64_Lo256RegClassID:
2901 return 64;
2902 case AMDGPU::SGPR_96RegClassID:
2903 case AMDGPU::SReg_96RegClassID:
2904 case AMDGPU::VReg_96RegClassID:
2905 case AMDGPU::AReg_96RegClassID:
2906 case AMDGPU::VReg_96_Align2RegClassID:
2907 case AMDGPU::AReg_96_Align2RegClassID:
2908 case AMDGPU::AV_96RegClassID:
2909 case AMDGPU::AV_96_Align2RegClassID:
2910 case AMDGPU::VReg_96_Lo256_Align2RegClassID:
2911 return 96;
2912 case AMDGPU::SGPR_128RegClassID:
2913 case AMDGPU::SReg_128RegClassID:
2914 case AMDGPU::VReg_128RegClassID:
2915 case AMDGPU::AReg_128RegClassID:
2916 case AMDGPU::VReg_128_Align2RegClassID:
2917 case AMDGPU::AReg_128_Align2RegClassID:
2918 case AMDGPU::AV_128RegClassID:
2919 case AMDGPU::AV_128_Align2RegClassID:
2920 case AMDGPU::SReg_128_XNULLRegClassID:
2921 case AMDGPU::VReg_128_Lo256_Align2RegClassID:
2922 return 128;
2923 case AMDGPU::SGPR_160RegClassID:
2924 case AMDGPU::SReg_160RegClassID:
2925 case AMDGPU::VReg_160RegClassID:
2926 case AMDGPU::AReg_160RegClassID:
2927 case AMDGPU::VReg_160_Align2RegClassID:
2928 case AMDGPU::AReg_160_Align2RegClassID:
2929 case AMDGPU::AV_160RegClassID:
2930 case AMDGPU::AV_160_Align2RegClassID:
2931 case AMDGPU::VReg_160_Lo256_Align2RegClassID:
2932 return 160;
2933 case AMDGPU::SGPR_192RegClassID:
2934 case AMDGPU::SReg_192RegClassID:
2935 case AMDGPU::VReg_192RegClassID:
2936 case AMDGPU::AReg_192RegClassID:
2937 case AMDGPU::VReg_192_Align2RegClassID:
2938 case AMDGPU::AReg_192_Align2RegClassID:
2939 case AMDGPU::AV_192RegClassID:
2940 case AMDGPU::AV_192_Align2RegClassID:
2941 case AMDGPU::VReg_192_Lo256_Align2RegClassID:
2942 return 192;
2943 case AMDGPU::SGPR_224RegClassID:
2944 case AMDGPU::SReg_224RegClassID:
2945 case AMDGPU::VReg_224RegClassID:
2946 case AMDGPU::AReg_224RegClassID:
2947 case AMDGPU::VReg_224_Align2RegClassID:
2948 case AMDGPU::AReg_224_Align2RegClassID:
2949 case AMDGPU::AV_224RegClassID:
2950 case AMDGPU::AV_224_Align2RegClassID:
2951 case AMDGPU::VReg_224_Lo256_Align2RegClassID:
2952 return 224;
2953 case AMDGPU::SGPR_256RegClassID:
2954 case AMDGPU::SReg_256RegClassID:
2955 case AMDGPU::VReg_256RegClassID:
2956 case AMDGPU::AReg_256RegClassID:
2957 case AMDGPU::VReg_256_Align2RegClassID:
2958 case AMDGPU::AReg_256_Align2RegClassID:
2959 case AMDGPU::AV_256RegClassID:
2960 case AMDGPU::AV_256_Align2RegClassID:
2961 case AMDGPU::SReg_256_XNULLRegClassID:
2962 case AMDGPU::VReg_256_Lo256_Align2RegClassID:
2963 return 256;
2964 case AMDGPU::SGPR_288RegClassID:
2965 case AMDGPU::SReg_288RegClassID:
2966 case AMDGPU::VReg_288RegClassID:
2967 case AMDGPU::AReg_288RegClassID:
2968 case AMDGPU::VReg_288_Align2RegClassID:
2969 case AMDGPU::AReg_288_Align2RegClassID:
2970 case AMDGPU::AV_288RegClassID:
2971 case AMDGPU::AV_288_Align2RegClassID:
2972 case AMDGPU::VReg_288_Lo256_Align2RegClassID:
2973 return 288;
2974 case AMDGPU::SGPR_320RegClassID:
2975 case AMDGPU::SReg_320RegClassID:
2976 case AMDGPU::VReg_320RegClassID:
2977 case AMDGPU::AReg_320RegClassID:
2978 case AMDGPU::VReg_320_Align2RegClassID:
2979 case AMDGPU::AReg_320_Align2RegClassID:
2980 case AMDGPU::AV_320RegClassID:
2981 case AMDGPU::AV_320_Align2RegClassID:
2982 case AMDGPU::VReg_320_Lo256_Align2RegClassID:
2983 return 320;
2984 case AMDGPU::SGPR_352RegClassID:
2985 case AMDGPU::SReg_352RegClassID:
2986 case AMDGPU::VReg_352RegClassID:
2987 case AMDGPU::AReg_352RegClassID:
2988 case AMDGPU::VReg_352_Align2RegClassID:
2989 case AMDGPU::AReg_352_Align2RegClassID:
2990 case AMDGPU::AV_352RegClassID:
2991 case AMDGPU::AV_352_Align2RegClassID:
2992 case AMDGPU::VReg_352_Lo256_Align2RegClassID:
2993 return 352;
2994 case AMDGPU::SGPR_384RegClassID:
2995 case AMDGPU::SReg_384RegClassID:
2996 case AMDGPU::VReg_384RegClassID:
2997 case AMDGPU::AReg_384RegClassID:
2998 case AMDGPU::VReg_384_Align2RegClassID:
2999 case AMDGPU::AReg_384_Align2RegClassID:
3000 case AMDGPU::AV_384RegClassID:
3001 case AMDGPU::AV_384_Align2RegClassID:
3002 case AMDGPU::VReg_384_Lo256_Align2RegClassID:
3003 return 384;
3004 case AMDGPU::SGPR_512RegClassID:
3005 case AMDGPU::SReg_512RegClassID:
3006 case AMDGPU::VReg_512RegClassID:
3007 case AMDGPU::AReg_512RegClassID:
3008 case AMDGPU::VReg_512_Align2RegClassID:
3009 case AMDGPU::AReg_512_Align2RegClassID:
3010 case AMDGPU::AV_512RegClassID:
3011 case AMDGPU::AV_512_Align2RegClassID:
3012 case AMDGPU::VReg_512_Lo256_Align2RegClassID:
3013 return 512;
3014 case AMDGPU::SGPR_1024RegClassID:
3015 case AMDGPU::SReg_1024RegClassID:
3016 case AMDGPU::VReg_1024RegClassID:
3017 case AMDGPU::AReg_1024RegClassID:
3018 case AMDGPU::VReg_1024_Align2RegClassID:
3019 case AMDGPU::AReg_1024_Align2RegClassID:
3020 case AMDGPU::AV_1024RegClassID:
3021 case AMDGPU::AV_1024_Align2RegClassID:
3022 case AMDGPU::VReg_1024_Lo256_Align2RegClassID:
3023 return 1024;
3024 default:
3025 llvm_unreachable("Unexpected register class");
3026 }
3027}
3028
3029unsigned getRegBitWidth(const MCRegisterClass &RC) {
3030 return getRegBitWidth(RC.getID());
3031}
3032
3033bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi) {
3035 return true;
3036
3037 uint64_t Val = static_cast<uint64_t>(Literal);
3038 return (Val == llvm::bit_cast<uint64_t>(0.0)) ||
3039 (Val == llvm::bit_cast<uint64_t>(1.0)) ||
3040 (Val == llvm::bit_cast<uint64_t>(-1.0)) ||
3041 (Val == llvm::bit_cast<uint64_t>(0.5)) ||
3042 (Val == llvm::bit_cast<uint64_t>(-0.5)) ||
3043 (Val == llvm::bit_cast<uint64_t>(2.0)) ||
3044 (Val == llvm::bit_cast<uint64_t>(-2.0)) ||
3045 (Val == llvm::bit_cast<uint64_t>(4.0)) ||
3046 (Val == llvm::bit_cast<uint64_t>(-4.0)) ||
3047 (Val == 0x3fc45f306dc9c882 && HasInv2Pi);
3048}
3049
3050bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi) {
3052 return true;
3053
3054 // The actual type of the operand does not seem to matter as long
3055 // as the bits match one of the inline immediate values. For example:
3056 //
3057 // -nan has the hexadecimal encoding of 0xfffffffe which is -2 in decimal,
3058 // so it is a legal inline immediate.
3059 //
3060 // 1065353216 has the hexadecimal encoding 0x3f800000 which is 1.0f in
3061 // floating-point, so it is a legal inline immediate.
3062
3063 uint32_t Val = static_cast<uint32_t>(Literal);
3064 return (Val == llvm::bit_cast<uint32_t>(0.0f)) ||
3065 (Val == llvm::bit_cast<uint32_t>(1.0f)) ||
3066 (Val == llvm::bit_cast<uint32_t>(-1.0f)) ||
3067 (Val == llvm::bit_cast<uint32_t>(0.5f)) ||
3068 (Val == llvm::bit_cast<uint32_t>(-0.5f)) ||
3069 (Val == llvm::bit_cast<uint32_t>(2.0f)) ||
3070 (Val == llvm::bit_cast<uint32_t>(-2.0f)) ||
3071 (Val == llvm::bit_cast<uint32_t>(4.0f)) ||
3072 (Val == llvm::bit_cast<uint32_t>(-4.0f)) ||
3073 (Val == 0x3e22f983 && HasInv2Pi);
3074}
3075
3076bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi) {
3077 if (!HasInv2Pi)
3078 return false;
3080 return true;
3081 uint16_t Val = static_cast<uint16_t>(Literal);
3082 return Val == 0x3F00 || // 0.5
3083 Val == 0xBF00 || // -0.5
3084 Val == 0x3F80 || // 1.0
3085 Val == 0xBF80 || // -1.0
3086 Val == 0x4000 || // 2.0
3087 Val == 0xC000 || // -2.0
3088 Val == 0x4080 || // 4.0
3089 Val == 0xC080 || // -4.0
3090 Val == 0x3E22; // 1.0 / (2.0 * pi)
3091}
3092
3093bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi) {
3094 return isInlinableLiteral32(Literal, HasInv2Pi);
3095}
3096
3097bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi) {
3098 if (!HasInv2Pi)
3099 return false;
3101 return true;
3102 uint16_t Val = static_cast<uint16_t>(Literal);
3103 return Val == 0x3C00 || // 1.0
3104 Val == 0xBC00 || // -1.0
3105 Val == 0x3800 || // 0.5
3106 Val == 0xB800 || // -0.5
3107 Val == 0x4000 || // 2.0
3108 Val == 0xC000 || // -2.0
3109 Val == 0x4400 || // 4.0
3110 Val == 0xC400 || // -4.0
3111 Val == 0x3118; // 1/2pi
3112}
3113
3114std::optional<unsigned> getInlineEncodingV216(bool IsFloat, uint32_t Literal) {
3115 // Unfortunately, the Instruction Set Architecture Reference Guide is
3116 // misleading about how the inline operands work for (packed) 16-bit
3117 // instructions. In a nutshell, the actual HW behavior is:
3118 //
3119 // - integer encodings (-16 .. 64) are always produced as sign-extended
3120 // 32-bit values
3121 // - float encodings are produced as:
3122 // - for F16 instructions: corresponding half-precision float values in
3123 // the LSBs, 0 in the MSBs
3124 // - for UI16 instructions: corresponding single-precision float value
3125 int32_t Signed = static_cast<int32_t>(Literal);
3126 if (Signed >= 0 && Signed <= 64)
3127 return 128 + Signed;
3128
3129 if (Signed >= -16 && Signed <= -1)
3130 return 192 + std::abs(Signed);
3131
3132 if (IsFloat) {
3133 // clang-format off
3134 switch (Literal) {
3135 case 0x3800: return 240; // 0.5
3136 case 0xB800: return 241; // -0.5
3137 case 0x3C00: return 242; // 1.0
3138 case 0xBC00: return 243; // -1.0
3139 case 0x4000: return 244; // 2.0
3140 case 0xC000: return 245; // -2.0
3141 case 0x4400: return 246; // 4.0
3142 case 0xC400: return 247; // -4.0
3143 case 0x3118: return 248; // 1.0 / (2.0 * pi)
3144 default: break;
3145 }
3146 // clang-format on
3147 } else {
3148 // clang-format off
3149 switch (Literal) {
3150 case 0x3F000000: return 240; // 0.5
3151 case 0xBF000000: return 241; // -0.5
3152 case 0x3F800000: return 242; // 1.0
3153 case 0xBF800000: return 243; // -1.0
3154 case 0x40000000: return 244; // 2.0
3155 case 0xC0000000: return 245; // -2.0
3156 case 0x40800000: return 246; // 4.0
3157 case 0xC0800000: return 247; // -4.0
3158 case 0x3E22F983: return 248; // 1.0 / (2.0 * pi)
3159 default: break;
3160 }
3161 // clang-format on
3162 }
3163
3164 return {};
3165}
3166
3167// Encoding of the literal as an inline constant for a V_PK_*_IU16 instruction
3168// or nullopt.
3169std::optional<unsigned> getInlineEncodingV2I16(uint32_t Literal) {
3170 return getInlineEncodingV216(false, Literal);
3171}
3172
3173// Encoding of the literal as an inline constant for a V_PK_*_BF16 instruction
3174// or nullopt.
3175std::optional<unsigned> getInlineEncodingV2BF16(uint32_t Literal) {
3176 int32_t Signed = static_cast<int32_t>(Literal);
3177 if (Signed >= 0 && Signed <= 64)
3178 return 128 + Signed;
3179
3180 if (Signed >= -16 && Signed <= -1)
3181 return 192 + std::abs(Signed);
3182
3183 // clang-format off
3184 switch (Literal) {
3185 case 0x3F00: return 240; // 0.5
3186 case 0xBF00: return 241; // -0.5
3187 case 0x3F80: return 242; // 1.0
3188 case 0xBF80: return 243; // -1.0
3189 case 0x4000: return 244; // 2.0
3190 case 0xC000: return 245; // -2.0
3191 case 0x4080: return 246; // 4.0
3192 case 0xC080: return 247; // -4.0
3193 case 0x3E22: return 248; // 1.0 / (2.0 * pi)
3194 default: break;
3195 }
3196 // clang-format on
3197
3198 return std::nullopt;
3199}
3200
3201// Encoding of the literal as an inline constant for a V_PK_*_F16 instruction
3202// or nullopt.
3203std::optional<unsigned> getInlineEncodingV2F16(uint32_t Literal) {
3204 return getInlineEncodingV216(true, Literal);
3205}
3206
3207// Encoding of the literal as an inline constant for V_PK_FMAC_F16 instruction
3208// or nullopt. This accounts for different inline constant behavior:
3209// - Pre-GFX11: fp16 inline constants have the value in low 16 bits, 0 in high
3210// - GFX11+: fp16 inline constants are duplicated into both halves
3212 bool IsGFX11Plus) {
3213 // Pre-GFX11 behavior: f16 in low bits, 0 in high bits
3214 if (!IsGFX11Plus)
3215 return getInlineEncodingV216(/*IsFloat=*/true, Literal);
3216
3217 // GFX11+ behavior: f16 duplicated in both halves
3218 // First, check for sign-extended integer inline constants (-16 to 64)
3219 // These work the same across all generations
3220 int32_t Signed = static_cast<int32_t>(Literal);
3221 if (Signed >= 0 && Signed <= 64)
3222 return 128 + Signed;
3223
3224 if (Signed >= -16 && Signed <= -1)
3225 return 192 + std::abs(Signed);
3226
3227 // For float inline constants on GFX11+, both halves must be equal
3228 uint16_t Lo = static_cast<uint16_t>(Literal);
3229 uint16_t Hi = static_cast<uint16_t>(Literal >> 16);
3230 if (Lo != Hi)
3231 return std::nullopt;
3232 return getInlineEncodingV216(/*IsFloat=*/true, Lo);
3233}
3234
3235// Whether the given literal can be inlined for a V_PK_* instruction.
3237 switch (OpType) {
3240 return getInlineEncodingV216(false, Literal).has_value();
3243 return getInlineEncodingV216(true, Literal).has_value();
3245 llvm_unreachable("OPERAND_REG_IMM_V2FP16_SPLAT is not supported");
3250 return false;
3251 default:
3252 llvm_unreachable("bad packed operand type");
3253 }
3254}
3255
3256// Whether the given literal can be inlined for a V_PK_*_IU16 instruction.
3260
3261// Whether the given literal can be inlined for a V_PK_*_BF16 instruction.
3265
3266// Whether the given literal can be inlined for a V_PK_*_F16 instruction.
3270
3271// Whether the given literal can be inlined for V_PK_FMAC_F16 instruction.
3273 return getPKFMACF16InlineEncoding(Literal, IsGFX11Plus).has_value();
3274}
3275
3276bool isValid32BitLiteral(uint64_t Val, bool IsFP64) {
3277 if (IsFP64)
3278 return !Lo_32(Val);
3279
3280 return isUInt<32>(Val) || isInt<32>(Val);
3281}
3282
3283int64_t encode32BitLiteral(int64_t Imm, OperandType Type, bool IsLit) {
3284 switch (Type) {
3285 default:
3286 break;
3291 return Imm & 0xffff;
3305 return Lo_32(Imm);
3308 return IsLit ? Imm : Hi_32(Imm);
3309 }
3310 return Imm;
3311}
3312
3314 const Function *F = A->getParent();
3315
3316 // Arguments to compute shaders are never a source of divergence.
3317 CallingConv::ID CC = F->getCallingConv();
3318 switch (CC) {
3321 return true;
3332 // For non-compute shaders, SGPR inputs are marked with either inreg or
3333 // byval. Everything else is in VGPRs.
3334 return A->hasAttribute(Attribute::InReg) ||
3335 A->hasAttribute(Attribute::ByVal);
3336 default:
3337 // TODO: treat i1 as divergent?
3338 return A->hasAttribute(Attribute::InReg);
3339 }
3340}
3341
3342bool isArgPassedInSGPR(const CallBase *CB, unsigned ArgNo) {
3343 // Arguments to compute shaders are never a source of divergence.
3345 switch (CC) {
3348 return true;
3359 // For non-compute shaders, SGPR inputs are marked with either inreg or
3360 // byval. Everything else is in VGPRs.
3361 return CB->paramHasAttr(ArgNo, Attribute::InReg) ||
3362 CB->paramHasAttr(ArgNo, Attribute::ByVal);
3363 default:
3364 return CB->paramHasAttr(ArgNo, Attribute::InReg);
3365 }
3366}
3367
3368static bool hasSMEMByteOffset(const MCSubtargetInfo &ST) {
3369 return isGCN3Encoding(ST) || isGFX10Plus(ST);
3370}
3371
3373 int64_t EncodedOffset) {
3374 if (isGFX12Plus(ST))
3375 return isUInt<23>(EncodedOffset);
3376
3377 return hasSMEMByteOffset(ST) ? isUInt<20>(EncodedOffset)
3378 : isUInt<8>(EncodedOffset);
3379}
3380
3382 int64_t EncodedOffset, bool IsBuffer) {
3383 if (isGFX12Plus(ST)) {
3384 if (IsBuffer && EncodedOffset < 0)
3385 return false;
3386 return isInt<24>(EncodedOffset);
3387 }
3388
3389 return !IsBuffer && hasSMRDSignedImmOffset(ST) && isInt<21>(EncodedOffset);
3390}
3391
3392static bool isDwordAligned(uint64_t ByteOffset) {
3393 return (ByteOffset & 3) == 0;
3394}
3395
3397 uint64_t ByteOffset) {
3398 if (hasSMEMByteOffset(ST))
3399 return ByteOffset;
3400
3401 assert(isDwordAligned(ByteOffset));
3402 return ByteOffset >> 2;
3403}
3404
3405std::optional<int64_t> getSMRDEncodedOffset(const MCSubtargetInfo &ST,
3406 int64_t ByteOffset, bool IsBuffer,
3407 bool HasSOffset) {
3408 // For unbuffered smem loads, it is illegal for the Immediate Offset to be
3409 // negative if the resulting (Offset + (M0 or SOffset or zero) is negative.
3410 // Handle case where SOffset is not present.
3411 if (!IsBuffer && !HasSOffset && ByteOffset < 0 && hasSMRDSignedImmOffset(ST))
3412 return std::nullopt;
3413
3414 if (isGFX12Plus(ST)) // 24 bit signed offsets
3415 return isInt<24>(ByteOffset) ? std::optional<int64_t>(ByteOffset)
3416 : std::nullopt;
3417
3418 // The signed version is always a byte offset.
3419 if (!IsBuffer && hasSMRDSignedImmOffset(ST)) {
3421 return isInt<20>(ByteOffset) ? std::optional<int64_t>(ByteOffset)
3422 : std::nullopt;
3423 }
3424
3425 if (!isDwordAligned(ByteOffset) && !hasSMEMByteOffset(ST))
3426 return std::nullopt;
3427
3428 int64_t EncodedOffset = convertSMRDOffsetUnits(ST, ByteOffset);
3429 return isLegalSMRDEncodedUnsignedOffset(ST, EncodedOffset)
3430 ? std::optional<int64_t>(EncodedOffset)
3431 : std::nullopt;
3432}
3433
3434std::optional<int64_t> getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST,
3435 int64_t ByteOffset) {
3436 if (!isCI(ST) || !isDwordAligned(ByteOffset))
3437 return std::nullopt;
3438
3439 int64_t EncodedOffset = convertSMRDOffsetUnits(ST, ByteOffset);
3440 return isUInt<32>(EncodedOffset) ? std::optional<int64_t>(EncodedOffset)
3441 : std::nullopt;
3442}
3443
3445 if (ST.getFeatureBits().test(FeatureFlatOffsetBits12))
3446 return 12;
3447 if (ST.getFeatureBits().test(FeatureFlatOffsetBits24))
3448 return 24;
3449 return 13;
3450}
3451
3452namespace {
3453
3454struct SourceOfDivergence {
3455 unsigned Intr;
3456};
3457const SourceOfDivergence *lookupSourceOfDivergence(unsigned Intr);
3458
3459struct AlwaysUniform {
3460 unsigned Intr;
3461};
3462const AlwaysUniform *lookupAlwaysUniform(unsigned Intr);
3463
3464#define GET_SourcesOfDivergence_IMPL
3465#define GET_UniformIntrinsics_IMPL
3466#define GET_Gfx9BufferFormat_IMPL
3467#define GET_Gfx10BufferFormat_IMPL
3468#define GET_Gfx11PlusBufferFormat_IMPL
3469
3470#include "AMDGPUGenSearchableTables.inc"
3471
3472} // end anonymous namespace
3473
3474bool isIntrinsicSourceOfDivergence(unsigned IntrID) {
3475 return lookupSourceOfDivergence(IntrID);
3476}
3477
3478bool isIntrinsicAlwaysUniform(unsigned IntrID) {
3479 return lookupAlwaysUniform(IntrID);
3480}
3481
3483 uint8_t NumComponents,
3484 uint8_t NumFormat,
3485 const MCSubtargetInfo &STI) {
3486 return isGFX11Plus(STI) ? getGfx11PlusBufferFormatInfo(
3487 BitsPerComp, NumComponents, NumFormat)
3488 : isGFX10(STI)
3489 ? getGfx10BufferFormatInfo(BitsPerComp, NumComponents, NumFormat)
3490 : getGfx9BufferFormatInfo(BitsPerComp, NumComponents, NumFormat);
3491}
3492
3494 const MCSubtargetInfo &STI) {
3495 return isGFX11Plus(STI) ? getGfx11PlusBufferFormatInfo(Format)
3496 : isGFX10(STI) ? getGfx10BufferFormatInfo(Format)
3497 : getGfx9BufferFormatInfo(Format);
3498}
3499
3501 const MCRegisterInfo &MRI) {
3502 const unsigned VGPRClasses[] = {
3503 AMDGPU::VGPR_16RegClassID, AMDGPU::VGPR_32RegClassID,
3504 AMDGPU::VReg_64RegClassID, AMDGPU::VReg_96RegClassID,
3505 AMDGPU::VReg_128RegClassID, AMDGPU::VReg_160RegClassID,
3506 AMDGPU::VReg_192RegClassID, AMDGPU::VReg_224RegClassID,
3507 AMDGPU::VReg_256RegClassID, AMDGPU::VReg_288RegClassID,
3508 AMDGPU::VReg_320RegClassID, AMDGPU::VReg_352RegClassID,
3509 AMDGPU::VReg_384RegClassID, AMDGPU::VReg_512RegClassID,
3510 AMDGPU::VReg_1024RegClassID};
3511
3512 for (unsigned RCID : VGPRClasses) {
3513 const MCRegisterClass &RC = MRI.getRegClass(RCID);
3514 if (RC.contains(Reg))
3515 return &RC;
3516 }
3517
3518 return nullptr;
3519}
3520
3522 unsigned Enc = MRI.getEncodingValue(Reg);
3523 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
3524 return Idx >> 8;
3525}
3526
3528 const MCRegisterInfo &MRI) {
3529 unsigned Enc = MRI.getEncodingValue(Reg);
3530 unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
3531 if (Idx >= 0x100)
3532 return MCRegister();
3533
3534 const MCRegisterClass *RC = getVGPRPhysRegClass(Reg, MRI);
3535 if (!RC)
3536 return MCRegister();
3537
3538 Idx |= MSBs << 8;
3539 if (RC->getID() == AMDGPU::VGPR_16RegClassID) {
3540 // This class has 2048 registers with interleaved lo16 and hi16.
3541 Idx *= 2;
3543 ++Idx;
3544 }
3545
3546 return RC->getRegister(Idx);
3547}
3548
3549static std::optional<unsigned>
3550convertSetRegImmToVgprMSBs(unsigned Imm, unsigned Simm16,
3551 bool HasSetregVGPRMSBFixup) {
3552 constexpr unsigned VGPRMSBShift =
3554
3555 auto [HwRegId, Offset, Size] = Hwreg::HwregEncoding::decode(Simm16);
3556 if (HwRegId != Hwreg::ID_MODE ||
3557 (!HasSetregVGPRMSBFixup && (Offset + Size) < VGPRMSBShift))
3558 return {};
3559 // If there is SetregVGPRMSBFixup then Offset is ignored.
3560 if (!HasSetregVGPRMSBFixup)
3561 Imm <<= Offset;
3562 Imm = (Imm & Hwreg::VGPR_MSB_MASK) >> VGPRMSBShift;
3563 if (!HasSetregVGPRMSBFixup)
3565 return llvm::rotr<uint8_t>(static_cast<uint8_t>(Imm), /*R=*/2);
3566}
3567
3568std::optional<unsigned> convertSetRegImmToVgprMSBs(const MachineInstr &MI,
3569 bool HasSetregVGPRMSBFixup) {
3570 assert(MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32);
3571 return convertSetRegImmToVgprMSBs(MI.getOperand(0).getImm(),
3572 MI.getOperand(1).getImm(),
3573 HasSetregVGPRMSBFixup);
3574}
3575
3576std::optional<unsigned> convertSetRegImmToVgprMSBs(const MCInst &MI,
3577 bool HasSetregVGPRMSBFixup) {
3578 assert(MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32_gfx12);
3579 return convertSetRegImmToVgprMSBs(MI.getOperand(0).getImm(),
3580 MI.getOperand(1).getImm(),
3581 HasSetregVGPRMSBFixup);
3582}
3583
3584std::pair<const AMDGPU::OpName *, const AMDGPU::OpName *>
3586 static const AMDGPU::OpName VOPOps[4] = {
3587 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2,
3588 AMDGPU::OpName::vdst};
3589 static const AMDGPU::OpName VDSOps[4] = {
3590 AMDGPU::OpName::addr, AMDGPU::OpName::data0, AMDGPU::OpName::data1,
3591 AMDGPU::OpName::vdst};
3592 static const AMDGPU::OpName FLATOps[4] = {
3593 AMDGPU::OpName::vaddr, AMDGPU::OpName::vdata,
3594 AMDGPU::OpName::NUM_OPERAND_NAMES, AMDGPU::OpName::vdst};
3595 static const AMDGPU::OpName BUFOps[4] = {
3596 AMDGPU::OpName::vaddr, AMDGPU::OpName::NUM_OPERAND_NAMES,
3597 AMDGPU::OpName::NUM_OPERAND_NAMES, AMDGPU::OpName::vdata};
3598 static const AMDGPU::OpName VIMGOps[4] = {
3599 AMDGPU::OpName::vaddr0, AMDGPU::OpName::vaddr1, AMDGPU::OpName::vaddr2,
3600 AMDGPU::OpName::vdata};
3601
3602 // For VOPD instructions MSB of a corresponding Y component operand VGPR
3603 // address is supposed to match X operand, otherwise VOPD shall not be
3604 // combined.
3605 static const AMDGPU::OpName VOPDOpsX[4] = {
3606 AMDGPU::OpName::src0X, AMDGPU::OpName::vsrc1X, AMDGPU::OpName::vsrc2X,
3607 AMDGPU::OpName::vdstX};
3608 static const AMDGPU::OpName VOPDOpsY[4] = {
3609 AMDGPU::OpName::src0Y, AMDGPU::OpName::vsrc1Y, AMDGPU::OpName::vsrc2Y,
3610 AMDGPU::OpName::vdstY};
3611
3612 // VOP2 MADMK instructions use src0, imm, src1 scheme.
3613 static const AMDGPU::OpName VOP2MADMKOps[4] = {
3614 AMDGPU::OpName::src0, AMDGPU::OpName::NUM_OPERAND_NAMES,
3615 AMDGPU::OpName::src1, AMDGPU::OpName::vdst};
3616 static const AMDGPU::OpName VOPDFMAMKOpsX[4] = {
3617 AMDGPU::OpName::src0X, AMDGPU::OpName::NUM_OPERAND_NAMES,
3618 AMDGPU::OpName::vsrc1X, AMDGPU::OpName::vdstX};
3619 static const AMDGPU::OpName VOPDFMAMKOpsY[4] = {
3620 AMDGPU::OpName::src0Y, AMDGPU::OpName::NUM_OPERAND_NAMES,
3621 AMDGPU::OpName::vsrc1Y, AMDGPU::OpName::vdstY};
3622
3626 switch (Desc.getOpcode()) {
3627 // LD_SCALE operands ignore MSB.
3628 case AMDGPU::V_WMMA_LD_SCALE_PAIRED_B32:
3629 case AMDGPU::V_WMMA_LD_SCALE_PAIRED_B32_gfx1250:
3630 case AMDGPU::V_WMMA_LD_SCALE16_PAIRED_B64:
3631 case AMDGPU::V_WMMA_LD_SCALE16_PAIRED_B64_gfx1250:
3632 return {};
3633 case AMDGPU::V_FMAMK_F16:
3634 case AMDGPU::V_FMAMK_F16_t16:
3635 case AMDGPU::V_FMAMK_F16_t16_gfx12:
3636 case AMDGPU::V_FMAMK_F16_fake16:
3637 case AMDGPU::V_FMAMK_F16_fake16_gfx12:
3638 case AMDGPU::V_FMAMK_F32:
3639 case AMDGPU::V_FMAMK_F32_gfx12:
3640 case AMDGPU::V_FMAMK_F64:
3641 case AMDGPU::V_FMAMK_F64_gfx1250:
3642 return {VOP2MADMKOps, nullptr};
3643 default:
3644 break;
3645 }
3646 return {VOPOps, nullptr};
3647 }
3648
3650 return {VDSOps, nullptr};
3651
3653 return {FLATOps, nullptr};
3654
3656 return {BUFOps, nullptr};
3657
3659 return {VIMGOps, nullptr};
3660
3661 if (AMDGPU::isVOPD(Desc.getOpcode())) {
3662 auto [OpX, OpY] = getVOPDComponents(Desc.getOpcode());
3663 return {(OpX == AMDGPU::V_FMAMK_F32) ? VOPDFMAMKOpsX : VOPDOpsX,
3664 (OpY == AMDGPU::V_FMAMK_F32) ? VOPDFMAMKOpsY : VOPDOpsY};
3665 }
3666
3668
3670 llvm_unreachable("Sample and export VGPR lowering is not implemented and"
3671 " these instructions are not expected on gfx1250");
3672
3673 return {};
3674}
3675
3676bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode) {
3677 const MCInstrDesc &Desc = MII.get(Opcode);
3679 return Desc.mayLoad() && !Desc.mayStore() && !getSMEMIsBuffer(Opcode);
3681 return false;
3682
3683 // Only SV and SVS modes are supported.
3684 if (SIInstrFlags::isFlatScratch(MII, Opcode))
3685 return hasNamedOperand(Opcode, OpName::vaddr);
3686
3687 // Only GVS mode is supported.
3688 return hasNamedOperand(Opcode, OpName::vaddr) &&
3689 hasNamedOperand(Opcode, OpName::saddr);
3690
3691 return false;
3692}
3693
3694bool hasAny64BitVGPROperands(const MCInstrDesc &OpDesc, const MCInstrInfo &MII,
3695 const MCSubtargetInfo &ST) {
3696 for (auto OpName : {OpName::vdst, OpName::src0, OpName::src1, OpName::src2}) {
3697 int Idx = getNamedOperandIdx(OpDesc.getOpcode(), OpName);
3698 if (Idx == -1)
3699 continue;
3700
3701 const MCOperandInfo &OpInfo = OpDesc.operands()[Idx];
3702 int16_t RegClass = MII.getOpRegClassID(
3703 OpInfo, ST.getHwMode(MCSubtargetInfo::HwMode_RegInfo));
3704 if (RegClass == AMDGPU::VReg_64RegClassID ||
3705 RegClass == AMDGPU::VReg_64_Align2RegClassID)
3706 return true;
3707 }
3708
3709 return false;
3710}
3711
3712bool isDPALU_DPP32BitOpc(unsigned Opc) {
3713 switch (Opc) {
3714 case AMDGPU::V_MUL_LO_U32_e64:
3715 case AMDGPU::V_MUL_LO_U32_e64_dpp:
3716 case AMDGPU::V_MUL_LO_U32_e64_dpp_gfx1250:
3717 case AMDGPU::V_MUL_HI_U32_e64:
3718 case AMDGPU::V_MUL_HI_U32_e64_dpp:
3719 case AMDGPU::V_MUL_HI_U32_e64_dpp_gfx1250:
3720 case AMDGPU::V_MUL_HI_I32_e64:
3721 case AMDGPU::V_MUL_HI_I32_e64_dpp:
3722 case AMDGPU::V_MUL_HI_I32_e64_dpp_gfx1250:
3723 case AMDGPU::V_MAD_U32_e64:
3724 case AMDGPU::V_MAD_U32_e64_dpp:
3725 case AMDGPU::V_MAD_U32_e64_dpp_gfx1250:
3726 return true;
3727 default:
3728 return false;
3729 }
3730}
3731
3732bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII,
3733 const MCSubtargetInfo &ST) {
3734 if (!ST.hasFeature(AMDGPU::FeatureDPALU_DPP))
3735 return false;
3736
3737 if (isDPALU_DPP32BitOpc(OpDesc.getOpcode()))
3738 return ST.hasFeature(AMDGPU::FeatureGFX1250Insts);
3739
3740 return hasAny64BitVGPROperands(OpDesc, MII, ST);
3741}
3742
3744 if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize32768))
3745 return 64;
3746 if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize65536))
3747 return 128;
3748 if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize196608))
3749 return 256;
3750 if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize163840))
3751 return 320;
3752 if (ST.getFeatureBits().test(FeatureAddressableLocalMemorySize327680))
3753 return 512;
3754 return 64; // In sync with getAddressableLocalMemorySize
3755}
3756
3758 switch (Opc) {
3759 case AMDGPU::V_PK_ADD_F32_gfx1250:
3760 case AMDGPU::V_PK_ADD_F32_gfx1250_gfx12:
3761 case AMDGPU::V_PK_MUL_F32_gfx1250:
3762 case AMDGPU::V_PK_MUL_F32_gfx1250_gfx12:
3763 case AMDGPU::V_PK_FMA_F32_gfx1250:
3764 case AMDGPU::V_PK_FMA_F32_gfx1250_gfx12:
3765 return true;
3766 default:
3767 return false;
3768 }
3769}
3770
3772 switch (Opc) {
3773 case AMDGPU::V_PK_ADD_F64:
3774 case AMDGPU::V_PK_ADD_F64_gfx1250:
3775 case AMDGPU::V_PK_MUL_F64:
3776 case AMDGPU::V_PK_MUL_F64_gfx1250:
3777 case AMDGPU::V_PK_FMA_F64:
3778 case AMDGPU::V_PK_FMA_F64_gfx1250:
3779 case AMDGPU::V_PK_MAX_NUM_F64:
3780 case AMDGPU::V_PK_MAX_NUM_F64_gfx1250:
3781 case AMDGPU::V_PK_MIN_NUM_F64:
3782 case AMDGPU::V_PK_MIN_NUM_F64_gfx1250:
3783 case AMDGPU::V_PK_ADD_NC_U64:
3784 case AMDGPU::V_PK_ADD_NC_U64_gfx1250:
3785 case AMDGPU::V_PK_SUB_NC_U64:
3786 case AMDGPU::V_PK_SUB_NC_U64_gfx1250:
3787 case AMDGPU::V_PK_LSHL_ADD_U64:
3788 case AMDGPU::V_PK_LSHL_ADD_U64_gfx1250:
3789 return true;
3790 default:
3791 return false;
3792 }
3793}
3794
3798
3799const std::array<unsigned, 3> &ClusterDimsAttr::getDims() const {
3800 assert(isFixedDims() && "expect kind to be FixedDims");
3801 return Dims;
3802}
3803
3804std::string ClusterDimsAttr::to_string() const {
3805 SmallString<10> Buffer;
3806 raw_svector_ostream OS(Buffer);
3807
3808 switch (getKind()) {
3809 case Kind::Unknown:
3810 return "";
3811 case Kind::NoCluster: {
3812 OS << EncoNoCluster << ',' << EncoNoCluster << ',' << EncoNoCluster;
3813 return Buffer.c_str();
3814 }
3815 case Kind::VariableDims: {
3816 OS << EncoVariableDims << ',' << EncoVariableDims << ','
3817 << EncoVariableDims;
3818 return Buffer.c_str();
3819 }
3820 case Kind::FixedDims: {
3821 OS << Dims[0] << ',' << Dims[1] << ',' << Dims[2];
3822 return Buffer.c_str();
3823 }
3824 }
3825 llvm_unreachable("Unknown ClusterDimsAttr kind");
3826}
3827
3829 std::optional<SmallVector<unsigned>> Attr =
3830 getIntegerVecAttribute(F, "amdgpu-cluster-dims", /*Size=*/3);
3832
3833 if (!Attr.has_value())
3834 AttrKind = Kind::Unknown;
3835 else if (all_of(*Attr, equal_to(EncoNoCluster)))
3836 AttrKind = Kind::NoCluster;
3837 else if (all_of(*Attr, equal_to(EncoVariableDims)))
3838 AttrKind = Kind::VariableDims;
3839
3840 ClusterDimsAttr A(AttrKind);
3841 if (AttrKind == Kind::FixedDims)
3842 A.Dims = {(*Attr)[0], (*Attr)[1], (*Attr)[2]};
3843
3844 return A;
3845}
3846
3847std::optional<APFloat> evaluateRcp(const APFloat &Val) {
3848 const fltSemantics &Sem = Val.getSemantics();
3849
3850 // v_rcp_f16/bf16 are correctly rounded.
3851 if (&Sem == &APFloat::IEEEhalf() || &Sem == &APFloat::BFloat())
3852 return APFloat::getOne(Sem) / Val;
3853
3854 // v_rcp_f32/f64 always flush a denormal input to zero (preserving sign)
3855 // before reciprocating.
3856 APFloat Arg = Val;
3857 if (Arg.isDenormal())
3858 Arg = APFloat::getZero(Sem, Arg.isNegative());
3859
3860 APFloat Result = APFloat::getOne(Sem) / Arg;
3861
3862 // v_rcp_f32/f64 always flush a denormal result to zero (preserving sign).
3863 if (Result.isDenormal())
3864 Result = APFloat::getZero(Sem, Result.isNegative());
3865
3866 // v_rcp_f32/f64 only approximate the reciprocal, except for these special
3867 // cases where the result is exact.
3868 if (!Result.isZero() && !Result.isInfinity() && !Result.isNaN() &&
3869 !Result.isOne() && !Result.isMinusOne())
3870 return std::nullopt;
3871
3872 return Result;
3873}
3874
3875} // namespace AMDGPU
3876
3878 switch (S) {
3879 case (AMDGPU::TargetIDSetting::Unsupported):
3880 OS << "Unsupported";
3881 break;
3882 case (AMDGPU::TargetIDSetting::Any):
3883 OS << "Any";
3884 break;
3885 case (AMDGPU::TargetIDSetting::Off):
3886 OS << "Off";
3887 break;
3888 case (AMDGPU::TargetIDSetting::On):
3889 OS << "On";
3890 break;
3891 }
3892 return OS;
3893}
3894
3895} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static llvm::cl::opt< unsigned > DefaultAMDHSACodeObjectVersion("amdhsa-code-object-version", llvm::cl::Hidden, llvm::cl::init(llvm::AMDGPU::AMDHSA_COV6), llvm::cl::desc("Set default AMDHSA Code Object Version (module flag " "or asm directive still take priority if present)"))
#define MAP_REG2REG
unsigned uint64_t
Provides AMDGPU specific target descriptions.
MC layer struct for AMDGPUMCKernelCodeT, provides MCExpr functionality where required.
@ AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
IRTranslator LLVM IR MI
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
Register const TargetRegisterInfo * TRI
This file contains the declarations for metadata subclasses.
#define T
uint64_t High
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
#define S_00B848_MEM_ORDERED(x)
Definition SIDefines.h:1483
#define S_00B848_WGP_MODE(x)
Definition SIDefines.h:1480
#define S_00B848_FWD_PROGRESS(x)
Definition SIDefines.h:1486
This file contains some functions that are useful when dealing with strings.
static const int BlockSize
Definition TarWriter.cpp:33
static ClusterDimsAttr get(const Function &F)
const std::array< unsigned, 3 > & getDims() const
void setSramEccSetting(TargetIDSetting NewSramEccSetting)
Sets sramecc setting to NewSramEccSetting.
void setXnackSetting(TargetIDSetting NewXnackSetting)
Sets xnack setting to NewXnackSetting.
unsigned getIndexInParsedOperands(unsigned CompOprIdx) const
unsigned getIndexOfSrcInParsedOperands(unsigned CompSrcIdx) const
std::optional< unsigned > getInvalidCompOperandIndex(std::function< MCRegister(unsigned, unsigned)> GetRegIdx, const MCRegisterInfo &MRI, bool SkipSrc=false, bool AllowSameVGPR=false, bool VOPD3=false) const
std::array< MCRegister, Component::MAX_OPR_NUM > RegIndices
Represents the counter values to wait for in an s_waitcnt instruction.
static const fltSemantics & BFloat()
Definition APFloat.h:303
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
bool isNegative() const
Definition APFloat.h:1575
bool isDenormal() const
Definition APFloat.h:1576
const fltSemantics & getSemantics() const
Definition APFloat.h:1583
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1184
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1175
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
CallingConv::ID getCallingConv() const
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
constexpr bool test(unsigned I) const
unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
unsigned getOpcode() const
Return the opcode number for this descriptor.
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
int16_t getOpRegClassID(const MCOperandInfo &OpInfo, unsigned HwModeId) const
Return the ID of the register class to use for OpInfo, for the active HwMode HwModeId.
Definition MCInstrInfo.h:79
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:86
MCRegisterClass - Base class of TargetRegisterClass.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool regsOverlap(MCRegister RegA, MCRegister RegB) const
Returns true if the two registers are equal or alias each other.
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
MCRegister getSubReg(MCRegister Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr unsigned id() const
Definition MCRegister.h:82
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
const FeatureBitset & getFeatureBits() const
StringRef getCPU() const
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
Representation of each machine instruction.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
const char * c_str()
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
Manages the enabling and disabling of subtarget specific features.
const std::vector< std::string > & getFeatures() const
Returns the vector of individual subtarget features.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:521
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:512
bool isAMDGCN() const
Tests whether the target is AMDGCN.
Definition Triple.h:990
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
unsigned decodeFieldVaVcc(unsigned Encoded)
unsigned encodeFieldVaVcc(unsigned Encoded, unsigned VaVcc)
unsigned decodeFieldHoldCnt(unsigned Encoded, const IsaVersion &Version)
bool decodeDepCtr(unsigned Code, int &Id, StringRef &Name, unsigned &Val, bool &IsDefault, const MCSubtargetInfo &STI)
unsigned encodeFieldHoldCnt(unsigned Encoded, unsigned HoldCnt, const IsaVersion &Version)
unsigned encodeFieldVaSsrc(unsigned Encoded, unsigned VaSsrc)
unsigned encodeFieldVaVdst(unsigned Encoded, unsigned VaVdst)
unsigned decodeFieldSaSdst(unsigned Encoded)
unsigned getHoldCntBitMask(const IsaVersion &Version)
unsigned decodeFieldVaSdst(unsigned Encoded)
unsigned encodeFieldVmVsrc(unsigned Encoded, unsigned VmVsrc)
unsigned decodeFieldVaSsrc(unsigned Encoded)
int encodeDepCtr(const StringRef Name, int64_t Val, unsigned &UsedOprMask, const MCSubtargetInfo &STI)
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
const CustomOperandVal DepCtrInfo[]
bool isSymbolicDepCtrEncoding(unsigned Code, bool &HasNonDefaultVal, const MCSubtargetInfo &STI)
unsigned decodeFieldVaVdst(unsigned Encoded)
int getDefaultDepCtrEncoding(const MCSubtargetInfo &STI)
unsigned decodeFieldVmVsrc(unsigned Encoded)
unsigned encodeFieldVaSdst(unsigned Encoded, unsigned VaSdst)
bool isSupportedTgtId(unsigned Id, const MCSubtargetInfo &STI)
static constexpr ExpTgt ExpTgtInfo[]
bool getTgtName(unsigned Id, StringRef &Name, int &Index)
unsigned getTgtId(const StringRef Name)
constexpr uint32_t VersionMinor
HSA metadata minor version.
constexpr uint32_t VersionMajor
HSA metadata major version.
unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo &STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize)
static unsigned getMaxHWAddressableLocalMemorySize(const MCSubtargetInfo &STI)
unsigned getAddressableNumArchVGPRs(const MCSubtargetInfo &STI)
bool isSGPROccupancyLimited(const MCSubtargetInfo &STI)
unsigned getArchVGPRAllocGranule()
For subtargets with a unified VGPR file and mixed ArchVGPR/AGPR usage, returns the allocation granule...
unsigned getEUsPerCU(const MCSubtargetInfo &STI)
static unsigned getPhysicalLocalMemorySize(const MCSubtargetInfo &STI)
static unsigned getSGPRTrapHandlerReserve(const MCSubtargetInfo &STI)
unsigned getMinFlatWorkGroupSize(const MCSubtargetInfo &STI)
unsigned getAddressableLocalMemorySize(const MCSubtargetInfo &STI)
unsigned getVGPREncodingGranule(const MCSubtargetInfo &STI, std::optional< bool > EnableWavefrontSize32)
unsigned getEncodedNumVGPRBlocks(const MCSubtargetInfo &STI, unsigned NumVGPRs, std::optional< bool > EnableWavefrontSize32)
unsigned getMaxWorkGroupsPerCU(const MCSubtargetInfo &STI, unsigned FlatWorkGroupSize)
unsigned getMinNumSGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU)
unsigned getMaxNumSGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU, bool Addressable)
unsigned getWavefrontSize(const MCSubtargetInfo &STI)
unsigned getWavesPerEUForWorkGroup(const MCSubtargetInfo &STI, unsigned FlatWorkGroupSize)
unsigned getInstCacheLineSize(const MCSubtargetInfo &STI)
static constexpr unsigned MaxDynamicVGPRBlocks
Maximum number of VGPR blocks that can be allocated in dynamic VGPR mode.
unsigned getSGPREncodingGranule(const MCSubtargetInfo &STI)
static unsigned getSGPRBudgetPerWave(unsigned TotalNumSGPRs, unsigned WavesPerEU, unsigned TrapReserve, unsigned Granule)
unsigned getTotalNumVGPRs(const MCSubtargetInfo &STI)
unsigned getMinNumVGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU, unsigned DynamicVGPRBlockSize)
unsigned getAddressableNumVGPRs(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize)
unsigned getWavesPerWorkGroup(const MCSubtargetInfo &STI, unsigned FlatWorkGroupSize)
unsigned getAllocatedNumVGPRBlocks(const MCSubtargetInfo &STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves, unsigned TotalNumSGPRs, unsigned Granule, unsigned TrapReserve)
unsigned getNumSGPRBlocks(const MCSubtargetInfo &STI, unsigned NumSGPRs)
unsigned getMaxWavesPerEU(const MCSubtargetInfo &STI)
unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed, bool FlatScrUsed, bool XNACKUsed)
unsigned getLocalMemorySize(const MCSubtargetInfo &STI)
unsigned getMaxNumVGPRs(const MCSubtargetInfo &STI, unsigned WavesPerEU, unsigned DynamicVGPRBlockSize)
static unsigned getGranulatedNumRegisterBlocks(unsigned NumRegs, unsigned Granule)
unsigned getVGPRAllocGranule(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getMinWavesPerEU(const MCSubtargetInfo &STI)
StringLiteral const UfmtSymbolicGFX11[]
bool isValidUnifiedFormat(unsigned Id, const MCSubtargetInfo &STI)
unsigned getDefaultFormatEncoding(const MCSubtargetInfo &STI)
StringRef getUnifiedFormatName(unsigned Id, const MCSubtargetInfo &STI)
unsigned const DfmtNfmt2UFmtGFX10[]
StringLiteral const DfmtSymbolic[]
static StringLiteral const * getNfmtLookupTable(const MCSubtargetInfo &STI)
bool isValidNfmt(unsigned Id, const MCSubtargetInfo &STI)
StringLiteral const NfmtSymbolicGFX10[]
bool isValidDfmtNfmt(unsigned Id, const MCSubtargetInfo &STI)
int64_t convertDfmtNfmt2Ufmt(unsigned Dfmt, unsigned Nfmt, const MCSubtargetInfo &STI)
StringRef getDfmtName(unsigned Id)
int64_t encodeDfmtNfmt(unsigned Dfmt, unsigned Nfmt)
int64_t getUnifiedFormat(const StringRef Name, const MCSubtargetInfo &STI)
bool isValidFormatEncoding(unsigned Val, const MCSubtargetInfo &STI)
StringRef getNfmtName(unsigned Id, const MCSubtargetInfo &STI)
unsigned const DfmtNfmt2UFmtGFX11[]
StringLiteral const NfmtSymbolicVI[]
StringLiteral const NfmtSymbolicSICI[]
int64_t getNfmt(const StringRef Name, const MCSubtargetInfo &STI)
int64_t getDfmt(const StringRef Name)
StringLiteral const UfmtSymbolicGFX10[]
void decodeDfmtNfmt(unsigned Format, unsigned &Dfmt, unsigned &Nfmt)
uint64_t encodeMsg(uint64_t MsgId, uint64_t OpId, uint64_t StreamId)
bool msgSupportsStream(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI)
void decodeMsg(unsigned Val, uint16_t &MsgId, uint16_t &OpId, uint16_t &StreamId, const MCSubtargetInfo &STI)
bool isValidMsgId(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgStream(int64_t MsgId, int64_t OpId, int64_t StreamId, const MCSubtargetInfo &STI, bool Strict)
bool msgDoesNotUseM0(int64_t MsgId, const MCSubtargetInfo &STI)
Returns true if the message does not use the m0 operand.
StringRef getMsgOpName(int64_t MsgId, uint64_t Encoding, const MCSubtargetInfo &STI)
Map from an encoding to the symbolic name for a sendmsg operation.
static uint64_t getMsgIdMask(const MCSubtargetInfo &STI)
bool msgRequiresOp(int64_t MsgId, const MCSubtargetInfo &STI)
bool isValidMsgOp(int64_t MsgId, int64_t OpId, const MCSubtargetInfo &STI, bool Strict)
constexpr unsigned VOPD_VGPR_BANK_MASKS[]
constexpr unsigned COMPONENTS_NUM
constexpr unsigned VOPD3_VGPR_BANK_MASKS[]
bool isGCN3Encoding(const MCSubtargetInfo &STI)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
bool isGFX10_BEncoding(const MCSubtargetInfo &STI)
bool isInlineValue(MCRegister Reg)
bool isGFX10_GFX11(const MCSubtargetInfo &STI)
bool isInlinableLiteralV216(uint32_t Literal, uint8_t OpType)
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool isSGPR(MCRegister Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset)
Convert ByteOffset to dwords if the subtarget uses dword SMRD immediate offsets.
static unsigned encodeStorecnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Storecnt)
MCRegister getMCReg(MCRegister Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg.
static bool hasSMEMByteOffset(const MCSubtargetInfo &ST)
bool isVOPCAsmOnly(unsigned Opc)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
bool getMTBUFHasSrsrc(unsigned Opc)
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool getWMMAIsXDL(unsigned Opc)
static std::optional< unsigned > convertSetRegImmToVgprMSBs(unsigned Imm, unsigned Simm16, bool HasSetregVGPRMSBFixup)
uint8_t wmmaScaleF8F6F4FormatToNumRegs(unsigned Fmt)
static bool isSymbolicCustomOperandEncoding(const CustomOperandVal *Opr, int Size, unsigned Code, bool &HasNonDefaultVal, const MCSubtargetInfo &STI)
bool isGFX10Before1030(const MCSubtargetInfo &STI)
bool isSISrcInlinableOperand(const MCInstrDesc &Desc, unsigned OpNo)
Does this operand support only inlinable literals?
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
const int OPR_ID_UNSUPPORTED
void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &KernelCode, const MCSubtargetInfo &STI)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
int getMTBUFElements(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
static int encodeCustomOperandVal(const CustomOperandVal &Op, int64_t InputVal)
unsigned getTemporalHintType(const MCInstrDesc TID)
int32_t getTotalNumVGPRs(bool has90AInsts, int32_t ArgNumAGPR, int32_t ArgNumVGPR)
bool isGFX10(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV216(bool IsFloat, uint32_t Literal)
FPType getFPDstSelType(unsigned Opc)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool hasA16(const MCSubtargetInfo &STI)
bool isLegalSMRDEncodedSignedOffset(const MCSubtargetInfo &ST, int64_t EncodedOffset, bool IsBuffer)
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
const MCRegisterClass * getVGPRPhysRegClass(MCRegister Reg, const MCRegisterInfo &MRI)
unsigned encodeLoadcntDscnt(const IsaVersion &Version, const Waitcnt &Decoded)
bool getHasMatrixScale(unsigned Opc)
bool hasPackedD16(const MCSubtargetInfo &STI)
unsigned getStorecntBitMask(const IsaVersion &Version)
bool isFullSIMDMode(const MCSubtargetInfo &STI)
unsigned getLdsDwGranularity(const MCSubtargetInfo &ST)
bool isGFX940(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
bool isHsaAbi(const MCSubtargetInfo &STI)
bool isGFX11(const MCSubtargetInfo &STI)
const int OPR_VAL_INVALID
bool getSMEMIsBuffer(unsigned Opc)
bool isPackedSingleSGPRFP32Inst(unsigned Opc)
The opcode is a packed fp32 instruction which only reads low 32 bits of a scalar operand and propagat...
bool isGFX10_3_GFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
unsigned getAsynccntBitMask(const IsaVersion &Version)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_ABI unsigned getAddressableNumSGPRs(GPUKind AK)
TargetID createAMDGPUTargetID(const MCSubtargetInfo &STI, StringRef FeatureString)
Construct TargetID from MCSubtargetInfo.
uint8_t mfmaScaleF8F6F4FormatToNumRegs(unsigned EncodingVal)
unsigned getVOPDOpcode(unsigned Opc, bool VOPD3)
bool isGroupSegment(const GlobalValue *GV)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
bool getMTBUFHasSoffset(unsigned Opc)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool hasXNACK(const MCSubtargetInfo &STI)
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
static unsigned getCombinedCountBitMask(const IsaVersion &Version, bool IsStore)
CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3)
bool isVOPC64DPP(unsigned Opc)
int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements)
bool getMAIIsGFX940XDL(unsigned Opc)
bool isSI(const MCSubtargetInfo &STI)
unsigned getDefaultAMDHSACodeObjectVersion()
LLVM_ABI unsigned getTotalNumSGPRs(GPUKind AK)
bool hasPrivateApertureRegs(const MCSubtargetInfo &STI)
bool isReadOnlySegment(const GlobalValue *GV)
Waitcnt decodeWaitcnt(const IsaVersion &Version, unsigned Encoded)
bool isArgPassedInSGPR(const Argument *A)
bool isIntrinsicAlwaysUniform(unsigned IntrID)
int getMUBUFBaseOpcode(unsigned Opc)
unsigned encodeWaitcnt(const IsaVersion &Version, const Waitcnt &Decoded)
unsigned getAMDHSACodeObjectVersion(const Module &M)
unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt)
unsigned getWaitcntBitMask(const IsaVersion &Version)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool getVOP3IsSingle(unsigned Opc)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
bool isGFX9(const MCSubtargetInfo &STI)
bool isDPALU_DPP32BitOpc(unsigned Opc)
bool getVOP1IsSingle(unsigned Opc)
static bool isDwordAligned(uint64_t ByteOffset)
unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST)
bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this a KImm operand?
bool getHasColorExport(const Function &F)
GPUKind
GPU kinds supported by the AMDGPU target.
int getMTBUFBaseOpcode(unsigned Opc)
bool isGFX90A(const MCSubtargetInfo &STI)
unsigned getSamplecntBitMask(const IsaVersion &Version)
unsigned getDefaultQueueImplicitArgPosition(unsigned CodeObjectVersion)
std::tuple< char, unsigned, unsigned > parseAsmPhysRegName(StringRef RegName)
Returns a valid charcode or 0 in the first entry if this is a valid physical register name.
bool getHasDepthExport(const Function &F)
bool isGFX8_GFX9_GFX10(const MCSubtargetInfo &STI)
bool getMUBUFHasVAddr(unsigned Opc)
bool isTrue16Inst(unsigned Opc)
LLVM_ABI unsigned getSGPRAllocGranule(GPUKind AK)
unsigned getVGPREncodingMSBs(MCRegister Reg, const MCRegisterInfo &MRI)
std::pair< unsigned, unsigned > getVOPDComponents(unsigned VOPDOpcode)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool isGFX12(const MCSubtargetInfo &STI)
unsigned getInitialPSInputAddr(const Function &F)
unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Expcnt)
bool isAsyncStore(unsigned Opc)
unsigned getDynamicVGPRBlockSize(const Function &F)
unsigned getKmcntBitMask(const IsaVersion &Version)
MCRegister getVGPRWithMSBs(MCRegister Reg, unsigned MSBs, const MCRegisterInfo &MRI)
If Reg is a low VGPR return a corresponding high VGPR with MSBs set.
unsigned getVmcntBitMask(const IsaVersion &Version)
bool isNotGFX10Plus(const MCSubtargetInfo &STI)
bool hasMAIInsts(const MCSubtargetInfo &STI)
unsigned getBitOp2(unsigned Opc)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
unsigned getXcntBitMask(const IsaVersion &Version)
bool isGenericAtomic(unsigned Opc)
const MFMA_F8F6F4_Info * getWMMA_F8F6F4_WithFormatArgs(unsigned FmtA, unsigned FmtB, unsigned F8F8Opcode)
bool isGFX8Plus(const MCSubtargetInfo &STI)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getLgkmcntBitMask(const IsaVersion &Version)
bool getMUBUFTfe(unsigned Opc)
unsigned getBvhcntBitMask(const IsaVersion &Version)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
bool hasMIMG_R128(const MCSubtargetInfo &STI)
LLVM_ABI GPUKind parseArchAMDGCN(StringRef CPU)
bool hasGFX10_3Insts(const MCSubtargetInfo &STI)
unsigned decodeDscnt(const IsaVersion &Version, unsigned Waitcnt)
std::pair< const AMDGPU::OpName *, const AMDGPU::OpName * > getVGPRLoweringOperandTables(const MCInstrDesc &Desc)
bool hasG16(const MCSubtargetInfo &STI)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements)
bool isGFX13Plus(const MCSubtargetInfo &STI)
unsigned getExpcntBitMask(const IsaVersion &Version)
bool hasArchitectedFlatScratch(const MCSubtargetInfo &STI)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
bool getMUBUFHasSoffset(unsigned Opc)
bool isNotGFX11Plus(const MCSubtargetInfo &STI)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this floating-point operand?
std::optional< APFloat > evaluateRcp(const APFloat &Val)
Evaluate the constant-folded result of v_rcp for Val, accounting for the hardware's denormal flushing...
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
unsigned getHostcallImplicitArgPosition(unsigned CodeObjectVersion)
static unsigned getDefaultCustomOperandEncoding(const CustomOperandVal *Opr, int Size, const MCSubtargetInfo &STI)
static unsigned encodeLoadcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Loadcnt)
bool isGFX10Plus(const MCSubtargetInfo &STI)
static bool decodeCustomOperand(const CustomOperandVal *Opr, int Size, unsigned Code, int &Idx, StringRef &Name, unsigned &Val, bool &IsDefault, const MCSubtargetInfo &STI)
static bool isValidRegPrefix(char C)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
AMDGPU::TargetID TargetID
bool isGlobalSegment(const GlobalValue *GV)
SmallVector< unsigned > getMaxNumWorkGroups(const Function &F)
int64_t encode32BitLiteral(int64_t Imm, OperandType Type, bool IsLit)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:447
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:465
@ OPERAND_REG_INLINE_C_LAST
Definition SIDefines.h:488
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:456
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:458
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:442
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:437
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:439
@ OPERAND_REG_INLINE_AC_FIRST
Definition SIDefines.h:490
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:441
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:444
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:436
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:459
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:470
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:471
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:445
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_FIRST
Definition SIDefines.h:487
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:455
@ OPERAND_REG_INLINE_AC_LAST
Definition SIDefines.h:491
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:457
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:472
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:454
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:462
std::optional< unsigned > getPKFMACF16InlineEncoding(uint32_t Literal, bool IsGFX11Plus)
bool isNotGFX9Plus(const MCSubtargetInfo &STI)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool hasGDS(const MCSubtargetInfo &STI)
bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST, int64_t EncodedOffset)
bool isGFX9Plus(const MCSubtargetInfo &STI)
bool hasDPPSrc1SGPR(const MCSubtargetInfo &STI)
const int OPR_ID_DUPLICATE
bool isVOPD(unsigned Opc)
VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY)
unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Vmcnt)
unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt)
bool isCvt_F32_Fp8_Bf8_e64(unsigned Opc)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
unsigned encodeStorecntDscnt(const IsaVersion &Version, const Waitcnt &Decoded)
bool isGFX1250(const MCSubtargetInfo &STI)
const MIMGBaseOpcodeInfo * getMIMGBaseOpcode(unsigned Opc)
bool isVI(const MCSubtargetInfo &STI)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool isTensorStore(unsigned Opc)
bool getMUBUFIsBufferInv(unsigned Opc)
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
MCRegister mc2PseudoReg(MCRegister Reg)
Convert hardware register Reg to a pseudo register.
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
static int encodeCustomOperand(const CustomOperandVal *Opr, int Size, const StringRef Name, int64_t InputVal, unsigned &UsedOprMask, const MCSubtargetInfo &STI)
unsigned hasKernargPreload(const MCSubtargetInfo &STI)
bool supportsWGP(const MCSubtargetInfo &STI)
bool isMAC(unsigned Opc)
bool isCI(const MCSubtargetInfo &STI)
unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Lgkmcnt)
bool getVOP2IsSingle(unsigned Opc)
bool getMAIIsDGEMM(unsigned Opc)
Returns true if MAI operation is a double precision GEMM.
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
const int OPR_ID_UNKNOWN
unsigned getCompletionActionImplicitArgPosition(unsigned CodeObjectVersion)
SmallVector< unsigned > getIntegerVecAttribute(const Function &F, StringRef Name, unsigned Size, unsigned DefaultVal)
unsigned decodeStorecnt(const IsaVersion &Version, unsigned Waitcnt)
bool isGFX1250Plus(const MCSubtargetInfo &STI)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
bool isNotGFX12Plus(const MCSubtargetInfo &STI)
bool getMTBUFHasVAddr(unsigned Opc)
bool hasPopsExitingWaveID(const MCSubtargetInfo &STI)
unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt)
uint8_t getELFABIVersion(const Triple &T, unsigned CodeObjectVersion)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
unsigned getLoadcntBitMask(const IsaVersion &Version)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
bool hasVOPD(const MCSubtargetInfo &STI)
int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily, bool VOPD3)
static unsigned encodeDscnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Dscnt)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const MFMA_F8F6F4_Info * getMFMA_F8F6F4_WithFormatArgs(unsigned CBSZ, unsigned BLGP, unsigned F8F8Opcode)
unsigned decodeLoadcnt(const IsaVersion &Version, unsigned Waitcnt)
unsigned getMultigridSyncArgImplicitArgPosition(unsigned CodeObjectVersion)
bool isGFX9_GFX10_GFX11(const MCSubtargetInfo &STI)
bool isGFX9_GFX10(const MCSubtargetInfo &STI)
int getMUBUFElements(unsigned Opc)
const GcnBufferFormatInfo * getGcnBufferFormatInfo(uint8_t BitsPerComp, uint8_t NumComponents, uint8_t NumFormat, const MCSubtargetInfo &STI)
unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc)
bool isPermlane16(unsigned Opc)
bool getMUBUFHasSrsrc(unsigned Opc)
unsigned getDscntBitMask(const IsaVersion &Version)
bool hasAny64BitVGPROperands(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ ELFABIVERSION_AMDGPU_HSA_V4
Definition ELF.h:384
@ ELFABIVERSION_AMDGPU_HSA_V5
Definition ELF.h:385
@ ELFABIVERSION_AMDGPU_HSA_V6
Definition ELF.h:386
constexpr bool isVOPC(const T &...O)
Definition SIDefines.h:237
constexpr bool isVOP3(const T &...O)
Definition SIDefines.h:240
constexpr bool isVOP1(const T &...O)
Definition SIDefines.h:231
constexpr bool isVOP2(const T &...O)
Definition SIDefines.h:234
constexpr bool isFLAT(const T &...O)
Definition SIDefines.h:287
constexpr bool isBuffer(const T &...O)
Definition SIDefines.h:268
constexpr bool isVIMAGE(const T &...O)
Definition SIDefines.h:278
constexpr bool isSMRD(const T &...O)
Definition SIDefines.h:272
constexpr bool isVOP3Like(const T &...O)
Definition SIDefines.h:246
constexpr bool isFlatScratch(const T &...O)
Definition SIDefines.h:362
constexpr bool isMIMG(const T &...O)
Definition SIDefines.h:275
constexpr bool isVOPD3(const T &...O)
Definition SIDefines.h:386
constexpr bool isEXP(const T &...O)
Definition SIDefines.h:284
constexpr bool isVSAMPLE(const T &...O)
Definition SIDefines.h:281
constexpr bool isDS(const T &...O)
Definition SIDefines.h:290
constexpr bool isAtomic(const T &...O)
Definition SIDefines.h:397
constexpr bool isDPP(const T &...O)
Definition SIDefines.h:256
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:683
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:578
constexpr T rotr(T V, int R)
Definition bit.h:399
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
testing::Matcher< const detail::ErrorHolder & > Failed()
Definition Error.h:198
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:547
std::string utostr(uint64_t X, bool isNeg=false)
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2173
Op::Description Desc
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
To bit_cast(const From &from) noexcept
Definition bit.h:90
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
constexpr int countr_zero_constexpr(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:190
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
#define N
AMD Kernel Code Object (amd_kernel_code_t).
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
Instruction set architecture version.