70 class AMDGPUAsmParser;
72 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
86 SMLoc StartLoc, EndLoc;
87 const AMDGPUAsmParser *AsmParser;
90 AMDGPUOperand(KindTy Kind_,
const AMDGPUAsmParser *AsmParser_)
93 using Ptr = std::unique_ptr<AMDGPUOperand>;
100 bool hasFPModifiers()
const {
return Abs || Neg; }
101 bool hasIntModifiers()
const {
return Sext; }
102 bool hasModifiers()
const {
return hasFPModifiers() || hasIntModifiers(); }
104 int64_t getFPModifiersOperand()
const {
111 int64_t getIntModifiersOperand()
const {
117 int64_t getModifiersOperand()
const {
118 assert(!(hasFPModifiers() && hasIntModifiers())
119 &&
"fp and int modifiers should not be used simultaneously");
120 if (hasFPModifiers()) {
121 return getFPModifiersOperand();
122 }
else if (hasIntModifiers()) {
123 return getIntModifiersOperand();
205 bool isToken()
const override {
209 if (Kind != Expression || !Expr)
216 return isa<MCSymbolRefExpr>(Expr);
219 bool isImm()
const override {
220 return Kind == Immediate;
223 bool isInlinableImm(
MVT type)
const;
224 bool isLiteralImm(
MVT type)
const;
226 bool isRegKind()
const {
230 bool isReg()
const override {
231 return isRegKind() && !hasModifiers();
235 return isRegKind() || isInlinableImm(type);
238 bool isRegOrImmWithInt16InputMods()
const {
242 bool isRegOrImmWithInt32InputMods()
const {
246 bool isRegOrImmWithInt64InputMods()
const {
250 bool isRegOrImmWithFP16InputMods()
const {
254 bool isRegOrImmWithFP32InputMods()
const {
258 bool isRegOrImmWithFP64InputMods()
const {
262 bool isVReg()
const {
263 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
264 isRegClass(AMDGPU::VReg_64RegClassID) ||
265 isRegClass(AMDGPU::VReg_96RegClassID) ||
266 isRegClass(AMDGPU::VReg_128RegClassID) ||
267 isRegClass(AMDGPU::VReg_256RegClassID) ||
268 isRegClass(AMDGPU::VReg_512RegClassID);
271 bool isVReg32OrOff()
const {
272 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
275 bool isSDWAOperand(
MVT type)
const;
276 bool isSDWAFP16Operand()
const;
277 bool isSDWAFP32Operand()
const;
278 bool isSDWAInt16Operand()
const;
279 bool isSDWAInt32Operand()
const;
281 bool isImmTy(ImmTy ImmT)
const {
282 return isImm() && Imm.Type == ImmT;
285 bool isImmModifier()
const {
286 return isImm() && Imm.Type != ImmTyNone;
289 bool isClampSI()
const {
return isImmTy(ImmTyClampSI); }
290 bool isOModSI()
const {
return isImmTy(ImmTyOModSI); }
291 bool isDMask()
const {
return isImmTy(ImmTyDMask); }
292 bool isUNorm()
const {
return isImmTy(ImmTyUNorm); }
293 bool isDA()
const {
return isImmTy(ImmTyDA); }
294 bool isR128A16()
const {
return isImmTy(ImmTyR128A16); }
295 bool isLWE()
const {
return isImmTy(ImmTyLWE); }
296 bool isOff()
const {
return isImmTy(ImmTyOff); }
297 bool isExpTgt()
const {
return isImmTy(ImmTyExpTgt); }
298 bool isExpVM()
const {
return isImmTy(ImmTyExpVM); }
299 bool isExpCompr()
const {
return isImmTy(ImmTyExpCompr); }
300 bool isOffen()
const {
return isImmTy(ImmTyOffen); }
301 bool isIdxen()
const {
return isImmTy(ImmTyIdxen); }
302 bool isAddr64()
const {
return isImmTy(ImmTyAddr64); }
303 bool isOffset()
const {
return isImmTy(ImmTyOffset) &&
isUInt<16>(getImm()); }
304 bool isOffset0()
const {
return isImmTy(ImmTyOffset0) &&
isUInt<16>(getImm()); }
305 bool isOffset1()
const {
return isImmTy(ImmTyOffset1) &&
isUInt<8>(getImm()); }
307 bool isOffsetU12()
const {
return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isUInt<12>(getImm()); }
308 bool isOffsetS13()
const {
return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isInt<13>(getImm()); }
309 bool isGDS()
const {
return isImmTy(ImmTyGDS); }
310 bool isLDS()
const {
return isImmTy(ImmTyLDS); }
311 bool isGLC()
const {
return isImmTy(ImmTyGLC); }
312 bool isSLC()
const {
return isImmTy(ImmTySLC); }
313 bool isTFE()
const {
return isImmTy(ImmTyTFE); }
314 bool isD16()
const {
return isImmTy(ImmTyD16); }
315 bool isFORMAT()
const {
return isImmTy(ImmTyFORMAT) &&
isUInt<8>(getImm()); }
316 bool isBankMask()
const {
return isImmTy(ImmTyDppBankMask); }
317 bool isRowMask()
const {
return isImmTy(ImmTyDppRowMask); }
318 bool isBoundCtrl()
const {
return isImmTy(ImmTyDppBoundCtrl); }
319 bool isSDWADstSel()
const {
return isImmTy(ImmTySdwaDstSel); }
320 bool isSDWASrc0Sel()
const {
return isImmTy(ImmTySdwaSrc0Sel); }
321 bool isSDWASrc1Sel()
const {
return isImmTy(ImmTySdwaSrc1Sel); }
322 bool isSDWADstUnused()
const {
return isImmTy(ImmTySdwaDstUnused); }
323 bool isInterpSlot()
const {
return isImmTy(ImmTyInterpSlot); }
324 bool isInterpAttr()
const {
return isImmTy(ImmTyInterpAttr); }
325 bool isAttrChan()
const {
return isImmTy(ImmTyAttrChan); }
326 bool isOpSel()
const {
return isImmTy(ImmTyOpSel); }
327 bool isOpSelHi()
const {
return isImmTy(ImmTyOpSelHi); }
328 bool isNegLo()
const {
return isImmTy(ImmTyNegLo); }
329 bool isNegHi()
const {
return isImmTy(ImmTyNegHi); }
330 bool isHigh()
const {
return isImmTy(ImmTyHigh); }
333 return isClampSI() || isOModSI();
336 bool isRegOrImm()
const {
337 return isReg() || isImm();
340 bool isRegClass(
unsigned RCID)
const;
342 bool isRegOrInlineNoMods(
unsigned RCID,
MVT type)
const {
343 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
346 bool isSCSrcB16()
const {
347 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID,
MVT::i16);
350 bool isSCSrcV2B16()
const {
354 bool isSCSrcB32()
const {
355 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID,
MVT::i32);
358 bool isSCSrcB64()
const {
359 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID,
MVT::i64);
362 bool isSCSrcF16()
const {
363 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID,
MVT::f16);
366 bool isSCSrcV2F16()
const {
370 bool isSCSrcF32()
const {
371 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID,
MVT::f32);
374 bool isSCSrcF64()
const {
375 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID,
MVT::f64);
378 bool isSSrcB32()
const {
379 return isSCSrcB32() || isLiteralImm(
MVT::i32) || isExpr();
382 bool isSSrcB16()
const {
383 return isSCSrcB16() || isLiteralImm(
MVT::i16);
386 bool isSSrcV2B16()
const {
391 bool isSSrcB64()
const {
394 return isSCSrcB64() || isLiteralImm(
MVT::i64);
397 bool isSSrcF32()
const {
398 return isSCSrcB32() || isLiteralImm(
MVT::f32) || isExpr();
401 bool isSSrcF64()
const {
402 return isSCSrcB64() || isLiteralImm(
MVT::f64);
405 bool isSSrcF16()
const {
406 return isSCSrcB16() || isLiteralImm(
MVT::f16);
409 bool isSSrcV2F16()
const {
414 bool isVCSrcB32()
const {
415 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID,
MVT::i32);
418 bool isVCSrcB64()
const {
419 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID,
MVT::i64);
422 bool isVCSrcB16()
const {
423 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID,
MVT::i16);
426 bool isVCSrcV2B16()
const {
430 bool isVCSrcF32()
const {
431 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID,
MVT::f32);
434 bool isVCSrcF64()
const {
435 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID,
MVT::f64);
438 bool isVCSrcF16()
const {
439 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID,
MVT::f16);
442 bool isVCSrcV2F16()
const {
446 bool isVSrcB32()
const {
447 return isVCSrcF32() || isLiteralImm(
MVT::i32) || isExpr();
450 bool isVSrcB64()
const {
451 return isVCSrcF64() || isLiteralImm(
MVT::i64);
454 bool isVSrcB16()
const {
455 return isVCSrcF16() || isLiteralImm(
MVT::i16);
458 bool isVSrcV2B16()
const {
463 bool isVSrcF32()
const {
464 return isVCSrcF32() || isLiteralImm(
MVT::f32) || isExpr();
467 bool isVSrcF64()
const {
468 return isVCSrcF64() || isLiteralImm(
MVT::f64);
471 bool isVSrcF16()
const {
472 return isVCSrcF16() || isLiteralImm(
MVT::f16);
475 bool isVSrcV2F16()
const {
480 bool isKImmFP32()
const {
484 bool isKImmFP16()
const {
488 bool isMem()
const override {
492 bool isExpr()
const {
493 return Kind == Expression;
496 bool isSoppBrTarget()
const {
497 return isExpr() || isImm();
500 bool isSWaitCnt()
const;
501 bool isHwreg()
const;
502 bool isSendMsg()
const;
503 bool isSwizzle()
const;
504 bool isSMRDOffset8()
const;
505 bool isSMRDOffset20()
const;
506 bool isSMRDLiteralOffset()
const;
507 bool isDPPCtrl()
const;
508 bool isGPRIdxMode()
const;
509 bool isS16Imm()
const;
510 bool isU16Imm()
const;
521 if (Kind == Expression)
522 return getExpressionAsToken();
527 int64_t getImm()
const {
532 ImmTy getImmTy()
const {
537 unsigned getReg()
const override {
541 SMLoc getStartLoc()
const override {
545 SMLoc getEndLoc()
const override {
550 return SMRange(StartLoc, EndLoc);
553 Modifiers getModifiers()
const {
554 assert(isRegKind() || isImmTy(ImmTyNone));
555 return isRegKind() ?
Reg.Mods : Imm.Mods;
558 void setModifiers(Modifiers Mods) {
559 assert(isRegKind() || isImmTy(ImmTyNone));
566 bool hasModifiers()
const {
567 return getModifiers().hasModifiers();
570 bool hasFPModifiers()
const {
571 return getModifiers().hasFPModifiers();
574 bool hasIntModifiers()
const {
575 return getModifiers().hasIntModifiers();
578 uint64_t applyInputFPModifiers(uint64_t Val,
unsigned Size)
const;
580 void addImmOperands(
MCInst &Inst,
unsigned N,
bool ApplyModifiers =
true)
const;
582 void addLiteralImmOperand(
MCInst &Inst, int64_t Val,
bool ApplyModifiers)
const;
584 template <
unsigned Bitw
idth>
585 void addKImmFPOperands(
MCInst &Inst,
unsigned N)
const;
587 void addKImmFP16Operands(
MCInst &Inst,
unsigned N)
const {
588 addKImmFPOperands<16>(Inst,
N);
591 void addKImmFP32Operands(
MCInst &Inst,
unsigned N)
const {
592 addKImmFPOperands<32>(Inst,
N);
595 void addRegOperands(
MCInst &Inst,
unsigned N)
const;
597 void addRegOrImmOperands(
MCInst &Inst,
unsigned N)
const {
599 addRegOperands(Inst, N);
603 addImmOperands(Inst, N);
606 void addRegOrImmWithInputModsOperands(
MCInst &Inst,
unsigned N)
const {
607 Modifiers Mods = getModifiers();
610 addRegOperands(Inst, N);
612 addImmOperands(Inst, N,
false);
616 void addRegOrImmWithFPInputModsOperands(
MCInst &Inst,
unsigned N)
const {
617 assert(!hasIntModifiers());
618 addRegOrImmWithInputModsOperands(Inst, N);
621 void addRegOrImmWithIntInputModsOperands(
MCInst &Inst,
unsigned N)
const {
622 assert(!hasFPModifiers());
623 addRegOrImmWithInputModsOperands(Inst, N);
626 void addRegWithInputModsOperands(
MCInst &Inst,
unsigned N)
const {
627 Modifiers Mods = getModifiers();
630 addRegOperands(Inst, N);
633 void addRegWithFPInputModsOperands(
MCInst &Inst,
unsigned N)
const {
634 assert(!hasIntModifiers());
635 addRegWithInputModsOperands(Inst, N);
638 void addRegWithIntInputModsOperands(
MCInst &Inst,
unsigned N)
const {
639 assert(!hasFPModifiers());
640 addRegWithInputModsOperands(Inst, N);
643 void addSoppBrTargetOperands(
MCInst &Inst,
unsigned N)
const {
645 addImmOperands(Inst, N);
654 case ImmTyNone: OS <<
"None";
break;
655 case ImmTyGDS: OS <<
"GDS";
break;
656 case ImmTyLDS: OS <<
"LDS";
break;
657 case ImmTyOffen: OS <<
"Offen";
break;
658 case ImmTyIdxen: OS <<
"Idxen";
break;
659 case ImmTyAddr64: OS <<
"Addr64";
break;
660 case ImmTyOffset: OS <<
"Offset";
break;
661 case ImmTyInstOffset: OS <<
"InstOffset";
break;
662 case ImmTyOffset0: OS <<
"Offset0";
break;
663 case ImmTyOffset1: OS <<
"Offset1";
break;
664 case ImmTyGLC: OS <<
"GLC";
break;
665 case ImmTySLC: OS <<
"SLC";
break;
666 case ImmTyTFE: OS <<
"TFE";
break;
667 case ImmTyD16: OS <<
"D16";
break;
668 case ImmTyFORMAT: OS <<
"FORMAT";
break;
669 case ImmTyClampSI: OS <<
"ClampSI";
break;
670 case ImmTyOModSI: OS <<
"OModSI";
break;
671 case ImmTyDppCtrl: OS <<
"DppCtrl";
break;
672 case ImmTyDppRowMask: OS <<
"DppRowMask";
break;
673 case ImmTyDppBankMask: OS <<
"DppBankMask";
break;
674 case ImmTyDppBoundCtrl: OS <<
"DppBoundCtrl";
break;
675 case ImmTySdwaDstSel: OS <<
"SdwaDstSel";
break;
676 case ImmTySdwaSrc0Sel: OS <<
"SdwaSrc0Sel";
break;
677 case ImmTySdwaSrc1Sel: OS <<
"SdwaSrc1Sel";
break;
678 case ImmTySdwaDstUnused: OS <<
"SdwaDstUnused";
break;
679 case ImmTyDMask: OS <<
"DMask";
break;
680 case ImmTyUNorm: OS <<
"UNorm";
break;
681 case ImmTyDA: OS <<
"DA";
break;
682 case ImmTyR128A16: OS <<
"R128A16";
break;
683 case ImmTyLWE: OS <<
"LWE";
break;
684 case ImmTyOff: OS <<
"Off";
break;
685 case ImmTyExpTgt: OS <<
"ExpTgt";
break;
686 case ImmTyExpCompr: OS <<
"ExpCompr";
break;
687 case ImmTyExpVM: OS <<
"ExpVM";
break;
688 case ImmTyHwreg: OS <<
"Hwreg";
break;
689 case ImmTySendMsg: OS <<
"SendMsg";
break;
690 case ImmTyInterpSlot: OS <<
"InterpSlot";
break;
691 case ImmTyInterpAttr: OS <<
"InterpAttr";
break;
692 case ImmTyAttrChan: OS <<
"AttrChan";
break;
693 case ImmTyOpSel: OS <<
"OpSel";
break;
694 case ImmTyOpSelHi: OS <<
"OpSelHi";
break;
695 case ImmTyNegLo: OS <<
"NegLo";
break;
696 case ImmTyNegHi: OS <<
"NegHi";
break;
697 case ImmTySwizzle: OS <<
"Swizzle";
break;
698 case ImmTyHigh: OS <<
"High";
break;
705 OS <<
"<register " <<
getReg() <<
" mods: " <<
Reg.Mods <<
'>';
708 OS <<
'<' << getImm();
709 if (getImmTy() != ImmTyNone) {
710 OS <<
" type: "; printImmTy(OS, getImmTy());
712 OS <<
" mods: " << Imm.Mods <<
'>';
718 OS <<
"<expr " << *Expr << '>
'; 723 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser, 724 int64_t Val, SMLoc Loc, 725 ImmTy Type = ImmTyNone, 726 bool IsFPImm = false) { 727 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser); 729 Op->Imm.IsFPImm = IsFPImm; 731 Op->Imm.Mods = Modifiers(); 737 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser, 738 StringRef Str, SMLoc Loc, 739 bool HasExplicitEncodingSize = true) { 740 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser); 741 Res->Tok.Data = Str.data(); 742 Res->Tok.Length = Str.size(); 748 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser, 749 unsigned RegNo, SMLoc S, 752 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser); 753 Op->Reg.RegNo = RegNo; 754 Op->Reg.Mods = Modifiers(); 755 Op->Reg.IsForcedVOP3 = ForceVOP3; 761 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser, 762 const class MCExpr *Expr, SMLoc S) { 763 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser); 771 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { 772 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; 776 //===----------------------------------------------------------------------===// 778 //===----------------------------------------------------------------------===// 780 // Holds info related to the current kernel, e.g. count of SGPRs used. 781 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next 782 // .amdgpu_hsa_kernel or at EOF. 783 class KernelScopeInfo { 784 int SgprIndexUnusedMin = -1; 785 int VgprIndexUnusedMin = -1; 786 MCContext *Ctx = nullptr; 788 void usesSgprAt(int i) { 789 if (i >= SgprIndexUnusedMin) { 790 SgprIndexUnusedMin = ++i; 792 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count")); 793 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx)); 798 void usesVgprAt(int i) { 799 if (i >= VgprIndexUnusedMin) { 800 VgprIndexUnusedMin = ++i; 802 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 803 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx)); 809 KernelScopeInfo() = default; 811 void initialize(MCContext &Context) { 813 usesSgprAt(SgprIndexUnusedMin = -1); 814 usesVgprAt(VgprIndexUnusedMin = -1); 817 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) { 819 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break; 820 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break; 826 class AMDGPUAsmParser : public MCTargetAsmParser { 829 // Number of extra operands parsed after the first optional operand. 830 // This may be necessary to skip hardcoded mandatory operands. 831 static const unsigned MAX_OPR_LOOKAHEAD = 8; 833 unsigned ForcedEncodingSize = 0; 834 bool ForcedDPP = false; 835 bool ForcedSDWA = false; 836 KernelScopeInfo KernelScope; 841 #define GET_ASSEMBLER_HEADER
842 #include "AMDGPUGenAsmMatcher.inc"
847 bool ParseAsAbsoluteExpression(uint32_t &Ret);
848 bool OutOfRangeError(SMRange Range);
862 bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed,
863 bool FlatScrUsed, bool XNACKUsed,
864 unsigned NextFreeVGPR, SMRange VGPRRange,
865 unsigned NextFreeSGPR, SMRange SGPRRange,
866 unsigned &VGPRBlocks, unsigned &SGPRBlocks);
867 bool ParseDirectiveAMDGCNTarget();
868 bool ParseDirectiveAMDHSAKernel();
869 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
870 bool ParseDirectiveHSACodeObjectVersion();
871 bool ParseDirectiveHSACodeObjectISA();
872 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
873 bool ParseDirectiveAMDKernelCodeT();
874 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
875 bool ParseDirectiveAMDGPUHsaKernel();
877 bool ParseDirectiveISAVersion();
878 bool ParseDirectiveHSAMetadata();
879 bool ParseDirectivePALMetadata();
881 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
882 RegisterKind RegKind, unsigned Reg1,
884 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
885 unsigned& RegNum, unsigned& RegWidth,
886 unsigned *DwordRegIndex);
887 Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
888 void initializeGprCountSymbol(RegisterKind RegKind);
889 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
891 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
892 bool IsAtomic, bool IsAtomicReturn, bool IsLds = false);
893 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
894 bool IsGdsHardcoded);
897 enum AMDGPUMatchResultTy {
898 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
901 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
903 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
904 const MCInstrInfo &MII,
905 const MCTargetOptions &Options)
906 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
907 MCAsmParserExtension::Initialize(Parser);
909 if (getFeatureBits().none()) {
910 // Set default features.
911 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
914 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
917 // TODO: make those pre-defined variables read-only.
918 // Currently there is none suitable machinery in the core llvm-mc for this.
919 // MCSymbol::isRedefinable is intended for another purpose, and
920 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
921 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
922 MCContext &Ctx = getContext();
923 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
925 Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
926 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
929 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
930 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
931 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
932 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
933 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
934 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
936 if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
937 initializeGprCountSymbol(IS_VGPR);
938 initializeGprCountSymbol(IS_SGPR);
940 KernelScope.initialize(getContext());
944 bool hasXNACK() const {
945 return AMDGPU::hasXNACK(getSTI());
948 bool hasMIMG_R128() const {
949 return AMDGPU::hasMIMG_R128(getSTI());
952 bool hasPackedD16() const {
953 return AMDGPU::hasPackedD16(getSTI());
957 return AMDGPU::isSI(getSTI());
961 return AMDGPU::isCI(getSTI());
965 return AMDGPU::isVI(getSTI());
968 bool isGFX9() const {
969 return AMDGPU::isGFX9(getSTI());
972 bool hasInv2PiInlineImm() const {
973 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
976 bool hasFlatOffsets() const {
977 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
980 bool hasSGPR102_SGPR103() const {
984 bool hasIntClamp() const {
985 return getFeatureBits()[AMDGPU::FeatureIntClamp];
988 AMDGPUTargetStreamer &getTargetStreamer() {
989 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
990 return static_cast<AMDGPUTargetStreamer &>(TS);
993 const MCRegisterInfo *getMRI() const {
994 // We need this const_cast because for some reason getContext() is not const
996 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
999 const MCInstrInfo *getMII() const {
1003 const FeatureBitset &getFeatureBits() const {
1004 return getSTI().getFeatureBits();
1007 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1008 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1009 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
1011 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1012 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1013 bool isForcedDPP() const { return ForcedDPP; }
1014 bool isForcedSDWA() const { return ForcedSDWA; }
1015 ArrayRef<unsigned> getMatchedVariants() const;
1017 std::unique_ptr<AMDGPUOperand> parseRegister();
1018 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
1019 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1020 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1021 unsigned Kind) override;
1022 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1023 OperandVector &Operands, MCStreamer &Out,
1024 uint64_t &ErrorInfo,
1025 bool MatchingInlineAsm) override;
1026 bool ParseDirective(AsmToken DirectiveID) override;
1027 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
1028 StringRef parseMnemonicSuffix(StringRef Name);
1029 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1030 SMLoc NameLoc, OperandVector &Operands) override;
1031 //bool ProcessInstruction(MCInst &Inst);
1033 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
1035 OperandMatchResultTy
1036 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1037 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1038 bool (*ConvertResult)(int64_t &) = nullptr);
1040 OperandMatchResultTy parseOperandArrayWithPrefix(
1042 OperandVector &Operands,
1043 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1044 bool (*ConvertResult)(int64_t&) = nullptr);
1046 OperandMatchResultTy
1047 parseNamedBit(const char *Name, OperandVector &Operands,
1048 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
1049 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
1052 bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
1053 OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
1054 OperandMatchResultTy parseReg(OperandVector &Operands);
1055 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
1056 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1057 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1058 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1059 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
1060 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
1061 OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands);
1063 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
1064 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1065 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
1066 void cvtExp(MCInst &Inst, const OperandVector &Operands);
1068 bool parseCnt(int64_t &IntVal);
1069 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
1070 OperandMatchResultTy parseHwreg(OperandVector &Operands);
1073 struct OperandInfoTy {
1075 bool IsSymbolic = false;
1077 OperandInfoTy(int64_t Id_) : Id(Id_) {}
1080 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
1081 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1084 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1086 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
1087 bool validateConstantBusLimitations(const MCInst &Inst);
1088 bool validateEarlyClobberLimitations(const MCInst &Inst);
1089 bool validateIntClampSupported(const MCInst &Inst);
1090 bool validateMIMGAtomicDMask(const MCInst &Inst);
1091 bool validateMIMGGatherDMask(const MCInst &Inst);
1092 bool validateMIMGDataSize(const MCInst &Inst);
1093 bool validateMIMGD16(const MCInst &Inst);
1094 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1095 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1096 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1098 bool trySkipId(const StringRef Id);
1099 bool trySkipToken(const AsmToken::TokenKind Kind);
1100 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1101 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1102 bool parseExpr(int64_t &Imm);
1105 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1106 OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
1108 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1109 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1110 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1111 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1112 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1114 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1115 const unsigned MinVal,
1116 const unsigned MaxVal,
1117 const StringRef ErrMsg);
1118 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1119 bool parseSwizzleOffset(int64_t &Imm);
1120 bool parseSwizzleMacro(int64_t &Imm);
1121 bool parseSwizzleQuadPerm(int64_t &Imm);
1122 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1123 bool parseSwizzleBroadcast(int64_t &Imm);
1124 bool parseSwizzleSwap(int64_t &Imm);
1125 bool parseSwizzleReverse(int64_t &Imm);
1127 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1128 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1129 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1130 void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); }
1131 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1133 AMDGPUOperand::Ptr defaultGLC() const;
1134 AMDGPUOperand::Ptr defaultSLC() const;
1136 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1137 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1138 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1139 AMDGPUOperand::Ptr defaultOffsetU12() const;
1140 AMDGPUOperand::Ptr defaultOffsetS13() const;
1142 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1144 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1145 OptionalImmIndexMap &OptionalIdx);
1146 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1147 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1148 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1150 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1152 void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1153 bool IsAtomic = false);
1154 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1156 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1157 AMDGPUOperand::Ptr defaultRowMask() const;
1158 AMDGPUOperand::Ptr defaultBankMask() const;
1159 AMDGPUOperand::Ptr defaultBoundCtrl() const;
1160 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1162 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1163 AMDGPUOperand::ImmTy Type);
1164 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1165 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1166 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1167 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1168 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1169 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1170 uint64_t BasicInstType, bool skipVcc = false);
1173 struct OptionalOperand {
1175 AMDGPUOperand::ImmTy Type;
1177 bool (*ConvertResult)(int64_t&);
1180 } // end anonymous namespace
1182 // May be called with integer type with equivalent bitwidth.
1183 static const fltSemantics *getFltSemantics(unsigned Size) {
1186 return &APFloat::IEEEsingle();
1188 return &APFloat::IEEEdouble();
1190 return &APFloat::IEEEhalf();
1192 llvm_unreachable("unsupported fp type");
1196 static const fltSemantics *getFltSemantics(MVT VT) {
1197 return getFltSemantics(VT.getSizeInBits() / 8);
1200 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1201 switch (OperandType) {
1202 case AMDGPU::OPERAND_REG_IMM_INT32:
1203 case AMDGPU::OPERAND_REG_IMM_FP32:
1204 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1205 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1206 return &APFloat::IEEEsingle();
1207 case AMDGPU::OPERAND_REG_IMM_INT64:
1208 case AMDGPU::OPERAND_REG_IMM_FP64:
1209 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1210 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1211 return &APFloat::IEEEdouble();
1212 case AMDGPU::OPERAND_REG_IMM_INT16:
1213 case AMDGPU::OPERAND_REG_IMM_FP16:
1214 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1215 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1216 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1217 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1218 return &APFloat::IEEEhalf();
1220 llvm_unreachable("unsupported fp type");
1224 //===----------------------------------------------------------------------===//
1226 //===----------------------------------------------------------------------===//
1228 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1231 // Convert literal to single precision
1232 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1233 APFloat::rmNearestTiesToEven,
1235 // We allow precision lost but not overflow or underflow
1236 if (Status != APFloat::opOK &&
1238 ((Status & APFloat::opOverflow) != 0 ||
1239 (Status & APFloat::opUnderflow) != 0)) {
1246 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1247 if (!isImmTy(ImmTyNone)) {
1248 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1251 // TODO: We should avoid using host float here. It would be better to
1252 // check the float bit values which is what a few other places do.
1253 // We've had bot failures before due to weird NaN support on mips hosts.
1260 AsmParser->hasInv2PiInlineImm());
1269 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1270 AsmParser->hasInv2PiInlineImm());
1275 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1276 AsmParser->hasInv2PiInlineImm());
1282 AsmParser->hasInv2PiInlineImm());
1287 static_cast<int16_t>(
Literal.getLoBits(16).getSExtValue()),
1288 AsmParser->hasInv2PiInlineImm());
1292 static_cast<int32_t>(
Literal.getLoBits(32).getZExtValue()),
1293 AsmParser->hasInv2PiInlineImm());
1296 bool AMDGPUOperand::isLiteralImm(
MVT type)
const {
1298 if (!isImmTy(ImmTyNone)) {
1305 if (type ==
MVT::f64 && hasFPModifiers()) {
1337 bool AMDGPUOperand::isRegClass(
unsigned RCID)
const {
1338 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(
getReg());
1341 bool AMDGPUOperand::isSDWAOperand(
MVT type)
const {
1342 if (AsmParser->isVI())
1344 else if (AsmParser->isGFX9())
1345 return isRegKind() || isInlinableImm(type);
1350 bool AMDGPUOperand::isSDWAFP16Operand()
const {
1354 bool AMDGPUOperand::isSDWAFP32Operand()
const {
1358 bool AMDGPUOperand::isSDWAInt16Operand()
const {
1362 bool AMDGPUOperand::isSDWAInt32Operand()
const {
1366 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val,
unsigned Size)
const 1368 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1369 assert(Size == 2 || Size == 4 || Size == 8);
1371 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1383 void AMDGPUOperand::addImmOperands(
MCInst &Inst,
unsigned N,
bool ApplyModifiers)
const {
1386 addLiteralImmOperand(Inst, Imm.Val,
1388 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1390 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1395 void AMDGPUOperand::addLiteralImmOperand(
MCInst &Inst, int64_t Val,
bool ApplyModifiers)
const {
1396 const auto& InstDesc = AsmParser->getMII()->get(Inst.
getOpcode());
1401 if (ApplyModifiers) {
1403 const unsigned Size = Imm.IsFPImm ?
sizeof(double) :
getOperandSize(InstDesc, OpNum);
1404 Val = applyInputFPModifiers(Val, Size);
1408 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1417 AsmParser->hasInv2PiInlineImm())) {
1425 if (
Literal.getLoBits(32) != 0) {
1426 const_cast<AMDGPUAsmParser *
>(AsmParser)->
Warning(Inst.
getLoc(),
1427 "Can't encode literal as exact 64-bit floating-point operand. " 1428 "Low 32-bits will be set to zero");
1458 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1461 ImmVal |= (ImmVal << 16);
1484 AsmParser->hasInv2PiInlineImm())) {
1510 AsmParser->hasInv2PiInlineImm())) {
1520 auto LiteralVal =
static_cast<uint16_t
>(
Literal.getLoBits(16).getZExtValue());
1522 AsmParser->hasInv2PiInlineImm()));
1525 static_cast<uint32_t>(LiteralVal);
1534 template <
unsigned Bitw
idth>
1535 void AMDGPUOperand::addKImmFPOperands(
MCInst &Inst,
unsigned N)
const {
1551 void AMDGPUOperand::addRegOperands(
MCInst &Inst,
unsigned N)
const {
1560 if (Is == IS_VGPR) {
1563 case 1:
return AMDGPU::VGPR_32RegClassID;
1564 case 2:
return AMDGPU::VReg_64RegClassID;
1565 case 3:
return AMDGPU::VReg_96RegClassID;
1566 case 4:
return AMDGPU::VReg_128RegClassID;
1567 case 8:
return AMDGPU::VReg_256RegClassID;
1568 case 16:
return AMDGPU::VReg_512RegClassID;
1570 }
else if (Is == IS_TTMP) {
1573 case 1:
return AMDGPU::TTMP_32RegClassID;
1574 case 2:
return AMDGPU::TTMP_64RegClassID;
1575 case 4:
return AMDGPU::TTMP_128RegClassID;
1576 case 8:
return AMDGPU::TTMP_256RegClassID;
1577 case 16:
return AMDGPU::TTMP_512RegClassID;
1579 }
else if (Is == IS_SGPR) {
1582 case 1:
return AMDGPU::SGPR_32RegClassID;
1583 case 2:
return AMDGPU::SGPR_64RegClassID;
1584 case 4:
return AMDGPU::SGPR_128RegClassID;
1585 case 8:
return AMDGPU::SGPR_256RegClassID;
1586 case 16:
return AMDGPU::SGPR_512RegClassID;
1594 .Case(
"exec", AMDGPU::EXEC)
1595 .
Case(
"vcc", AMDGPU::VCC)
1596 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
1597 .
Case(
"xnack_mask", AMDGPU::XNACK_MASK)
1598 .
Case(
"m0", AMDGPU::M0)
1599 .
Case(
"scc", AMDGPU::SCC)
1600 .
Case(
"tba", AMDGPU::TBA)
1601 .
Case(
"tma", AMDGPU::TMA)
1602 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1603 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1604 .
Case(
"xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
1605 .
Case(
"xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
1606 .
Case(
"vcc_lo", AMDGPU::VCC_LO)
1607 .
Case(
"vcc_hi", AMDGPU::VCC_HI)
1608 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
1609 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
1610 .
Case(
"tma_lo", AMDGPU::TMA_LO)
1611 .
Case(
"tma_hi", AMDGPU::TMA_HI)
1612 .
Case(
"tba_lo", AMDGPU::TBA_LO)
1613 .
Case(
"tba_hi", AMDGPU::TBA_HI)
1617 bool AMDGPUAsmParser::ParseRegister(
unsigned &RegNo,
SMLoc &StartLoc,
1619 auto R = parseRegister();
1620 if (!R)
return true;
1622 RegNo = R->getReg();
1623 StartLoc = R->getStartLoc();
1624 EndLoc = R->getEndLoc();
1628 bool AMDGPUAsmParser::AddNextRegisterToList(
unsigned &
Reg,
unsigned &RegWidth,
1633 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1638 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1639 Reg = AMDGPU::FLAT_SCR;
1643 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
1644 Reg = AMDGPU::XNACK_MASK;
1648 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1653 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1658 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1667 if (Reg1 != Reg + RegWidth) {
1677 bool AMDGPUAsmParser::ParseAMDGPURegister(
RegisterKind &RegKind,
unsigned &Reg,
1678 unsigned &RegNum,
unsigned &RegWidth,
1679 unsigned *DwordRegIndex) {
1680 if (DwordRegIndex) { *DwordRegIndex = 0; }
1683 StringRef RegName = Parser.getTok().getString();
1686 RegKind = IS_SPECIAL;
1688 unsigned RegNumIndex = 0;
1689 if (RegName[0] ==
'v') {
1692 }
else if (RegName[0] ==
's') {
1696 RegNumIndex = strlen(
"ttmp");
1701 if (RegName.
size() > RegNumIndex) {
1710 int64_t RegLo, RegHi;
1715 if (getParser().parseAbsoluteExpression(RegLo))
1726 if (getParser().parseAbsoluteExpression(RegHi))
1734 RegWidth = (RegHi - RegLo) + 1;
1740 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth,
nullptr))
1745 unsigned Reg1, RegNum1, RegWidth1;
1752 }
else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1,
nullptr)) {
1753 if (RegWidth1 != 1) {
1756 if (RegKind1 != RegKind) {
1759 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1779 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1781 Size = std::min(RegWidth, 4u);
1783 if (RegNum % Size != 0)
1785 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1786 RegNum = RegNum /
Size;
1801 if (!subtargetHasRegister(*TRI, Reg))
1807 AMDGPUAsmParser::getGprCountSymbolName(
RegisterKind RegKind) {
1810 return StringRef(
".amdgcn.next_free_vgpr");
1812 return StringRef(
".amdgcn.next_free_sgpr");
1818 void AMDGPUAsmParser::initializeGprCountSymbol(
RegisterKind RegKind) {
1819 auto SymbolName = getGprCountSymbolName(RegKind);
1825 bool AMDGPUAsmParser::updateGprCountSymbols(
RegisterKind RegKind,
1826 unsigned DwordRegIndex,
1827 unsigned RegWidth) {
1832 auto SymbolName = getGprCountSymbolName(RegKind);
1837 int64_t NewMax = DwordRegIndex + RegWidth - 1;
1841 return !
Error(getParser().getTok().getLoc(),
1842 ".amdgcn.next_free_{v,s}gpr symbols must be variable");
1845 getParser().getTok().getLoc(),
1846 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions");
1848 if (OldCount <= NewMax)
1854 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1855 const auto &Tok = Parser.getTok();
1856 SMLoc StartLoc = Tok.getLoc();
1857 SMLoc EndLoc = Tok.getEndLoc();
1859 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1861 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1865 if (!updateGprCountSymbols(RegKind, DwordRegIndex, RegWidth))
1868 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1869 return AMDGPUOperand::CreateReg(
this, Reg, StartLoc, EndLoc,
false);
1873 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val,
bool AbsMod) {
1886 if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1890 return !Expr->evaluateAsAbsolute(Val);
1893 return getParser().parseAbsoluteExpression(Val);
1897 AMDGPUAsmParser::parseImm(
OperandVector &Operands,
bool AbsMod) {
1901 const AsmToken NextToken = getLexer().peekTok();
1910 SMLoc S = Parser.getTok().getLoc();
1911 switch(getLexer().getKind()) {
1914 if (parseAbsoluteExpr(IntVal, AbsMod))
1918 Operands.
push_back(AMDGPUOperand::CreateImm(
this, IntVal, S));
1923 if (parseAbsoluteExpr(IntVal, AbsMod))
1931 AMDGPUOperand::ImmTyNone,
true));
1941 if (
auto R = parseRegister()) {
1943 R->Reg.IsForcedVOP3 = isForcedVOP3();
1951 AMDGPUAsmParser::parseRegOrImm(
OperandVector &Operands,
bool AbsMod) {
1952 auto res = parseImm(Operands, AbsMod);
1957 return parseReg(Operands);
1961 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(
OperandVector &Operands,
1963 bool Negate =
false, Negate2 =
false, Abs =
false, Abs2 =
false;
1966 const AsmToken NextToken = getLexer().peekTok();
1970 Error(Parser.getTok().getLoc(),
"invalid syntax, expected 'neg' modifier");
1989 Parser.getTok().getString() ==
"neg") {
1991 Error(Parser.getTok().getLoc(),
"expected register or immediate");
1997 Error(Parser.getTok().getLoc(),
"expected left paren after neg");
2004 Parser.getTok().getString() ==
"abs") {
2008 Error(Parser.getTok().getLoc(),
"expected left paren after abs");
2016 Error(Parser.getTok().getLoc(),
"expected register or immediate");
2025 Res = parseRegOrImm(Operands, Abs);
2027 Res = parseReg(Operands);
2033 AMDGPUOperand::Modifiers Mods;
2036 Error(Parser.getTok().getLoc(),
"expected vertical bar");
2044 Error(Parser.getTok().getLoc(),
"expected closing parentheses");
2053 }
else if (Negate2) {
2055 Error(Parser.getTok().getLoc(),
"expected closing parentheses");
2062 if (Mods.hasFPModifiers()) {
2063 AMDGPUOperand &
Op =
static_cast<AMDGPUOperand &
>(*Operands.
back());
2064 Op.setModifiers(Mods);
2070 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(
OperandVector &Operands,
2075 Parser.getTok().getString() ==
"sext") {
2079 Error(Parser.getTok().getLoc(),
"expected left paren after sext");
2087 Res = parseRegOrImm(Operands);
2089 Res = parseReg(Operands);
2095 AMDGPUOperand::Modifiers Mods;
2098 Error(Parser.getTok().getLoc(),
"expected closing parentheses");
2105 if (Mods.hasIntModifiers()) {
2106 AMDGPUOperand &
Op =
static_cast<AMDGPUOperand &
>(*Operands.
back());
2107 Op.setModifiers(Mods);
2114 AMDGPUAsmParser::parseRegWithFPInputMods(
OperandVector &Operands) {
2115 return parseRegOrImmWithFPInputMods(Operands,
false);
2119 AMDGPUAsmParser::parseRegWithIntInputMods(
OperandVector &Operands) {
2120 return parseRegOrImmWithIntInputMods(Operands,
false);
2124 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
2130 const AsmToken &Tok = Parser.getTok();
2133 AMDGPUOperand::ImmTyOff,
false));
2141 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
2142 uint64_t TSFlags = MII.get(Inst.
getOpcode()).TSFlags;
2148 return Match_InvalidOperand;
2150 if ((TSFlags & SIInstrFlags::VOP3) &&
2152 getForcedEncodingSize() != 64)
2153 return Match_PreferE32;
2155 if (Inst.
getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2156 Inst.
getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
2162 return Match_InvalidOperand;
2171 if (Op.getImm() != 0)
2172 return Match_InvalidOperand;
2175 return Match_Success;
2180 if (getForcedEncodingSize() == 32) {
2185 if (isForcedVOP3()) {
2190 if (isForcedSDWA()) {
2196 if (isForcedDPP()) {
2201 static const unsigned Variants[] = {
2209 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(
const MCInst &Inst)
const {
2212 for (
unsigned i = 0; i < Num; ++i) {
2215 case AMDGPU::FLAT_SCR:
2223 return AMDGPU::NoRegister;
2230 bool AMDGPUAsmParser::isInlineConstant(
const MCInst &Inst,
2231 unsigned OpIdx)
const {
2240 int64_t Val = MO.
getImm();
2262 bool AMDGPUAsmParser::usesConstantBus(
const MCInst &Inst,
unsigned OpIdx) {
2265 return !isInlineConstant(Inst, OpIdx);
2267 return !MO.
isReg() ||
2271 bool AMDGPUAsmParser::validateConstantBusLimitations(
const MCInst &Inst) {
2272 const unsigned Opcode = Inst.
getOpcode();
2274 unsigned ConstantBusUseCount = 0;
2283 ++ConstantBusUseCount;
2286 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2287 if (SGPRUsed != AMDGPU::NoRegister) {
2288 ++ConstantBusUseCount;
2295 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2297 for (
int OpIdx : OpIndices) {
2298 if (OpIdx == -1)
break;
2301 if (usesConstantBus(Inst, OpIdx)) {
2310 if (Reg != SGPRUsed) {
2311 ++ConstantBusUseCount;
2315 ++ConstantBusUseCount;
2321 return ConstantBusUseCount <= 1;
2324 bool AMDGPUAsmParser::validateEarlyClobberLimitations(
const MCInst &Inst) {
2325 const unsigned Opcode = Inst.
getOpcode();
2345 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2347 for (
int SrcIdx : SrcIndices) {
2348 if (SrcIdx == -1)
break;
2361 bool AMDGPUAsmParser::validateIntClampSupported(
const MCInst &Inst) {
2375 bool AMDGPUAsmParser::validateMIMGDataSize(
const MCInst &Inst) {
2402 DataSize = (DataSize + 1) / 2;
2405 return (VDataSize / 4) == DataSize + TFESize;
2408 bool AMDGPUAsmParser::validateMIMGAtomicDMask(
const MCInst &Inst) {
2425 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
2428 bool AMDGPUAsmParser::validateMIMGGatherDMask(
const MCInst &Inst) {
2444 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
2447 bool AMDGPUAsmParser::validateMIMGD16(
const MCInst &Inst) {
2464 bool AMDGPUAsmParser::validateInstruction(
const MCInst &Inst,
2465 const SMLoc &IDLoc) {
2466 if (!validateConstantBusLimitations(Inst)) {
2468 "invalid operand (violates constant bus restrictions)");
2471 if (!validateEarlyClobberLimitations(Inst)) {
2473 "destination must be different than all sources");
2476 if (!validateIntClampSupported(Inst)) {
2478 "integer clamping is not supported on this GPU");
2482 if (!validateMIMGD16(Inst)) {
2484 "d16 modifier is not supported on this GPU");
2487 if (!validateMIMGDataSize(Inst)) {
2489 "image data size does not match dmask and tfe");
2492 if (!validateMIMGAtomicDMask(Inst)) {
2494 "invalid atomic image dmask");
2497 if (!validateMIMGGatherDMask(Inst)) {
2499 "invalid image_gather dmask: only one bit must be set");
2507 unsigned VariantID = 0);
2509 bool AMDGPUAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
2513 bool MatchingInlineAsm) {
2515 unsigned Result = Match_Success;
2516 for (
auto Variant : getMatchedVariants()) {
2518 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2523 if ((R == Match_Success) ||
2524 (R == Match_PreferE32) ||
2525 (R == Match_MissingFeature && Result != Match_PreferE32) ||
2526 (R == Match_InvalidOperand && Result != Match_MissingFeature
2527 && Result != Match_PreferE32) ||
2528 (R == Match_MnemonicFail && Result != Match_InvalidOperand
2529 && Result != Match_MissingFeature
2530 && Result != Match_PreferE32)) {
2534 if (R == Match_Success)
2541 if (!validateInstruction(Inst, IDLoc)) {
2548 case Match_MissingFeature:
2549 return Error(IDLoc,
"instruction not supported on this GPU");
2551 case Match_MnemonicFail: {
2552 uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
2554 ((AMDGPUOperand &)*Operands[0]).
getToken(), FBS);
2555 return Error(IDLoc,
"invalid instruction" + Suggestion,
2556 ((AMDGPUOperand &)*Operands[0]).getLocRange());
2559 case Match_InvalidOperand: {
2560 SMLoc ErrorLoc = IDLoc;
2561 if (ErrorInfo != ~0ULL) {
2562 if (ErrorInfo >= Operands.
size()) {
2563 return Error(IDLoc,
"too few operands for instruction");
2565 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2566 if (ErrorLoc ==
SMLoc())
2569 return Error(ErrorLoc,
"invalid operand for instruction");
2572 case Match_PreferE32:
2573 return Error(IDLoc,
"internal error: instruction without _e64 suffix " 2574 "should be encoded as e32");
2579 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(
uint32_t &
Ret) {
2584 if (getParser().parseAbsoluteExpression(Tmp)) {
2591 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(
uint32_t &Major,
2593 if (ParseAsAbsoluteExpression(Major))
2594 return TokError(
"invalid major version");
2597 return TokError(
"minor version number required, comma expected");
2600 if (ParseAsAbsoluteExpression(Minor))
2601 return TokError(
"invalid minor version");
2606 bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
2608 return TokError(
"directive only supported for amdgcn architecture");
2612 SMLoc TargetStart = getTok().getLoc();
2613 if (getParser().parseEscapedString(Target))
2617 std::string ExpectedTarget;
2621 if (Target != ExpectedTargetOS.
str())
2622 return getParser().Error(TargetRange.
Start,
"target must match options",
2625 getTargetStreamer().EmitDirectiveAMDGCNTarget(Target);
2629 bool AMDGPUAsmParser::OutOfRangeError(
SMRange Range) {
2630 return getParser().Error(Range.
Start,
"value out of range", Range);
2633 bool AMDGPUAsmParser::calculateGPRBlocks(
2635 bool XNACKUsed,
unsigned NextFreeVGPR,
SMRange VGPRRange,
2636 unsigned NextFreeSGPR,
SMRange SGPRRange,
unsigned &VGPRBlocks,
2637 unsigned &SGPRBlocks) {
2646 if (Version.
Major >= 8 && !Features.test(FeatureSGPRInitBug) &&
2647 NumSGPRs > MaxAddressableNumSGPRs)
2648 return OutOfRangeError(SGPRRange);
2653 if ((Version.
Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
2654 NumSGPRs > MaxAddressableNumSGPRs)
2655 return OutOfRangeError(SGPRRange);
2657 if (Features.test(FeatureSGPRInitBug))
2666 bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
2668 return TokError(
"directive only supported for amdgcn architecture");
2671 return TokError(
"directive only supported for amdhsa OS");
2674 if (getParser().parseIdentifier(KernelName))
2684 uint64_t NextFreeVGPR = 0;
2686 uint64_t NextFreeSGPR = 0;
2687 unsigned UserSGPRCount = 0;
2688 bool ReserveVCC =
true;
2689 bool ReserveFlatScr =
true;
2697 return TokError(
"expected .amdhsa_ directive or .end_amdhsa_kernel");
2700 SMRange IDRange = getTok().getLocRange();
2703 if (ID ==
".end_amdhsa_kernel")
2706 if (Seen.
find(ID) != Seen.
end())
2707 return TokError(
".amdhsa_ directives cannot be repeated");
2710 SMLoc ValStart = getTok().getLoc();
2712 if (getParser().parseAbsoluteExpression(IVal))
2714 SMLoc ValEnd = getTok().getLoc();
2718 return OutOfRangeError(ValRange);
2720 uint64_t Val = IVal;
2722 #define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ 2723 if (!isUInt<ENTRY##_WIDTH>(VALUE)) \ 2724 return OutOfRangeError(RANGE); \ 2725 AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); 2727 if (ID ==
".amdhsa_group_segment_fixed_size") {
2729 return OutOfRangeError(ValRange);
2731 }
else if (ID ==
".amdhsa_private_segment_fixed_size") {
2733 return OutOfRangeError(ValRange);
2735 }
else if (ID ==
".amdhsa_user_sgpr_private_segment_buffer") {
2737 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
2740 }
else if (ID ==
".amdhsa_user_sgpr_dispatch_ptr") {
2742 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val,
2745 }
else if (ID ==
".amdhsa_user_sgpr_queue_ptr") {
2747 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val,
2750 }
else if (ID ==
".amdhsa_user_sgpr_kernarg_segment_ptr") {
2752 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
2755 }
else if (ID ==
".amdhsa_user_sgpr_dispatch_id") {
2757 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val,
2760 }
else if (ID ==
".amdhsa_user_sgpr_flat_scratch_init") {
2762 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val,
2765 }
else if (ID ==
".amdhsa_user_sgpr_private_segment_size") {
2767 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
2770 }
else if (ID ==
".amdhsa_system_sgpr_private_segment_wavefront_offset") {
2773 COMPUTE_PGM_RSRC2_ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, Val,
2775 }
else if (ID ==
".amdhsa_system_sgpr_workgroup_id_x") {
2777 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val,
2779 }
else if (ID ==
".amdhsa_system_sgpr_workgroup_id_y") {
2781 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val,
2783 }
else if (ID ==
".amdhsa_system_sgpr_workgroup_id_z") {
2785 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val,
2787 }
else if (ID ==
".amdhsa_system_sgpr_workgroup_info") {
2789 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val,
2791 }
else if (ID ==
".amdhsa_system_vgpr_workitem_id") {
2793 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val,
2795 }
else if (ID ==
".amdhsa_next_free_vgpr") {
2796 VGPRRange = ValRange;
2798 }
else if (ID ==
".amdhsa_next_free_sgpr") {
2799 SGPRRange = ValRange;
2801 }
else if (ID ==
".amdhsa_reserve_vcc") {
2802 if (!isUInt<1>(Val))
2803 return OutOfRangeError(ValRange);
2805 }
else if (ID ==
".amdhsa_reserve_flat_scratch") {
2806 if (IVersion.
Major < 7)
2807 return getParser().Error(IDRange.
Start,
"directive requires gfx7+",
2809 if (!isUInt<1>(Val))
2810 return OutOfRangeError(ValRange);
2811 ReserveFlatScr = Val;
2812 }
else if (ID ==
".amdhsa_reserve_xnack_mask") {
2813 if (IVersion.
Major < 8)
2814 return getParser().Error(IDRange.
Start,
"directive requires gfx8+",
2816 if (!isUInt<1>(Val))
2817 return OutOfRangeError(ValRange);
2819 }
else if (ID ==
".amdhsa_float_round_mode_32") {
2821 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange);
2822 }
else if (ID ==
".amdhsa_float_round_mode_16_64") {
2824 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange);
2825 }
else if (ID ==
".amdhsa_float_denorm_mode_32") {
2827 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange);
2828 }
else if (ID ==
".amdhsa_float_denorm_mode_16_64") {
2830 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val,
2832 }
else if (ID ==
".amdhsa_dx10_clamp") {
2834 COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange);
2835 }
else if (ID ==
".amdhsa_ieee_mode") {
2838 }
else if (ID ==
".amdhsa_fp16_overflow") {
2839 if (IVersion.
Major < 9)
2840 return getParser().Error(IDRange.
Start,
"directive requires gfx9+",
2844 }
else if (ID ==
".amdhsa_exception_fp_ieee_invalid_op") {
2847 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val,
2849 }
else if (ID ==
".amdhsa_exception_fp_denorm_src") {
2851 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
2853 }
else if (ID ==
".amdhsa_exception_fp_ieee_div_zero") {
2856 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val,
2858 }
else if (ID ==
".amdhsa_exception_fp_ieee_overflow") {
2860 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
2862 }
else if (ID ==
".amdhsa_exception_fp_ieee_underflow") {
2864 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
2866 }
else if (ID ==
".amdhsa_exception_fp_ieee_inexact") {
2868 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
2870 }
else if (ID ==
".amdhsa_exception_int_div_zero") {
2872 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
2875 return getParser().Error(IDRange.
Start,
2876 "unknown .amdhsa_kernel directive", IDRange);
2879 #undef PARSE_BITS_ENTRY 2882 if (Seen.
find(
".amdhsa_next_free_vgpr") == Seen.
end())
2883 return TokError(
".amdhsa_next_free_vgpr directive is required");
2885 if (Seen.
find(
".amdhsa_next_free_sgpr") == Seen.
end())
2886 return TokError(
".amdhsa_next_free_sgpr directive is required");
2888 unsigned VGPRBlocks;
2889 unsigned SGPRBlocks;
2890 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
2891 ReserveXNACK, NextFreeVGPR, VGPRRange, NextFreeSGPR,
2892 SGPRRange, VGPRBlocks, SGPRBlocks))
2895 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>(
2897 return OutOfRangeError(VGPRRange);
2899 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks);
2901 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>(
2903 return OutOfRangeError(SGPRRange);
2905 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
2908 if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount))
2909 return TokError(
"too many user SGPRs enabled");
2913 getTargetStreamer().EmitAmdhsaKernelDescriptor(
2914 getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC,
2915 ReserveFlatScr, ReserveXNACK);
2919 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2923 if (ParseDirectiveMajorMinor(Major, Minor))
2926 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2930 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2941 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2947 if (ParseDirectiveMajorMinor(Major, Minor))
2951 return TokError(
"stepping version number required, comma expected");
2954 if (ParseAsAbsoluteExpression(Stepping))
2955 return TokError(
"invalid stepping version");
2958 return TokError(
"vendor name required, comma expected");
2962 return TokError(
"invalid vendor name");
2964 VendorName = getLexer().getTok().getStringContents();
2968 return TokError(
"arch name required, comma expected");
2972 return TokError(
"invalid arch name");
2974 ArchName = getLexer().getTok().getStringContents();
2977 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2978 VendorName, ArchName);
2982 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(
StringRef ID,
2986 if (ID ==
"max_scratch_backing_memory_byte_size") {
2987 Parser.eatToEndOfStatement();
2994 return TokError(Err.
str());
3000 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
3011 return TokError(
"expected value identifier or .end_amd_kernel_code_t");
3013 StringRef ID = getLexer().getTok().getIdentifier();
3016 if (ID ==
".end_amd_kernel_code_t")
3019 if (ParseAMDKernelCodeTValue(ID, Header))
3023 getTargetStreamer().EmitAMDKernelCodeT(Header);
3028 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
3030 return TokError(
"expected symbol name");
3032 StringRef KernelName = Parser.getTok().getString();
3034 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
3038 KernelScope.initialize(getContext());
3042 bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
3044 return Error(getParser().getTok().getLoc(),
3045 ".amd_amdgpu_isa directive is not available on non-amdgcn " 3049 auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
3051 std::string ISAVersionStringFromSTI;
3055 if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.
str()) {
3056 return Error(getParser().getTok().getLoc(),
3057 ".amd_amdgpu_isa directive does not match triple and/or mcpu " 3058 "arguments specified through the command line");
3061 getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.
str());
3067 bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
3070 std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) =
3078 return Error(getParser().getTok().getLoc(),
3079 (
Twine(AssemblerDirectiveBegin) +
Twine(
" directive is " 3080 "not available on non-amdhsa OSes")).str());
3083 std::string HSAMetadataString;
3086 getLexer().setSkipSpace(
false);
3088 bool FoundEnd =
false;
3091 YamlStream << getLexer().getTok().getString();
3096 StringRef ID = getLexer().getTok().getIdentifier();
3097 if (ID == AssemblerDirectiveEnd) {
3104 YamlStream << Parser.parseStringToEndOfStatement()
3105 << getContext().getAsmInfo()->getSeparatorString();
3107 Parser.eatToEndOfStatement();
3110 getLexer().setSkipSpace(
true);
3113 return TokError(
Twine(
"expected directive ") +
3120 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
3121 return Error(getParser().getTok().getLoc(),
"invalid HSA metadata");
3123 if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString))
3124 return Error(getParser().getTok().getLoc(),
"invalid HSA metadata");
3130 bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
3132 return Error(getParser().getTok().getLoc(),
3134 "not available on non-amdpal OSes")).str());
3140 if (ParseAsAbsoluteExpression(Value)) {
3141 return TokError(
Twine(
"invalid value in ") +
3144 PALMetadata.push_back(Value);
3149 getTargetStreamer().EmitPALMetadata(PALMetadata);
3153 bool AMDGPUAsmParser::ParseDirective(
AsmToken DirectiveID) {
3157 if (IDVal ==
".amdgcn_target")
3158 return ParseDirectiveAMDGCNTarget();
3160 if (IDVal ==
".amdhsa_kernel")
3161 return ParseDirectiveAMDHSAKernel();
3165 return ParseDirectiveHSAMetadata();
3167 if (IDVal ==
".hsa_code_object_version")
3168 return ParseDirectiveHSACodeObjectVersion();
3170 if (IDVal ==
".hsa_code_object_isa")
3171 return ParseDirectiveHSACodeObjectISA();
3173 if (IDVal ==
".amd_kernel_code_t")
3174 return ParseDirectiveAMDKernelCodeT();
3176 if (IDVal ==
".amdgpu_hsa_kernel")
3177 return ParseDirectiveAMDGPUHsaKernel();
3179 if (IDVal ==
".amd_amdgpu_isa")
3180 return ParseDirectiveISAVersion();
3183 return ParseDirectiveHSAMetadata();
3187 return ParseDirectivePALMetadata();
3193 unsigned RegNo)
const {
3203 case AMDGPU::TBA_LO:
3204 case AMDGPU::TBA_HI:
3206 case AMDGPU::TMA_LO:
3207 case AMDGPU::TMA_HI:
3209 case AMDGPU::XNACK_MASK:
3210 case AMDGPU::XNACK_MASK_LO:
3211 case AMDGPU::XNACK_MASK_HI:
3223 case AMDGPU::FLAT_SCR:
3224 case AMDGPU::FLAT_SCR_LO:
3225 case AMDGPU::FLAT_SCR_HI:
3258 ResTy = parseRegOrImm(Operands);
3263 const auto &Tok = Parser.getTok();
3264 SMLoc S = Tok.getLoc();
3266 const MCExpr *Expr =
nullptr;
3267 if (!Parser.parseExpression(Expr)) {
3268 Operands.
push_back(AMDGPUOperand::CreateExpr(
this, Expr, S));
3274 Operands.
push_back(AMDGPUOperand::CreateToken(
this, Tok.getString(), S));
3284 setForcedEncodingSize(0);
3285 setForcedDPP(
false);
3286 setForcedSDWA(
false);
3289 setForcedEncodingSize(64);
3291 }
else if (Name.
endswith(
"_e32")) {
3292 setForcedEncodingSize(32);
3294 }
else if (Name.
endswith(
"_dpp")) {
3297 }
else if (Name.
endswith(
"_sdwa")) {
3298 setForcedSDWA(
true);
3308 Name = parseMnemonicSuffix(Name);
3309 Operands.
push_back(AMDGPUOperand::CreateToken(
this, Name, NameLoc));
3321 Error(getLexer().getLoc(),
"failed parsing operand.");
3327 Error(getLexer().getLoc(),
"not a valid operand.");
3343 AMDGPUAsmParser::parseIntWithPrefix(
const char *
Prefix, int64_t &Int) {
3344 switch(getLexer().getKind()) {
3347 StringRef Name = Parser.getTok().getString();
3348 if (!Name.
equals(Prefix)) {
3358 bool IsMinus =
false;
3367 if (getParser().parseAbsoluteExpression(Int))
3379 AMDGPUAsmParser::parseIntWithPrefix(
const char *Prefix,
OperandVector &Operands,
3380 AMDGPUOperand::ImmTy ImmTy,
3381 bool (*ConvertResult)(int64_t&)) {
3382 SMLoc S = Parser.getTok().getLoc();
3389 if (ConvertResult && !ConvertResult(Value)) {
3393 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Value, S, ImmTy));
3400 AMDGPUOperand::ImmTy ImmTy,
3401 bool (*ConvertResult)(int64_t&)) {
3402 StringRef Name = Parser.getTok().getString();
3403 if (!Name.
equals(Prefix))
3416 SMLoc S = Parser.getTok().getLoc();
3420 for (
int I = 0;
I < 4; ++
I) {
3434 if (getParser().parseAbsoluteExpression(Op))
3437 if (Op != 0 && Op != 1)
3443 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Val, S, ImmTy));
3448 AMDGPUAsmParser::parseNamedBit(
const char *Name,
OperandVector &Operands,
3449 AMDGPUOperand::ImmTy ImmTy) {
3451 SMLoc S = Parser.getTok().getLoc();
3456 switch(getLexer().getKind()) {
3458 StringRef Tok = Parser.getTok().getString();
3460 if (Tok ==
"r128" &&
isGFX9())
3461 Error(S,
"r128 modifier is not supported on this GPU");
3462 if (Tok ==
"a16" && !
isGFX9())
3463 Error(S,
"a16 modifier is not supported on this GPU");
3479 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Bit, S, ImmTy));
3485 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
3486 AMDGPUOperand::ImmTy ImmT,
3487 int64_t Default = 0) {
3488 auto i = OptionalIdx.find(ImmT);
3489 if (i != OptionalIdx.end()) {
3490 unsigned Idx = i->second;
3491 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
3502 StringRef Tok = Parser.getTok().getString();
3503 if (Tok != Prefix) {
3517 Value = Parser.getTok().getString();
3525 SMLoc S = Parser.getTok().getLoc();
3526 int64_t Dfmt = 0, Nfmt = 0;
3528 bool GotDfmt =
false, GotNfmt =
false;
3529 while (!GotDfmt || !GotNfmt) {
3531 auto Res = parseIntWithPrefix(
"dfmt", Dfmt);
3536 Error(Parser.getTok().getLoc(),
"out of range dfmt");
3545 auto Res = parseIntWithPrefix(
"nfmt", Nfmt);
3550 Error(Parser.getTok().getLoc(),
"out of range nfmt");
3560 if (!GotDfmt && !GotNfmt)
3562 auto Format = Dfmt | Nfmt << 4;
3564 AMDGPUOperand::CreateImm(
this,
Format, S, AMDGPUOperand::ImmTyFORMAT));
3572 void AMDGPUAsmParser::cvtDSOffset01(
MCInst &Inst,
3574 OptionalImmIndexMap OptionalIdx;
3576 for (
unsigned i = 1, e = Operands.
size(); i != e; ++i) {
3577 AMDGPUOperand &
Op = ((AMDGPUOperand &)*Operands[i]);
3581 Op.addRegOperands(Inst, 1);
3586 OptionalIdx[Op.getImmTy()] = i;
3597 bool IsGdsHardcoded) {
3598 OptionalImmIndexMap OptionalIdx;
3600 for (
unsigned i = 1, e = Operands.
size(); i != e; ++i) {
3601 AMDGPUOperand &
Op = ((AMDGPUOperand &)*Operands[i]);
3605 Op.addRegOperands(Inst, 1);
3609 if (Op.isToken() && Op.getToken() ==
"gds") {
3610 IsGdsHardcoded =
true;
3615 OptionalIdx[Op.getImmTy()] = i;
3618 AMDGPUOperand::ImmTy OffsetType =
3619 (Inst.
getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
3620 Inst.
getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
3621 AMDGPUOperand::ImmTyOffset;
3625 if (!IsGdsHardcoded) {
3632 OptionalImmIndexMap OptionalIdx;
3634 unsigned OperandIdx[4];
3635 unsigned EnMask = 0;
3638 for (
unsigned i = 1, e = Operands.
size(); i != e; ++i) {
3639 AMDGPUOperand &
Op = ((AMDGPUOperand &)*Operands[i]);
3644 OperandIdx[SrcIdx] = Inst.
size();
3645 Op.addRegOperands(Inst, 1);
3652 OperandIdx[SrcIdx] = Inst.
size();
3658 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
3659 Op.addImmOperands(Inst, 1);
3663 if (Op.isToken() && Op.getToken() ==
"done")
3667 OptionalIdx[Op.getImmTy()] = i;
3673 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
3680 for (
auto i = 0; i < SrcIdx; ++i) {
3682 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
3698 const AMDGPU::IsaVersion ISA,
3707 IntVal = encode(ISA, IntVal, CntVal);
3708 if (CntVal !=
decode(ISA, IntVal)) {
3710 IntVal = encode(ISA, IntVal, -1);
3718 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
3719 StringRef CntName = Parser.getTok().getString();
3730 SMLoc ValLoc = Parser.getTok().getLoc();
3731 if (getParser().parseAbsoluteExpression(CntVal))
3737 bool Sat = CntName.
endswith(
"_sat");
3739 if (CntName ==
"vmcnt" || CntName ==
"vmcnt_sat") {
3741 }
else if (CntName ==
"expcnt" || CntName ==
"expcnt_sat") {
3743 }
else if (CntName ==
"lgkmcnt" || CntName ==
"lgkmcnt_sat") {
3748 Error(ValLoc,
"too large value for " + CntName);
3758 const AsmToken NextToken = getLexer().peekTok();
3768 AMDGPUAsmParser::parseSWaitCntOps(
OperandVector &Operands) {
3771 SMLoc S = Parser.getTok().getLoc();
3773 switch(getLexer().getKind()) {
3777 if (getParser().parseAbsoluteExpression(Waitcnt))
3783 if (parseCnt(Waitcnt))
3788 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Waitcnt, S));
3792 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &
Offset,
3796 if (Parser.getTok().getString() !=
"hwreg")
3805 HwReg.IsSymbolic =
true;
3807 const StringRef tok = Parser.getTok().getString();
3819 HwReg.IsSymbolic =
false;
3822 if (getParser().parseAbsoluteExpression(HwReg.Id))
3838 if (getParser().parseAbsoluteExpression(Offset))
3847 if (getParser().parseAbsoluteExpression(Width))
3860 int64_t Imm16Val = 0;
3861 SMLoc S = Parser.getTok().getLoc();
3863 switch(getLexer().getKind()) {
3867 if (getParser().parseAbsoluteExpression(Imm16Val))
3870 Error(S,
"invalid immediate: only 16-bit values are legal");
3880 if (parseHwregConstruct(HwReg, Offset, Width))
3882 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3883 if (HwReg.IsSymbolic)
3884 Error(S,
"invalid symbolic name of hardware register");
3886 Error(S,
"invalid code of hardware register: only 6-bit values are legal");
3888 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3889 Error(S,
"invalid bit offset: only 5-bit values are legal");
3890 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3891 Error(S,
"invalid bitfield width: only values from 1 to 32 are legal");
3896 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3900 bool AMDGPUOperand::isSWaitCnt()
const {
3904 bool AMDGPUOperand::isHwreg()
const {
3905 return isImmTy(ImmTyHwreg);
3908 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &
Operation, int64_t &
StreamId) {
3911 if (Parser.getTok().getString() !=
"sendmsg")
3920 Msg.IsSymbolic =
true;
3922 const std::string tok = Parser.getTok().getString();
3935 Msg.IsSymbolic =
false;
3938 if (getParser().parseAbsoluteExpression(Msg.Id))
3941 if (getParser().parseAbsoluteExpression(Msg.Id))
3961 Operation.IsSymbolic =
true;
3965 const StringRef Tok = Parser.getTok().getString();
3966 for (
int i = F; i < L; ++i) {
3974 Operation.IsSymbolic =
false;
3977 if (getParser().parseAbsoluteExpression(Operation.Id))
3994 if (getParser().parseAbsoluteExpression(StreamId))
4008 StringRef Str = Parser.getTok().getString();
4015 SMLoc S = Parser.getTok().getLoc();
4020 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Slot, S,
4021 AMDGPUOperand::ImmTyInterpSlot));
4029 StringRef Str = Parser.getTok().getString();
4049 SMLoc S = Parser.getTok().getLoc();
4052 Error(S,
"out of bounds attr");
4058 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Attr, S,
4059 AMDGPUOperand::ImmTyInterpAttr));
4060 Operands.
push_back(AMDGPUOperand::CreateImm(
this, AttrChan, SChan,
4061 AMDGPUOperand::ImmTyAttrChan));
4065 void AMDGPUAsmParser::errorExpTgt() {
4066 Error(Parser.getTok().getLoc(),
"invalid exp target");
4071 if (Str ==
"null") {
4130 StringRef Str = Parser.getTok().getString();
4132 auto Res = parseExpTgtImpl(Str, Val);
4136 SMLoc S = Parser.getTok().getLoc();
4139 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Val, S,
4140 AMDGPUOperand::ImmTyExpTgt));
4148 int64_t Imm16Val = 0;
4149 SMLoc S = Parser.getTok().getLoc();
4151 switch(getLexer().getKind()) {
4156 if (getParser().parseAbsoluteExpression(Imm16Val))
4159 Error(S,
"invalid immediate: only 16-bit values are legal");
4168 if (parseSendMsgConstruct(Msg, Operation, StreamId))
4175 Error(S,
"invalid/unsupported symbolic name of message");
4177 Error(S,
"invalid/unsupported code of message");
4184 if (Operation.IsSymbolic)
4185 Error(S,
"invalid symbolic name of GS_OP");
4187 Error(S,
"invalid code of GS_OP: only 2-bit values are legal");
4192 Error(S,
"invalid GS_OP: NOP is for GS_DONE only");
4195 Imm16Val |= (Operation.Id <<
OP_SHIFT_);
4199 if (Operation.IsSymbolic)
4200 Error(S,
"invalid/unsupported symbolic name of SYSMSG_OP");
4202 Error(S,
"invalid/unsupported code of SYSMSG_OP");
4205 Imm16Val |= (Operation.Id <<
OP_SHIFT_);
4210 Error(S,
"invalid stream id: only 2-bit values are legal");
4219 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
4223 bool AMDGPUOperand::isSendMsg()
const {
4224 return isImmTy(ImmTySendMsg);
4234 Parser.getTok().getString() ==
Id) {
4243 if (getLexer().getKind() == Kind) {
4253 if (!trySkipToken(Kind)) {
4254 Error(Parser.getTok().getLoc(), ErrMsg);
4261 AMDGPUAsmParser::parseExpr(int64_t &Imm) {
4262 return !getParser().parseAbsoluteExpression(Imm);
4267 SMLoc S = Parser.getTok().getLoc();
4269 Val = Parser.getTok().getStringContents();
4285 const unsigned OrMask,
4286 const unsigned XorMask) {
4296 AMDGPUAsmParser::parseSwizzleOperands(
const unsigned OpNum, int64_t*
Op,
4297 const unsigned MinVal,
4298 const unsigned MaxVal,
4300 for (
unsigned i = 0; i < OpNum; ++i) {
4304 SMLoc ExprLoc = Parser.getTok().getLoc();
4305 if (!parseExpr(Op[i])) {
4308 if (Op[i] < MinVal || Op[i] > MaxVal) {
4309 Error(ExprLoc, ErrMsg);
4318 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
4323 "expected a 2-bit lane id")) {
4325 for (
auto i = 0; i <
LANE_NUM; ++i) {
4334 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
4337 SMLoc S = Parser.getTok().getLoc();
4341 if (!parseSwizzleOperands(1, &GroupSize,
4343 "group size must be in the interval [2,32]")) {
4347 Error(S,
"group size must be a power of two");
4350 if (parseSwizzleOperands(1, &LaneIdx,
4352 "lane id must be in the interval [0,group size - 1]")) {
4360 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
4363 SMLoc S = Parser.getTok().getLoc();
4366 if (!parseSwizzleOperands(1, &GroupSize,
4367 2, 32,
"group size must be in the interval [2,32]")) {
4371 Error(S,
"group size must be a power of two");
4380 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
4383 SMLoc S = Parser.getTok().getLoc();
4386 if (!parseSwizzleOperands(1, &GroupSize,
4387 1, 16,
"group size must be in the interval [1,16]")) {
4391 Error(S,
"group size must be a power of two");
4400 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
4408 SMLoc StrLoc = Parser.getTok().getLoc();
4409 if (!parseString(Ctl)) {
4413 Error(StrLoc,
"expected a 5-character mask");
4417 unsigned AndMask = 0;
4418 unsigned OrMask = 0;
4419 unsigned XorMask = 0;
4421 for (
size_t i = 0; i < Ctl.
size(); ++i) {
4425 Error(StrLoc,
"invalid mask");
4447 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
4449 SMLoc OffsetLoc = Parser.getTok().getLoc();
4451 if (!parseExpr(Imm)) {
4455 Error(OffsetLoc,
"expected a 16-bit offset");
4462 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
4467 SMLoc ModeLoc = Parser.getTok().getLoc();
4471 Ok = parseSwizzleQuadPerm(Imm);
4473 Ok = parseSwizzleBitmaskPerm(Imm);
4475 Ok = parseSwizzleBroadcast(Imm);
4477 Ok = parseSwizzleSwap(Imm);
4479 Ok = parseSwizzleReverse(Imm);
4481 Error(ModeLoc,
"expected a swizzle mode");
4484 return Ok && skipToken(
AsmToken::RParen,
"expected a closing parentheses");
4492 SMLoc S = Parser.getTok().getLoc();
4495 if (trySkipId(
"offset")) {
4499 if (trySkipId(
"swizzle")) {
4500 Ok = parseSwizzleMacro(Imm);
4502 Ok = parseSwizzleOffset(Imm);
4506 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Imm, S, AMDGPUOperand::ImmTySwizzle));
4512 return parseOptionalOpr(Operands);
4517 AMDGPUOperand::isSwizzle()
const {
4518 return isImmTy(ImmTySwizzle);
4526 AMDGPUAsmParser::parseSOppBrTarget(
OperandVector &Operands) {
4527 SMLoc S = Parser.getTok().getLoc();
4529 switch (getLexer().getKind()) {
4533 if (getParser().parseAbsoluteExpression(Imm))
4535 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Imm, S));
4540 Operands.
push_back(AMDGPUOperand::CreateExpr(
this,
4542 Parser.getTok().getString()), getContext()), S));
4552 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC()
const {
4553 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyGLC);
4556 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC()
const {
4557 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTySLC);
4560 void AMDGPUAsmParser::cvtMubufImpl(
MCInst &Inst,
4563 bool IsAtomicReturn,
4565 bool IsLdsOpcode = IsLds;
4566 bool HasLdsModifier =
false;
4567 OptionalImmIndexMap OptionalIdx;
4568 assert(IsAtomicReturn ? IsAtomic :
true);
4570 for (
unsigned i = 1, e = Operands.
size(); i != e; ++i) {
4571 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4575 Op.addRegOperands(Inst, 1);
4580 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
4581 Op.addImmOperands(Inst, 1);
4585 HasLdsModifier = Op.isLDS();
4595 OptionalIdx[Op.getImmTy()] = i;
4605 if (IsLdsOpcode && !HasLdsModifier) {
4607 if (NoLdsOpcode != -1) {
4609 IsLdsOpcode =
false;
4614 if (IsAtomicReturn) {
4631 OptionalImmIndexMap OptionalIdx;
4633 for (
unsigned i = 1, e = Operands.
size(); i != e; ++i) {
4634 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4638 Op.addRegOperands(Inst, 1);
4643 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
4644 Op.addImmOperands(Inst, 1);
4656 OptionalIdx[Op.getImmTy()] = i;
4660 AMDGPUOperand::ImmTyOffset);
4675 for (
unsigned J = 0; J < Desc.
getNumDefs(); ++J) {
4676 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4682 ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1);
4685 OptionalImmIndexMap OptionalIdx;
4687 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
4688 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4692 Op.addRegOperands(Inst, 1);
4693 }
else if (Op.isImmModifier()) {
4694 OptionalIdx[Op.getImmTy()] =
I;
4712 cvtMIMG(Inst, Operands,
true);
4719 bool AMDGPUOperand::isSMRDOffset8()
const {
4723 bool AMDGPUOperand::isSMRDOffset20()
const {
4724 return isImm() && isUInt<20>(getImm());
4727 bool AMDGPUOperand::isSMRDLiteralOffset()
const {
4733 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8()
const {
4734 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyOffset);
4737 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20()
const {
4738 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyOffset);
4741 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset()
const {
4742 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyOffset);
4745 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12()
const {
4746 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyOffset);
4749 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetS13()
const {
4750 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyOffset);
4758 if (Mul != 1 && Mul != 2 && Mul != 4)
4780 if (BoundCtrl == 0) {
4785 if (BoundCtrl == -1) {
4795 {
"offen", AMDGPUOperand::ImmTyOffen,
true,
nullptr},
4796 {
"idxen", AMDGPUOperand::ImmTyIdxen,
true,
nullptr},
4797 {
"addr64", AMDGPUOperand::ImmTyAddr64,
true,
nullptr},
4798 {
"offset0", AMDGPUOperand::ImmTyOffset0,
false,
nullptr},
4799 {
"offset1", AMDGPUOperand::ImmTyOffset1,
false,
nullptr},
4800 {
"gds", AMDGPUOperand::ImmTyGDS,
true,
nullptr},
4801 {
"lds", AMDGPUOperand::ImmTyLDS,
true,
nullptr},
4802 {
"offset", AMDGPUOperand::ImmTyOffset,
false,
nullptr},
4803 {
"inst_offset", AMDGPUOperand::ImmTyInstOffset,
false,
nullptr},
4804 {
"dfmt", AMDGPUOperand::ImmTyFORMAT,
false,
nullptr},
4805 {
"glc", AMDGPUOperand::ImmTyGLC,
true,
nullptr},
4806 {
"slc", AMDGPUOperand::ImmTySLC,
true,
nullptr},
4807 {
"tfe", AMDGPUOperand::ImmTyTFE,
true,
nullptr},
4808 {
"d16", AMDGPUOperand::ImmTyD16,
true,
nullptr},
4809 {
"high", AMDGPUOperand::ImmTyHigh,
true,
nullptr},
4810 {
"clamp", AMDGPUOperand::ImmTyClampSI,
true,
nullptr},
4812 {
"unorm", AMDGPUOperand::ImmTyUNorm,
true,
nullptr},
4813 {
"da", AMDGPUOperand::ImmTyDA,
true,
nullptr},
4814 {
"r128", AMDGPUOperand::ImmTyR128A16,
true,
nullptr},
4815 {
"a16", AMDGPUOperand::ImmTyR128A16,
true,
nullptr},
4816 {
"lwe", AMDGPUOperand::ImmTyLWE,
true,
nullptr},
4817 {
"d16", AMDGPUOperand::ImmTyD16,
true,
nullptr},
4818 {
"dmask", AMDGPUOperand::ImmTyDMask,
false,
nullptr},
4819 {
"row_mask", AMDGPUOperand::ImmTyDppRowMask,
false,
nullptr},
4820 {
"bank_mask", AMDGPUOperand::ImmTyDppBankMask,
false,
nullptr},
4822 {
"dst_sel", AMDGPUOperand::ImmTySdwaDstSel,
false,
nullptr},
4823 {
"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel,
false,
nullptr},
4824 {
"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel,
false,
nullptr},
4825 {
"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused,
false,
nullptr},
4826 {
"compr", AMDGPUOperand::ImmTyExpCompr,
true,
nullptr },
4827 {
"vm", AMDGPUOperand::ImmTyExpVM,
true,
nullptr},
4828 {
"op_sel", AMDGPUOperand::ImmTyOpSel,
false,
nullptr},
4829 {
"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi,
false,
nullptr},
4830 {
"neg_lo", AMDGPUOperand::ImmTyNegLo,
false,
nullptr},
4831 {
"neg_hi", AMDGPUOperand::ImmTyNegHi,
false,
nullptr}
4851 if (size == 1 || ((AMDGPUOperand &)*Operands[size - 1]).isRegKind()) {
4856 for (
unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
4860 res = parseOptionalOpr(Operands);
4869 for (
const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
4872 res = parseNamedBit(Op.Name, Operands, Op.Type);
4873 }
else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
4874 res = parseOModOperand(Operands);
4875 }
else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
4876 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
4877 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
4878 res = parseSDWASel(Operands, Op.Name, Op.Type);
4879 }
else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
4880 res = parseSDWADstUnused(Operands);
4881 }
else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
4882 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
4883 Op.Type == AMDGPUOperand::ImmTyNegLo ||
4884 Op.Type == AMDGPUOperand::ImmTyNegHi) {
4885 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
4887 }
else if (Op.Type == AMDGPUOperand::ImmTyFORMAT) {
4888 res = parseDfmtNfmt(Operands);
4890 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
4900 StringRef Name = Parser.getTok().getString();
4901 if (Name ==
"mul") {
4902 return parseIntWithPrefix(
"mul", Operands,
4906 if (Name ==
"div") {
4907 return parseIntWithPrefix(
"div", Operands,
4915 cvtVOP3P(Inst, Operands);
4920 const int Ops[] = { AMDGPU::OpName::src0,
4921 AMDGPU::OpName::src1,
4922 AMDGPU::OpName::src2 };
4931 if ((OpSel & (1 << SrcNum)) != 0) {
4951 OptionalImmIndexMap OptionalIdx;
4956 for (
unsigned J = 0; J < Desc.
getNumDefs(); ++J) {
4957 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4960 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
4961 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4963 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4964 }
else if (Op.isInterpSlot() ||
4965 Op.isInterpAttr() ||
4968 }
else if (Op.isImmModifier()) {
4969 OptionalIdx[Op.getImmTy()] =
I;
4989 OptionalImmIndexMap &OptionalIdx) {
4994 for (
unsigned J = 0; J < Desc.
getNumDefs(); ++J) {
4995 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5000 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
5001 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5003 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
5004 }
else if (Op.isImmModifier()) {
5005 OptionalIdx[Op.getImmTy()] =
I;
5006 }
else if (Op.isRegOrImm()) {
5007 Op.addRegOrImmOperands(Inst, 1);
5014 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
5015 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5017 OptionalIdx[Op.getImmTy()] =
I;
5019 Op.addRegOrImmOperands(Inst, 1);
5036 if (Opc == AMDGPU::V_MAC_F32_e64_si ||
5037 Opc == AMDGPU::V_MAC_F32_e64_vi ||
5038 Opc == AMDGPU::V_MAC_F16_e64_vi ||
5039 Opc == AMDGPU::V_FMAC_F32_e64_vi) {
5040 auto it = Inst.
begin();
5049 OptionalImmIndexMap OptionalIdx;
5050 cvtVOP3(Inst, Operands, OptionalIdx);
5053 void AMDGPUAsmParser::cvtVOP3P(
MCInst &Inst,
5055 OptionalImmIndexMap OptIdx;
5061 cvtVOP3(Inst, Operands, OptIdx);
5074 if (OpSelHiIdx != -1) {
5075 int DefaultVal = IsPacked ? -1 : 0;
5081 if (NegLoIdx != -1) {
5087 const int Ops[] = { AMDGPU::OpName::src0,
5088 AMDGPU::OpName::src1,
5089 AMDGPU::OpName::src2 };
5090 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
5091 AMDGPU::OpName::src1_modifiers,
5092 AMDGPU::OpName::src2_modifiers };
5097 unsigned OpSelHi = 0;
5101 if (OpSelHiIdx != -1) {
5105 if (NegLoIdx != -1) {
5111 for (
int J = 0; J < 3; ++J) {
5118 if ((OpSel & (1 << J)) != 0)
5121 if ((OpSelHi & (1 << J)) != 0)
5124 if ((NegLo & (1 << J)) != 0)
5127 if ((NegHi & (1 << J)) != 0)
5140 bool AMDGPUOperand::isDPPCtrl()
const {
5143 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
5145 int64_t Imm = getImm();
5162 bool AMDGPUOperand::isGPRIdxMode()
const {
5163 return isImm() && isUInt<4>(getImm());
5166 bool AMDGPUOperand::isS16Imm()
const {
5170 bool AMDGPUOperand::isU16Imm()
const {
5178 SMLoc S = Parser.getTok().getLoc();
5183 Prefix = Parser.getTok().getString();
5188 if (Prefix ==
"row_mirror") {
5191 }
else if (Prefix ==
"row_half_mirror") {
5196 if (Prefix !=
"quad_perm" 5197 && Prefix !=
"row_shl" 5198 && Prefix !=
"row_shr" 5199 && Prefix !=
"row_ror" 5200 && Prefix !=
"wave_shl" 5201 && Prefix !=
"wave_rol" 5202 && Prefix !=
"wave_shr" 5203 && Prefix !=
"wave_ror" 5204 && Prefix !=
"row_bcast") {
5212 if (Prefix ==
"quad_perm") {
5219 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
5222 for (
int i = 0; i < 3; ++i) {
5228 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
5230 const int shift = i*2 + 2;
5231 Int += (Temp << shift);
5240 if (getParser().parseAbsoluteExpression(Int))
5243 if (Prefix ==
"row_shl" && 1 <= Int && Int <= 15) {
5245 }
else if (Prefix ==
"row_shr" && 1 <= Int && Int <= 15) {
5247 }
else if (Prefix ==
"row_ror" && 1 <= Int && Int <= 15) {
5249 }
else if (Prefix ==
"wave_shl" && 1 == Int) {
5251 }
else if (Prefix ==
"wave_rol" && 1 == Int) {
5253 }
else if (Prefix ==
"wave_shr" && 1 == Int) {
5255 }
else if (Prefix ==
"wave_ror" && 1 == Int) {
5257 }
else if (Prefix ==
"row_bcast") {
5260 }
else if (Int == 31) {
5271 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
5275 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask()
const {
5276 return AMDGPUOperand::CreateImm(
this, 0xf,
SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
5279 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask()
const {
5280 return AMDGPUOperand::CreateImm(
this, 0xf,
SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
5283 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl()
const {
5284 return AMDGPUOperand::CreateImm(
this, 0,
SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
5288 OptionalImmIndexMap OptionalIdx;
5292 for (
unsigned J = 0; J < Desc.
getNumDefs(); ++J) {
5293 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5296 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
5304 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5306 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
5311 Op.addRegWithFPInputModsOperands(Inst, 2);
5312 }
else if (Op.isDPPCtrl()) {
5313 Op.addImmOperands(Inst, 1);
5314 }
else if (Op.isImm()) {
5316 OptionalIdx[Op.getImmTy()] =
I;
5333 AMDGPUOperand::ImmTy Type) {
5336 SMLoc S = Parser.getTok().getLoc();
5340 res = parseStringWithPrefix(Prefix, Value);
5357 if (Int == 0xffffffff) {
5361 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Int, S, Type));
5366 AMDGPUAsmParser::parseSDWADstUnused(
OperandVector &Operands) {
5369 SMLoc S = Parser.getTok().getLoc();
5373 res = parseStringWithPrefix(
"dst_unused", Value);
5386 if (Int == 0xffffffff) {
5390 Operands.
push_back(AMDGPUOperand::CreateImm(
this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
5411 uint64_t BasicInstType,
bool skipVcc) {
5414 OptionalImmIndexMap OptionalIdx;
5415 bool skippedVcc =
false;
5419 for (
unsigned J = 0; J < Desc.
getNumDefs(); ++J) {
5420 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5423 for (
unsigned E = Operands.
size(); I !=
E; ++
I) {
5424 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5425 if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
5441 Op.addRegOrImmWithInputModsOperands(Inst, 2);
5442 }
else if (Op.isImm()) {
5444 OptionalIdx[Op.getImmTy()] =
I;
5451 if (Inst.
getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
5452 Inst.
getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
5454 switch (BasicInstType) {
5483 llvm_unreachable(
"Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
5489 if (Inst.
getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
5490 Inst.
getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
5491 auto it = Inst.
begin();
5504 #define GET_REGISTER_MATCHER 5505 #define GET_MATCHER_IMPLEMENTATION 5506 #define GET_MNEMONIC_SPELL_CHECKER 5507 #include "AMDGPUGenAsmMatcher.inc" 5517 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
5520 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
5522 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
5524 return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
5526 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
5528 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
5530 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
5538 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
5540 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
5541 case MCK_SoppBrTarget:
5542 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
5543 case MCK_VReg32OrOff:
5544 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
5545 case MCK_InterpSlot:
5546 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
5548 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
5550 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
5552 return Match_InvalidOperand;
static bool isReg(const MCInst &MI, unsigned OpNo)
unsigned getNumImplicitUses() const
Return the number of implicit uses this instruction has.
constexpr bool isUInt< 32 >(uint64_t x)
Represents a range in source code.
unsigned mc2PseudoReg(unsigned Reg)
Convert hardware register Reg to a pseudo register.
Target & getTheGCNTarget()
The target for GCN GPUs.
bool hasPackedD16(const MCSubtargetInfo &STI)
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum)
uint64_t getZExtValue() const
Get zero extended value.
static const fltSemantics * getOpFltSemantics(uint8_t OperandType)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
This class represents lattice values for constants.
bool isVariable() const
isVariable - Check if this is a variable symbol.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
constexpr char AssemblerDirectiveBegin[]
HSA metadata beginning assembler directive.
static MCOperand createExpr(const MCExpr *Val)
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Target & getTheAMDGPUTarget()
The target which supports all AMD GPUs.
void push_back(const T &Elt)
Represents the counter values to wait for in an s_waitcnt instruction.
Describe properties that are true of each instruction in the target description file.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
static bool encodeCnt(const AMDGPU::IsaVersion ISA, int64_t &IntVal, int64_t CntVal, bool Saturate, unsigned(*encode)(const IsaVersion &Version, unsigned, unsigned), unsigned(*decode)(const IsaVersion &Version, unsigned))
const FeatureBitset Features
Instruction set architecture version.
iterator find(StringRef Key)
static unsigned getSpecialRegForName(StringRef RegName)
unsigned decodeVmcnt(const IsaVersion &Version, unsigned Waitcnt)
static InstrUID decode(OpcodeType type, InstructionContext insnContext, uint8_t opcode, uint8_t modRM)
A raw_ostream that writes to an SmallVector or SmallString.
constexpr bool isInt< 16 >(int64_t x)
unsigned const TargetRegisterInfo * TRI
bool isInlinableLiteralV216(int32_t Literal, bool HasInv2Pi)
unsigned encodeVmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Vmcnt)
static void addOptionalImmOperand(MCInst &Inst, const OperandVector &Operands, AMDGPUAsmParser::OptionalImmIndexMap &OptionalIdx, AMDGPUOperand::ImmTy ImmT, int64_t Default=0)
bool mayLoad() const
Return true if this instruction could possibly read memory.
unsigned decodeExpcnt(const IsaVersion &Version, unsigned Waitcnt)
static bool ConvertOmodDiv(int64_t &Div)
bool parseAmdKernelCodeField(StringRef ID, MCAsmParser &Parser, amd_kernel_code_t &C, raw_ostream &Err)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static LLVM_READNONE unsigned encodeBitmaskPerm(const unsigned AndMask, const unsigned OrMask, const unsigned XorMask)
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo=false)
Emit the given Instruction into the current section.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_back(size_t N=1) const
Return a StringRef equal to 'this' but with only the last N elements remaining.
bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi)
amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor()
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
static MCOperand createReg(unsigned Reg)
bool isRegIntersect(unsigned Reg0, unsigned Reg1, const MCRegisterInfo *TRI)
Is there any intersection between registers.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
AMD Kernel Code Object (amd_kernel_code_t).
unsigned getRegOperandSize(const MCRegisterInfo *MRI, const MCInstrDesc &Desc, unsigned OpNo)
Get size of register operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Base class for the full range of assembler expressions which are needed for parsing.
unsigned getNumVGPRBlocks(const MCSubtargetInfo *STI, unsigned NumVGPRs)
Target independent representation for an assembler token.
static int getRegClass(RegisterKind Is, unsigned RegWidth)
Represent a reference to a symbol from inside an expression.
uint32_t compute_pgm_rsrc2
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
static bool isMem(const MachineInstr &MI, unsigned Op)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand...
This file implements a class to represent arbitrary precision integral constant values and operations...
uint32_t private_segment_fixed_size
unsigned getReg() const
Returns the register number.
bool hasCodeObjectV3(const MCSubtargetInfo *STI)
unsigned getSizeInBits() const
std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \\\)
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
uint8_t OperandType
Information about the type of the operand.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
uint32_t group_segment_fixed_size
RegisterMCAsmParser - Helper template for registering a target specific assembly parser, for use in the target machine initialization function.
unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed, bool FlatScrUsed, bool XNACKUsed)
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
unsigned encodeExpcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Expcnt)
static const fltSemantics & IEEEdouble() LLVM_READNONE
unsigned decodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
uint16_t kernel_code_properties
MCRegisterClass - Base class of TargetRegisterClass.
iterator insert(iterator I, const MCOperand &Op)
Analysis containing CSE Info
Instances of this class represent a single low-level machine instruction.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
unsigned short NumOperands
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool isSISrcFPOperand(const MCInstrDesc &Desc, unsigned OpNo)
Is this floating-point operand?
A switch()-like statement whose cases are string literals.
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
Streaming machine code generation interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
bool isSI(const MCSubtargetInfo &STI)
constexpr bool isUInt< 8 >(uint64_t x)
unsigned const MachineRegisterInfo * MRI
constexpr char AssemblerDirectiveBegin[]
HSA metadata beginning assembler directive.
Container class for subtarget features.
The instances of the Type class are immutable: once they are created, they are never changed...
PowerPC Reduce CR logical Operation
unsigned getScalarSizeInBits() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const char *const IdSymbolic[]
MCRegAliasIterator enumerates all registers aliasing Reg.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
unsigned getNumOperands() const
static const OptionalOperand AMDGPUOptionalOperandTable[]
SmallVectorImpl< MCOperand >::iterator iterator
constexpr char AssemblerDirectiveEnd[]
HSA metadata ending assembler directive.
constexpr char AssemblerDirective[]
PAL metadata assembler directive.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
#define AMDHSA_BITS_SET(DST, MSK, VAL)
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< typename base::iterator, bool > insert(StringRef Key)
constexpr char NumSGPRs[]
Key for Kernel::CodeProps::Metadata::mNumSGPRs.
Operands with register or inline constant.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
IsaVersion getIsaVersion(StringRef GPU)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set.
static bool ConvertBoundCtrl(int64_t &BoundCtrl)
AMDHSA kernel descriptor definitions.
void setOpcode(unsigned Op)
unsigned countPopulation(T Value)
Count the number of set bits in a value.
constexpr std::enable_if<(N< 64), bool >::type isUInt(uint64_t X)
Checks if an unsigned integer fits into the given bit width.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
LLVM_READONLY int getMUBUFNoLdsInst(uint16_t Opcode)
constexpr bool isInt< 32 >(int64_t x)
testing::Matcher< const detail::ErrorHolder & > Failed()
const MCSymbol & getSymbol() const
unsigned getAddressableNumSGPRs(const MCSubtargetInfo *STI)
const MCOperand & getOperand(unsigned i) const
Promote Memory to Register
static bool ConvertOmodMul(int64_t &Mul)
StringRef str()
Return a StringRef for the vector contents.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
void setVariableValue(const MCExpr *Value)
double BitsToDouble(uint64_t Bits)
This function takes a 64-bit integer and returns the bit equivalent double.
void LLVMInitializeAMDGPUAsmParser()
Force static initialization.
bool is(TokenKind K) const
Target - Wrapper for Target specific information.
Class for arbitrary precision integers.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const char *const OpSysSymbolic[]
Base class for user error types.
bool mayStore() const
Return true if this instruction could possibly modify memory.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
static std::string AMDGPUMnemonicSpellCheck(StringRef S, uint64_t FBS, unsigned VariantID=0)
bool isCI(const MCSubtargetInfo &STI)
static SMLoc getFromPointer(const char *Ptr)
uint32_t compute_pgm_rsrc1
bool isGFX9(const MCSubtargetInfo &STI)
const char *const OpGsSymbolic[]
Provides AMDGPU specific target descriptions.
Interface definition for SIInstrInfo.
constexpr char AssemblerDirectiveEnd[]
HSA metadata ending assembler directive.
static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT)
bool isVI(const MCSubtargetInfo &STI)
unsigned getNumSGPRBlocks(const MCSubtargetInfo *STI, unsigned NumSGPRs)
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasXNACK(const MCSubtargetInfo &STI)
unsigned getWaitcntBitMask(const IsaVersion &Version)
constexpr bool isUInt< 16 >(uint64_t x)
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Operands with register or 32-bit immediate.
void setReg(unsigned Reg)
Set the register number.
StringRef getName() const
getName - Get the symbol name.
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo)
Can this operand also contain immediate values?
static StringRef getCPU(StringRef CPU)
Processes a CPU name.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
A raw_ostream that writes to an std::string.
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM Value Representation.
Lightweight error class with error context and mandatory checking.
const MCOperandInfo * OpInfo
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_READNONE unsigned getOperandSize(const MCOperandInfo &OpInfo)
StringSet - A wrapper for StringMap that provides set-like functionality.
unsigned getMCReg(unsigned Reg, const MCSubtargetInfo &STI)
If Reg is a pseudo reg, return the correct hardware register given STI otherwise return Reg...
This class implements an extremely fast bulk output stream that can only output to a stream...
static const fltSemantics * getFltSemantics(unsigned Size)
void addOperand(const MCOperand &Op)
StringRef - Represent a constant reference to a string, i.e.
APInt bitcastToAPInt() const
bool isSGPR(unsigned Reg, const MCRegisterInfo *TRI)
Is Reg - scalar register.
Represents a location in source code.
unsigned getOpcode() const
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Instances of this class represent operands of the MCInst class.
void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, const MCSubtargetInfo *STI)
static MCOperand createImm(int64_t Val)
unsigned encodeLgkmcnt(const IsaVersion &Version, unsigned Waitcnt, unsigned Lgkmcnt)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
std::vector< uint32_t > Metadata
PAL metadata represented as a vector.
void streamIsaVersion(const MCSubtargetInfo *STI, raw_ostream &Stream)
Streams isa version string for given subtarget STI into Stream.
const MCRegisterClass & getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
const MCPhysReg * ImplicitUses