1 //===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AMDKernelCodeT.h" 10 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 11 #include "MCTargetDesc/AMDGPUTargetStreamer.h" 12 #include "SIDefines.h" 13 #include "SIInstrInfo.h" 14 #include "SIRegisterInfo.h" 15 #include "TargetInfo/AMDGPUTargetInfo.h" 16 #include "Utils/AMDGPUAsmUtils.h" 17 #include "Utils/AMDGPUBaseInfo.h" 18 #include "Utils/AMDKernelCodeTUtils.h" 19 #include "llvm/ADT/APFloat.h" 20 #include "llvm/ADT/SmallBitVector.h" 21 #include "llvm/ADT/StringSet.h" 22 #include "llvm/ADT/Twine.h" 23 #include "llvm/BinaryFormat/ELF.h" 24 #include "llvm/CodeGen/MachineValueType.h" 25 #include "llvm/MC/MCAsmInfo.h" 26 #include "llvm/MC/MCContext.h" 27 #include "llvm/MC/MCExpr.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/MC/MCInstrDesc.h" 30 #include "llvm/MC/MCParser/MCAsmLexer.h" 31 #include "llvm/MC/MCParser/MCAsmParser.h" 32 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 33 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 34 #include "llvm/MC/MCSymbol.h" 35 #include "llvm/MC/TargetRegistry.h" 36 #include "llvm/Support/AMDGPUMetadata.h" 37 #include "llvm/Support/AMDHSAKernelDescriptor.h" 38 #include "llvm/Support/Casting.h" 39 #include "llvm/Support/MathExtras.h" 40 #include "llvm/TargetParser/TargetParser.h" 41 #include <optional> 42 43 using namespace llvm; 44 using namespace llvm::AMDGPU; 45 using namespace llvm::amdhsa; 46 47 namespace { 48 49 class AMDGPUAsmParser; 50 51 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_AGPR, IS_TTMP, IS_SPECIAL }; 52 53 //===----------------------------------------------------------------------===// 54 // Operand 55 //===----------------------------------------------------------------------===// 56 57 class AMDGPUOperand : public MCParsedAsmOperand { 58 enum KindTy { 59 Token, 60 Immediate, 61 Register, 62 Expression 63 } Kind; 64 65 SMLoc StartLoc, EndLoc; 66 const AMDGPUAsmParser *AsmParser; 67 68 public: 69 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_) 70 : Kind(Kind_), AsmParser(AsmParser_) {} 71 72 using Ptr = std::unique_ptr<AMDGPUOperand>; 73 74 struct Modifiers { 75 bool Abs = false; 76 bool Neg = false; 77 bool Sext = false; 78 bool Lit = false; 79 80 bool hasFPModifiers() const { return Abs || Neg; } 81 bool hasIntModifiers() const { return Sext; } 82 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); } 83 84 int64_t getFPModifiersOperand() const { 85 int64_t Operand = 0; 86 Operand |= Abs ? SISrcMods::ABS : 0u; 87 Operand |= Neg ? SISrcMods::NEG : 0u; 88 return Operand; 89 } 90 91 int64_t getIntModifiersOperand() const { 92 int64_t Operand = 0; 93 Operand |= Sext ? SISrcMods::SEXT : 0u; 94 return Operand; 95 } 96 97 int64_t getModifiersOperand() const { 98 assert(!(hasFPModifiers() && hasIntModifiers()) 99 && "fp and int modifiers should not be used simultaneously"); 100 if (hasFPModifiers()) { 101 return getFPModifiersOperand(); 102 } else if (hasIntModifiers()) { 103 return getIntModifiersOperand(); 104 } else { 105 return 0; 106 } 107 } 108 109 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods); 110 }; 111 112 enum ImmTy { 113 ImmTyNone, 114 ImmTyGDS, 115 ImmTyLDS, 116 ImmTyOffen, 117 ImmTyIdxen, 118 ImmTyAddr64, 119 ImmTyOffset, 120 ImmTyInstOffset, 121 ImmTyOffset0, 122 ImmTyOffset1, 123 ImmTySMEMOffsetMod, 124 ImmTyCPol, 125 ImmTyTFE, 126 ImmTyD16, 127 ImmTyClampSI, 128 ImmTyOModSI, 129 ImmTySDWADstSel, 130 ImmTySDWASrc0Sel, 131 ImmTySDWASrc1Sel, 132 ImmTySDWADstUnused, 133 ImmTyDMask, 134 ImmTyDim, 135 ImmTyUNorm, 136 ImmTyDA, 137 ImmTyR128A16, 138 ImmTyA16, 139 ImmTyLWE, 140 ImmTyExpTgt, 141 ImmTyExpCompr, 142 ImmTyExpVM, 143 ImmTyFORMAT, 144 ImmTyHwreg, 145 ImmTyOff, 146 ImmTySendMsg, 147 ImmTyInterpSlot, 148 ImmTyInterpAttr, 149 ImmTyInterpAttrChan, 150 ImmTyOpSel, 151 ImmTyOpSelHi, 152 ImmTyNegLo, 153 ImmTyNegHi, 154 ImmTyDPP8, 155 ImmTyDppCtrl, 156 ImmTyDppRowMask, 157 ImmTyDppBankMask, 158 ImmTyDppBoundCtrl, 159 ImmTyDppFI, 160 ImmTySwizzle, 161 ImmTyGprIdxMode, 162 ImmTyHigh, 163 ImmTyBLGP, 164 ImmTyCBSZ, 165 ImmTyABID, 166 ImmTyEndpgm, 167 ImmTyWaitVDST, 168 ImmTyWaitEXP, 169 ImmTyWaitVAVDst, 170 ImmTyWaitVMVSrc, 171 }; 172 173 // Immediate operand kind. 174 // It helps to identify the location of an offending operand after an error. 175 // Note that regular literals and mandatory literals (KImm) must be handled 176 // differently. When looking for an offending operand, we should usually 177 // ignore mandatory literals because they are part of the instruction and 178 // cannot be changed. Report location of mandatory operands only for VOPD, 179 // when both OpX and OpY have a KImm and there are no other literals. 180 enum ImmKindTy { 181 ImmKindTyNone, 182 ImmKindTyLiteral, 183 ImmKindTyMandatoryLiteral, 184 ImmKindTyConst, 185 }; 186 187 private: 188 struct TokOp { 189 const char *Data; 190 unsigned Length; 191 }; 192 193 struct ImmOp { 194 int64_t Val; 195 ImmTy Type; 196 bool IsFPImm; 197 mutable ImmKindTy Kind; 198 Modifiers Mods; 199 }; 200 201 struct RegOp { 202 unsigned RegNo; 203 Modifiers Mods; 204 }; 205 206 union { 207 TokOp Tok; 208 ImmOp Imm; 209 RegOp Reg; 210 const MCExpr *Expr; 211 }; 212 213 public: 214 bool isToken() const override { return Kind == Token; } 215 216 bool isSymbolRefExpr() const { 217 return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr); 218 } 219 220 bool isImm() const override { 221 return Kind == Immediate; 222 } 223 224 void setImmKindNone() const { 225 assert(isImm()); 226 Imm.Kind = ImmKindTyNone; 227 } 228 229 void setImmKindLiteral() const { 230 assert(isImm()); 231 Imm.Kind = ImmKindTyLiteral; 232 } 233 234 void setImmKindMandatoryLiteral() const { 235 assert(isImm()); 236 Imm.Kind = ImmKindTyMandatoryLiteral; 237 } 238 239 void setImmKindConst() const { 240 assert(isImm()); 241 Imm.Kind = ImmKindTyConst; 242 } 243 244 bool IsImmKindLiteral() const { 245 return isImm() && Imm.Kind == ImmKindTyLiteral; 246 } 247 248 bool IsImmKindMandatoryLiteral() const { 249 return isImm() && Imm.Kind == ImmKindTyMandatoryLiteral; 250 } 251 252 bool isImmKindConst() const { 253 return isImm() && Imm.Kind == ImmKindTyConst; 254 } 255 256 bool isInlinableImm(MVT type) const; 257 bool isLiteralImm(MVT type) const; 258 259 bool isRegKind() const { 260 return Kind == Register; 261 } 262 263 bool isReg() const override { 264 return isRegKind() && !hasModifiers(); 265 } 266 267 bool isRegOrInline(unsigned RCID, MVT type) const { 268 return isRegClass(RCID) || isInlinableImm(type); 269 } 270 271 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const { 272 return isRegOrInline(RCID, type) || isLiteralImm(type); 273 } 274 275 bool isRegOrImmWithInt16InputMods() const { 276 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16); 277 } 278 279 bool isRegOrImmWithIntT16InputMods() const { 280 return isRegOrImmWithInputMods(AMDGPU::VS_16RegClassID, MVT::i16); 281 } 282 283 bool isRegOrImmWithInt32InputMods() const { 284 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32); 285 } 286 287 bool isRegOrInlineImmWithInt16InputMods() const { 288 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i16); 289 } 290 291 bool isRegOrInlineImmWithInt32InputMods() const { 292 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::i32); 293 } 294 295 bool isRegOrImmWithInt64InputMods() const { 296 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64); 297 } 298 299 bool isRegOrImmWithFP16InputMods() const { 300 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16); 301 } 302 303 bool isRegOrImmWithFPT16InputMods() const { 304 return isRegOrImmWithInputMods(AMDGPU::VS_16RegClassID, MVT::f16); 305 } 306 307 bool isRegOrImmWithFP32InputMods() const { 308 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32); 309 } 310 311 bool isRegOrImmWithFP64InputMods() const { 312 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64); 313 } 314 315 bool isRegOrInlineImmWithFP16InputMods() const { 316 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::f16); 317 } 318 319 bool isRegOrInlineImmWithFP32InputMods() const { 320 return isRegOrInline(AMDGPU::VS_32RegClassID, MVT::f32); 321 } 322 323 324 bool isVReg() const { 325 return isRegClass(AMDGPU::VGPR_32RegClassID) || 326 isRegClass(AMDGPU::VReg_64RegClassID) || 327 isRegClass(AMDGPU::VReg_96RegClassID) || 328 isRegClass(AMDGPU::VReg_128RegClassID) || 329 isRegClass(AMDGPU::VReg_160RegClassID) || 330 isRegClass(AMDGPU::VReg_192RegClassID) || 331 isRegClass(AMDGPU::VReg_256RegClassID) || 332 isRegClass(AMDGPU::VReg_512RegClassID) || 333 isRegClass(AMDGPU::VReg_1024RegClassID); 334 } 335 336 bool isVReg32() const { 337 return isRegClass(AMDGPU::VGPR_32RegClassID); 338 } 339 340 bool isVReg32OrOff() const { 341 return isOff() || isVReg32(); 342 } 343 344 bool isNull() const { 345 return isRegKind() && getReg() == AMDGPU::SGPR_NULL; 346 } 347 348 bool isVRegWithInputMods() const; 349 template <bool IsFake16> bool isT16VRegWithInputMods() const; 350 351 bool isSDWAOperand(MVT type) const; 352 bool isSDWAFP16Operand() const; 353 bool isSDWAFP32Operand() const; 354 bool isSDWAInt16Operand() const; 355 bool isSDWAInt32Operand() const; 356 357 bool isImmTy(ImmTy ImmT) const { 358 return isImm() && Imm.Type == ImmT; 359 } 360 361 template <ImmTy Ty> bool isImmTy() const { return isImmTy(Ty); } 362 363 bool isImmLiteral() const { return isImmTy(ImmTyNone); } 364 365 bool isImmModifier() const { 366 return isImm() && Imm.Type != ImmTyNone; 367 } 368 369 bool isOModSI() const { return isImmTy(ImmTyOModSI); } 370 bool isDMask() const { return isImmTy(ImmTyDMask); } 371 bool isDim() const { return isImmTy(ImmTyDim); } 372 bool isR128A16() const { return isImmTy(ImmTyR128A16); } 373 bool isOff() const { return isImmTy(ImmTyOff); } 374 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); } 375 bool isOffen() const { return isImmTy(ImmTyOffen); } 376 bool isIdxen() const { return isImmTy(ImmTyIdxen); } 377 bool isAddr64() const { return isImmTy(ImmTyAddr64); } 378 bool isOffset() const { return isImmTy(ImmTyOffset); } 379 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); } 380 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } 381 bool isSMEMOffsetMod() const { return isImmTy(ImmTySMEMOffsetMod); } 382 bool isFlatOffset() const { return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset); } 383 bool isGDS() const { return isImmTy(ImmTyGDS); } 384 bool isLDS() const { return isImmTy(ImmTyLDS); } 385 bool isCPol() const { return isImmTy(ImmTyCPol); } 386 bool isTFE() const { return isImmTy(ImmTyTFE); } 387 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<7>(getImm()); } 388 bool isDppBankMask() const { return isImmTy(ImmTyDppBankMask); } 389 bool isDppRowMask() const { return isImmTy(ImmTyDppRowMask); } 390 bool isDppBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); } 391 bool isDppFI() const { return isImmTy(ImmTyDppFI); } 392 bool isSDWADstSel() const { return isImmTy(ImmTySDWADstSel); } 393 bool isSDWASrc0Sel() const { return isImmTy(ImmTySDWASrc0Sel); } 394 bool isSDWASrc1Sel() const { return isImmTy(ImmTySDWASrc1Sel); } 395 bool isSDWADstUnused() const { return isImmTy(ImmTySDWADstUnused); } 396 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); } 397 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); } 398 bool isInterpAttrChan() const { return isImmTy(ImmTyInterpAttrChan); } 399 bool isOpSel() const { return isImmTy(ImmTyOpSel); } 400 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); } 401 bool isNegLo() const { return isImmTy(ImmTyNegLo); } 402 bool isNegHi() const { return isImmTy(ImmTyNegHi); } 403 404 bool isRegOrImm() const { 405 return isReg() || isImm(); 406 } 407 408 bool isRegClass(unsigned RCID) const; 409 410 bool isInlineValue() const; 411 412 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const { 413 return isRegOrInline(RCID, type) && !hasModifiers(); 414 } 415 416 bool isSCSrcB16() const { 417 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16); 418 } 419 420 bool isSCSrcV2B16() const { 421 return isSCSrcB16(); 422 } 423 424 bool isSCSrcB32() const { 425 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32); 426 } 427 428 bool isSCSrcB64() const { 429 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64); 430 } 431 432 bool isBoolReg() const; 433 434 bool isSCSrcF16() const { 435 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16); 436 } 437 438 bool isSCSrcV2F16() const { 439 return isSCSrcF16(); 440 } 441 442 bool isSCSrcF32() const { 443 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32); 444 } 445 446 bool isSCSrcF64() const { 447 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64); 448 } 449 450 bool isSSrcB32() const { 451 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr(); 452 } 453 454 bool isSSrcB16() const { 455 return isSCSrcB16() || isLiteralImm(MVT::i16); 456 } 457 458 bool isSSrcV2B16() const { 459 llvm_unreachable("cannot happen"); 460 return isSSrcB16(); 461 } 462 463 bool isSSrcB64() const { 464 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 465 // See isVSrc64(). 466 return isSCSrcB64() || isLiteralImm(MVT::i64); 467 } 468 469 bool isSSrcF32() const { 470 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr(); 471 } 472 473 bool isSSrcF64() const { 474 return isSCSrcB64() || isLiteralImm(MVT::f64); 475 } 476 477 bool isSSrcF16() const { 478 return isSCSrcB16() || isLiteralImm(MVT::f16); 479 } 480 481 bool isSSrcV2F16() const { 482 llvm_unreachable("cannot happen"); 483 return isSSrcF16(); 484 } 485 486 bool isSSrcV2FP32() const { 487 llvm_unreachable("cannot happen"); 488 return isSSrcF32(); 489 } 490 491 bool isSCSrcV2FP32() const { 492 llvm_unreachable("cannot happen"); 493 return isSCSrcF32(); 494 } 495 496 bool isSSrcV2INT32() const { 497 llvm_unreachable("cannot happen"); 498 return isSSrcB32(); 499 } 500 501 bool isSCSrcV2INT32() const { 502 llvm_unreachable("cannot happen"); 503 return isSCSrcB32(); 504 } 505 506 bool isSSrcOrLdsB32() const { 507 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) || 508 isLiteralImm(MVT::i32) || isExpr(); 509 } 510 511 bool isVCSrcB32() const { 512 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32); 513 } 514 515 bool isVCSrcB64() const { 516 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64); 517 } 518 519 bool isVCSrcTB16() const { 520 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::i16); 521 } 522 523 bool isVCSrcTB16_Lo128() const { 524 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::i16); 525 } 526 527 bool isVCSrcFake16B16_Lo128() const { 528 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::i16); 529 } 530 531 bool isVCSrcB16() const { 532 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16); 533 } 534 535 bool isVCSrcV2B16() const { 536 return isVCSrcB16(); 537 } 538 539 bool isVCSrcF32() const { 540 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32); 541 } 542 543 bool isVCSrcF64() const { 544 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64); 545 } 546 547 bool isVCSrcTF16() const { 548 return isRegOrInlineNoMods(AMDGPU::VS_16RegClassID, MVT::f16); 549 } 550 551 bool isVCSrcTF16_Lo128() const { 552 return isRegOrInlineNoMods(AMDGPU::VS_16_Lo128RegClassID, MVT::f16); 553 } 554 555 bool isVCSrcFake16F16_Lo128() const { 556 return isRegOrInlineNoMods(AMDGPU::VS_32_Lo128RegClassID, MVT::f16); 557 } 558 559 bool isVCSrcF16() const { 560 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16); 561 } 562 563 bool isVCSrcV2F16() const { 564 return isVCSrcF16(); 565 } 566 567 bool isVSrcB32() const { 568 return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr(); 569 } 570 571 bool isVSrcB64() const { 572 return isVCSrcF64() || isLiteralImm(MVT::i64); 573 } 574 575 bool isVSrcTB16() const { return isVCSrcTB16() || isLiteralImm(MVT::i16); } 576 577 bool isVSrcTB16_Lo128() const { 578 return isVCSrcTB16_Lo128() || isLiteralImm(MVT::i16); 579 } 580 581 bool isVSrcFake16B16_Lo128() const { 582 return isVCSrcFake16B16_Lo128() || isLiteralImm(MVT::i16); 583 } 584 585 bool isVSrcB16() const { 586 return isVCSrcB16() || isLiteralImm(MVT::i16); 587 } 588 589 bool isVSrcV2B16() const { 590 return isVSrcB16() || isLiteralImm(MVT::v2i16); 591 } 592 593 bool isVCSrcV2FP32() const { 594 return isVCSrcF64(); 595 } 596 597 bool isVSrcV2FP32() const { 598 return isVSrcF64() || isLiteralImm(MVT::v2f32); 599 } 600 601 bool isVCSrcV2INT32() const { 602 return isVCSrcB64(); 603 } 604 605 bool isVSrcV2INT32() const { 606 return isVSrcB64() || isLiteralImm(MVT::v2i32); 607 } 608 609 bool isVSrcF32() const { 610 return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr(); 611 } 612 613 bool isVSrcF64() const { 614 return isVCSrcF64() || isLiteralImm(MVT::f64); 615 } 616 617 bool isVSrcTF16() const { return isVCSrcTF16() || isLiteralImm(MVT::f16); } 618 619 bool isVSrcTF16_Lo128() const { 620 return isVCSrcTF16_Lo128() || isLiteralImm(MVT::f16); 621 } 622 623 bool isVSrcFake16F16_Lo128() const { 624 return isVCSrcFake16F16_Lo128() || isLiteralImm(MVT::f16); 625 } 626 627 bool isVSrcF16() const { 628 return isVCSrcF16() || isLiteralImm(MVT::f16); 629 } 630 631 bool isVSrcV2F16() const { 632 return isVSrcF16() || isLiteralImm(MVT::v2f16); 633 } 634 635 bool isVISrcB32() const { 636 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32); 637 } 638 639 bool isVISrcB16() const { 640 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16); 641 } 642 643 bool isVISrcV2B16() const { 644 return isVISrcB16(); 645 } 646 647 bool isVISrcF32() const { 648 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32); 649 } 650 651 bool isVISrcF16() const { 652 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16); 653 } 654 655 bool isVISrcV2F16() const { 656 return isVISrcF16() || isVISrcB32(); 657 } 658 659 bool isVISrc_64B64() const { 660 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i64); 661 } 662 663 bool isVISrc_64F64() const { 664 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f64); 665 } 666 667 bool isVISrc_64V2FP32() const { 668 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::f32); 669 } 670 671 bool isVISrc_64V2INT32() const { 672 return isRegOrInlineNoMods(AMDGPU::VReg_64RegClassID, MVT::i32); 673 } 674 675 bool isVISrc_256B64() const { 676 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i64); 677 } 678 679 bool isVISrc_256F64() const { 680 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f64); 681 } 682 683 bool isVISrc_128B16() const { 684 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i16); 685 } 686 687 bool isVISrc_128V2B16() const { 688 return isVISrc_128B16(); 689 } 690 691 bool isVISrc_128B32() const { 692 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::i32); 693 } 694 695 bool isVISrc_128F32() const { 696 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f32); 697 } 698 699 bool isVISrc_256V2FP32() const { 700 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::f32); 701 } 702 703 bool isVISrc_256V2INT32() const { 704 return isRegOrInlineNoMods(AMDGPU::VReg_256RegClassID, MVT::i32); 705 } 706 707 bool isVISrc_512B32() const { 708 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i32); 709 } 710 711 bool isVISrc_512B16() const { 712 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::i16); 713 } 714 715 bool isVISrc_512V2B16() const { 716 return isVISrc_512B16(); 717 } 718 719 bool isVISrc_512F32() const { 720 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f32); 721 } 722 723 bool isVISrc_512F16() const { 724 return isRegOrInlineNoMods(AMDGPU::VReg_512RegClassID, MVT::f16); 725 } 726 727 bool isVISrc_512V2F16() const { 728 return isVISrc_512F16() || isVISrc_512B32(); 729 } 730 731 bool isVISrc_1024B32() const { 732 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i32); 733 } 734 735 bool isVISrc_1024B16() const { 736 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::i16); 737 } 738 739 bool isVISrc_1024V2B16() const { 740 return isVISrc_1024B16(); 741 } 742 743 bool isVISrc_1024F32() const { 744 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f32); 745 } 746 747 bool isVISrc_1024F16() const { 748 return isRegOrInlineNoMods(AMDGPU::VReg_1024RegClassID, MVT::f16); 749 } 750 751 bool isVISrc_1024V2F16() const { 752 return isVISrc_1024F16() || isVISrc_1024B32(); 753 } 754 755 bool isAISrcB32() const { 756 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32); 757 } 758 759 bool isAISrcB16() const { 760 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16); 761 } 762 763 bool isAISrcV2B16() const { 764 return isAISrcB16(); 765 } 766 767 bool isAISrcF32() const { 768 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32); 769 } 770 771 bool isAISrcF16() const { 772 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16); 773 } 774 775 bool isAISrcV2F16() const { 776 return isAISrcF16() || isAISrcB32(); 777 } 778 779 bool isAISrc_64B64() const { 780 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::i64); 781 } 782 783 bool isAISrc_64F64() const { 784 return isRegOrInlineNoMods(AMDGPU::AReg_64RegClassID, MVT::f64); 785 } 786 787 bool isAISrc_128B32() const { 788 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32); 789 } 790 791 bool isAISrc_128B16() const { 792 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16); 793 } 794 795 bool isAISrc_128V2B16() const { 796 return isAISrc_128B16(); 797 } 798 799 bool isAISrc_128F32() const { 800 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32); 801 } 802 803 bool isAISrc_128F16() const { 804 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16); 805 } 806 807 bool isAISrc_128V2F16() const { 808 return isAISrc_128F16() || isAISrc_128B32(); 809 } 810 811 bool isVISrc_128F16() const { 812 return isRegOrInlineNoMods(AMDGPU::VReg_128RegClassID, MVT::f16); 813 } 814 815 bool isVISrc_128V2F16() const { 816 return isVISrc_128F16() || isVISrc_128B32(); 817 } 818 819 bool isAISrc_256B64() const { 820 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::i64); 821 } 822 823 bool isAISrc_256F64() const { 824 return isRegOrInlineNoMods(AMDGPU::AReg_256RegClassID, MVT::f64); 825 } 826 827 bool isAISrc_512B32() const { 828 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32); 829 } 830 831 bool isAISrc_512B16() const { 832 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16); 833 } 834 835 bool isAISrc_512V2B16() const { 836 return isAISrc_512B16(); 837 } 838 839 bool isAISrc_512F32() const { 840 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32); 841 } 842 843 bool isAISrc_512F16() const { 844 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16); 845 } 846 847 bool isAISrc_512V2F16() const { 848 return isAISrc_512F16() || isAISrc_512B32(); 849 } 850 851 bool isAISrc_1024B32() const { 852 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32); 853 } 854 855 bool isAISrc_1024B16() const { 856 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16); 857 } 858 859 bool isAISrc_1024V2B16() const { 860 return isAISrc_1024B16(); 861 } 862 863 bool isAISrc_1024F32() const { 864 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32); 865 } 866 867 bool isAISrc_1024F16() const { 868 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16); 869 } 870 871 bool isAISrc_1024V2F16() const { 872 return isAISrc_1024F16() || isAISrc_1024B32(); 873 } 874 875 bool isKImmFP32() const { 876 return isLiteralImm(MVT::f32); 877 } 878 879 bool isKImmFP16() const { 880 return isLiteralImm(MVT::f16); 881 } 882 883 bool isMem() const override { 884 return false; 885 } 886 887 bool isExpr() const { 888 return Kind == Expression; 889 } 890 891 bool isSOPPBrTarget() const { return isExpr() || isImm(); } 892 893 bool isSWaitCnt() const; 894 bool isDepCtr() const; 895 bool isSDelayALU() const; 896 bool isHwreg() const; 897 bool isSendMsg() const; 898 bool isSplitBarrier() const; 899 bool isSwizzle() const; 900 bool isSMRDOffset8() const; 901 bool isSMEMOffset() const; 902 bool isSMRDLiteralOffset() const; 903 bool isDPP8() const; 904 bool isDPPCtrl() const; 905 bool isBLGP() const; 906 bool isCBSZ() const; 907 bool isABID() const; 908 bool isGPRIdxMode() const; 909 bool isS16Imm() const; 910 bool isU16Imm() const; 911 bool isEndpgm() const; 912 bool isWaitVDST() const; 913 bool isWaitEXP() const; 914 bool isWaitVAVDst() const; 915 bool isWaitVMVSrc() const; 916 917 auto getPredicate(std::function<bool(const AMDGPUOperand &Op)> P) const { 918 return std::bind(P, *this); 919 } 920 921 StringRef getToken() const { 922 assert(isToken()); 923 return StringRef(Tok.Data, Tok.Length); 924 } 925 926 int64_t getImm() const { 927 assert(isImm()); 928 return Imm.Val; 929 } 930 931 void setImm(int64_t Val) { 932 assert(isImm()); 933 Imm.Val = Val; 934 } 935 936 ImmTy getImmTy() const { 937 assert(isImm()); 938 return Imm.Type; 939 } 940 941 unsigned getReg() const override { 942 assert(isRegKind()); 943 return Reg.RegNo; 944 } 945 946 SMLoc getStartLoc() const override { 947 return StartLoc; 948 } 949 950 SMLoc getEndLoc() const override { 951 return EndLoc; 952 } 953 954 SMRange getLocRange() const { 955 return SMRange(StartLoc, EndLoc); 956 } 957 958 Modifiers getModifiers() const { 959 assert(isRegKind() || isImmTy(ImmTyNone)); 960 return isRegKind() ? Reg.Mods : Imm.Mods; 961 } 962 963 void setModifiers(Modifiers Mods) { 964 assert(isRegKind() || isImmTy(ImmTyNone)); 965 if (isRegKind()) 966 Reg.Mods = Mods; 967 else 968 Imm.Mods = Mods; 969 } 970 971 bool hasModifiers() const { 972 return getModifiers().hasModifiers(); 973 } 974 975 bool hasFPModifiers() const { 976 return getModifiers().hasFPModifiers(); 977 } 978 979 bool hasIntModifiers() const { 980 return getModifiers().hasIntModifiers(); 981 } 982 983 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const; 984 985 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const; 986 987 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const; 988 989 void addRegOperands(MCInst &Inst, unsigned N) const; 990 991 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 992 if (isRegKind()) 993 addRegOperands(Inst, N); 994 else 995 addImmOperands(Inst, N); 996 } 997 998 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 999 Modifiers Mods = getModifiers(); 1000 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 1001 if (isRegKind()) { 1002 addRegOperands(Inst, N); 1003 } else { 1004 addImmOperands(Inst, N, false); 1005 } 1006 } 1007 1008 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 1009 assert(!hasIntModifiers()); 1010 addRegOrImmWithInputModsOperands(Inst, N); 1011 } 1012 1013 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 1014 assert(!hasFPModifiers()); 1015 addRegOrImmWithInputModsOperands(Inst, N); 1016 } 1017 1018 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 1019 Modifiers Mods = getModifiers(); 1020 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 1021 assert(isRegKind()); 1022 addRegOperands(Inst, N); 1023 } 1024 1025 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 1026 assert(!hasIntModifiers()); 1027 addRegWithInputModsOperands(Inst, N); 1028 } 1029 1030 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 1031 assert(!hasFPModifiers()); 1032 addRegWithInputModsOperands(Inst, N); 1033 } 1034 1035 static void printImmTy(raw_ostream& OS, ImmTy Type) { 1036 // clang-format off 1037 switch (Type) { 1038 case ImmTyNone: OS << "None"; break; 1039 case ImmTyGDS: OS << "GDS"; break; 1040 case ImmTyLDS: OS << "LDS"; break; 1041 case ImmTyOffen: OS << "Offen"; break; 1042 case ImmTyIdxen: OS << "Idxen"; break; 1043 case ImmTyAddr64: OS << "Addr64"; break; 1044 case ImmTyOffset: OS << "Offset"; break; 1045 case ImmTyInstOffset: OS << "InstOffset"; break; 1046 case ImmTyOffset0: OS << "Offset0"; break; 1047 case ImmTyOffset1: OS << "Offset1"; break; 1048 case ImmTySMEMOffsetMod: OS << "SMEMOffsetMod"; break; 1049 case ImmTyCPol: OS << "CPol"; break; 1050 case ImmTyTFE: OS << "TFE"; break; 1051 case ImmTyD16: OS << "D16"; break; 1052 case ImmTyFORMAT: OS << "FORMAT"; break; 1053 case ImmTyClampSI: OS << "ClampSI"; break; 1054 case ImmTyOModSI: OS << "OModSI"; break; 1055 case ImmTyDPP8: OS << "DPP8"; break; 1056 case ImmTyDppCtrl: OS << "DppCtrl"; break; 1057 case ImmTyDppRowMask: OS << "DppRowMask"; break; 1058 case ImmTyDppBankMask: OS << "DppBankMask"; break; 1059 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break; 1060 case ImmTyDppFI: OS << "DppFI"; break; 1061 case ImmTySDWADstSel: OS << "SDWADstSel"; break; 1062 case ImmTySDWASrc0Sel: OS << "SDWASrc0Sel"; break; 1063 case ImmTySDWASrc1Sel: OS << "SDWASrc1Sel"; break; 1064 case ImmTySDWADstUnused: OS << "SDWADstUnused"; break; 1065 case ImmTyDMask: OS << "DMask"; break; 1066 case ImmTyDim: OS << "Dim"; break; 1067 case ImmTyUNorm: OS << "UNorm"; break; 1068 case ImmTyDA: OS << "DA"; break; 1069 case ImmTyR128A16: OS << "R128A16"; break; 1070 case ImmTyA16: OS << "A16"; break; 1071 case ImmTyLWE: OS << "LWE"; break; 1072 case ImmTyOff: OS << "Off"; break; 1073 case ImmTyExpTgt: OS << "ExpTgt"; break; 1074 case ImmTyExpCompr: OS << "ExpCompr"; break; 1075 case ImmTyExpVM: OS << "ExpVM"; break; 1076 case ImmTyHwreg: OS << "Hwreg"; break; 1077 case ImmTySendMsg: OS << "SendMsg"; break; 1078 case ImmTyInterpSlot: OS << "InterpSlot"; break; 1079 case ImmTyInterpAttr: OS << "InterpAttr"; break; 1080 case ImmTyInterpAttrChan: OS << "InterpAttrChan"; break; 1081 case ImmTyOpSel: OS << "OpSel"; break; 1082 case ImmTyOpSelHi: OS << "OpSelHi"; break; 1083 case ImmTyNegLo: OS << "NegLo"; break; 1084 case ImmTyNegHi: OS << "NegHi"; break; 1085 case ImmTySwizzle: OS << "Swizzle"; break; 1086 case ImmTyGprIdxMode: OS << "GprIdxMode"; break; 1087 case ImmTyHigh: OS << "High"; break; 1088 case ImmTyBLGP: OS << "BLGP"; break; 1089 case ImmTyCBSZ: OS << "CBSZ"; break; 1090 case ImmTyABID: OS << "ABID"; break; 1091 case ImmTyEndpgm: OS << "Endpgm"; break; 1092 case ImmTyWaitVDST: OS << "WaitVDST"; break; 1093 case ImmTyWaitEXP: OS << "WaitEXP"; break; 1094 case ImmTyWaitVAVDst: OS << "WaitVAVDst"; break; 1095 case ImmTyWaitVMVSrc: OS << "WaitVMVSrc"; break; 1096 } 1097 // clang-format on 1098 } 1099 1100 void print(raw_ostream &OS) const override { 1101 switch (Kind) { 1102 case Register: 1103 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>'; 1104 break; 1105 case Immediate: 1106 OS << '<' << getImm(); 1107 if (getImmTy() != ImmTyNone) { 1108 OS << " type: "; printImmTy(OS, getImmTy()); 1109 } 1110 OS << " mods: " << Imm.Mods << '>'; 1111 break; 1112 case Token: 1113 OS << '\'' << getToken() << '\''; 1114 break; 1115 case Expression: 1116 OS << "<expr " << *Expr << '>'; 1117 break; 1118 } 1119 } 1120 1121 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser, 1122 int64_t Val, SMLoc Loc, 1123 ImmTy Type = ImmTyNone, 1124 bool IsFPImm = false) { 1125 auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser); 1126 Op->Imm.Val = Val; 1127 Op->Imm.IsFPImm = IsFPImm; 1128 Op->Imm.Kind = ImmKindTyNone; 1129 Op->Imm.Type = Type; 1130 Op->Imm.Mods = Modifiers(); 1131 Op->StartLoc = Loc; 1132 Op->EndLoc = Loc; 1133 return Op; 1134 } 1135 1136 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser, 1137 StringRef Str, SMLoc Loc, 1138 bool HasExplicitEncodingSize = true) { 1139 auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser); 1140 Res->Tok.Data = Str.data(); 1141 Res->Tok.Length = Str.size(); 1142 Res->StartLoc = Loc; 1143 Res->EndLoc = Loc; 1144 return Res; 1145 } 1146 1147 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser, 1148 unsigned RegNo, SMLoc S, 1149 SMLoc E) { 1150 auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser); 1151 Op->Reg.RegNo = RegNo; 1152 Op->Reg.Mods = Modifiers(); 1153 Op->StartLoc = S; 1154 Op->EndLoc = E; 1155 return Op; 1156 } 1157 1158 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser, 1159 const class MCExpr *Expr, SMLoc S) { 1160 auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser); 1161 Op->Expr = Expr; 1162 Op->StartLoc = S; 1163 Op->EndLoc = S; 1164 return Op; 1165 } 1166 }; 1167 1168 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { 1169 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; 1170 return OS; 1171 } 1172 1173 //===----------------------------------------------------------------------===// 1174 // AsmParser 1175 //===----------------------------------------------------------------------===// 1176 1177 // Holds info related to the current kernel, e.g. count of SGPRs used. 1178 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next 1179 // .amdgpu_hsa_kernel or at EOF. 1180 class KernelScopeInfo { 1181 int SgprIndexUnusedMin = -1; 1182 int VgprIndexUnusedMin = -1; 1183 int AgprIndexUnusedMin = -1; 1184 MCContext *Ctx = nullptr; 1185 MCSubtargetInfo const *MSTI = nullptr; 1186 1187 void usesSgprAt(int i) { 1188 if (i >= SgprIndexUnusedMin) { 1189 SgprIndexUnusedMin = ++i; 1190 if (Ctx) { 1191 MCSymbol* const Sym = 1192 Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count")); 1193 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx)); 1194 } 1195 } 1196 } 1197 1198 void usesVgprAt(int i) { 1199 if (i >= VgprIndexUnusedMin) { 1200 VgprIndexUnusedMin = ++i; 1201 if (Ctx) { 1202 MCSymbol* const Sym = 1203 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 1204 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin, 1205 VgprIndexUnusedMin); 1206 Sym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx)); 1207 } 1208 } 1209 } 1210 1211 void usesAgprAt(int i) { 1212 // Instruction will error in AMDGPUAsmParser::MatchAndEmitInstruction 1213 if (!hasMAIInsts(*MSTI)) 1214 return; 1215 1216 if (i >= AgprIndexUnusedMin) { 1217 AgprIndexUnusedMin = ++i; 1218 if (Ctx) { 1219 MCSymbol* const Sym = 1220 Ctx->getOrCreateSymbol(Twine(".kernel.agpr_count")); 1221 Sym->setVariableValue(MCConstantExpr::create(AgprIndexUnusedMin, *Ctx)); 1222 1223 // Also update vgpr_count (dependent on agpr_count for gfx908/gfx90a) 1224 MCSymbol* const vSym = 1225 Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 1226 int totalVGPR = getTotalNumVGPRs(isGFX90A(*MSTI), AgprIndexUnusedMin, 1227 VgprIndexUnusedMin); 1228 vSym->setVariableValue(MCConstantExpr::create(totalVGPR, *Ctx)); 1229 } 1230 } 1231 } 1232 1233 public: 1234 KernelScopeInfo() = default; 1235 1236 void initialize(MCContext &Context) { 1237 Ctx = &Context; 1238 MSTI = Ctx->getSubtargetInfo(); 1239 1240 usesSgprAt(SgprIndexUnusedMin = -1); 1241 usesVgprAt(VgprIndexUnusedMin = -1); 1242 if (hasMAIInsts(*MSTI)) { 1243 usesAgprAt(AgprIndexUnusedMin = -1); 1244 } 1245 } 1246 1247 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, 1248 unsigned RegWidth) { 1249 switch (RegKind) { 1250 case IS_SGPR: 1251 usesSgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1); 1252 break; 1253 case IS_AGPR: 1254 usesAgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1); 1255 break; 1256 case IS_VGPR: 1257 usesVgprAt(DwordRegIndex + divideCeil(RegWidth, 32) - 1); 1258 break; 1259 default: 1260 break; 1261 } 1262 } 1263 }; 1264 1265 class AMDGPUAsmParser : public MCTargetAsmParser { 1266 MCAsmParser &Parser; 1267 1268 unsigned ForcedEncodingSize = 0; 1269 bool ForcedDPP = false; 1270 bool ForcedSDWA = false; 1271 KernelScopeInfo KernelScope; 1272 1273 /// @name Auto-generated Match Functions 1274 /// { 1275 1276 #define GET_ASSEMBLER_HEADER 1277 #include "AMDGPUGenAsmMatcher.inc" 1278 1279 /// } 1280 1281 private: 1282 bool ParseAsAbsoluteExpression(uint32_t &Ret); 1283 bool OutOfRangeError(SMRange Range); 1284 /// Calculate VGPR/SGPR blocks required for given target, reserved 1285 /// registers, and user-specified NextFreeXGPR values. 1286 /// 1287 /// \param Features [in] Target features, used for bug corrections. 1288 /// \param VCCUsed [in] Whether VCC special SGPR is reserved. 1289 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved. 1290 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved. 1291 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel 1292 /// descriptor field, if valid. 1293 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one. 1294 /// \param VGPRRange [in] Token range, used for VGPR diagnostics. 1295 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one. 1296 /// \param SGPRRange [in] Token range, used for SGPR diagnostics. 1297 /// \param VGPRBlocks [out] Result VGPR block count. 1298 /// \param SGPRBlocks [out] Result SGPR block count. 1299 bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed, 1300 bool FlatScrUsed, bool XNACKUsed, 1301 std::optional<bool> EnableWavefrontSize32, 1302 unsigned NextFreeVGPR, SMRange VGPRRange, 1303 unsigned NextFreeSGPR, SMRange SGPRRange, 1304 unsigned &VGPRBlocks, unsigned &SGPRBlocks); 1305 bool ParseDirectiveAMDGCNTarget(); 1306 bool ParseDirectiveAMDHSACodeObjectVersion(); 1307 bool ParseDirectiveAMDHSAKernel(); 1308 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 1309 bool ParseDirectiveAMDKernelCodeT(); 1310 // TODO: Possibly make subtargetHasRegister const. 1311 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo); 1312 bool ParseDirectiveAMDGPUHsaKernel(); 1313 1314 bool ParseDirectiveISAVersion(); 1315 bool ParseDirectiveHSAMetadata(); 1316 bool ParseDirectivePALMetadataBegin(); 1317 bool ParseDirectivePALMetadata(); 1318 bool ParseDirectiveAMDGPULDS(); 1319 1320 /// Common code to parse out a block of text (typically YAML) between start and 1321 /// end directives. 1322 bool ParseToEndDirective(const char *AssemblerDirectiveBegin, 1323 const char *AssemblerDirectiveEnd, 1324 std::string &CollectString); 1325 1326 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, 1327 RegisterKind RegKind, unsigned Reg1, SMLoc Loc); 1328 bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 1329 unsigned &RegNum, unsigned &RegWidth, 1330 bool RestoreOnFailure = false); 1331 bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 1332 unsigned &RegNum, unsigned &RegWidth, 1333 SmallVectorImpl<AsmToken> &Tokens); 1334 unsigned ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum, 1335 unsigned &RegWidth, 1336 SmallVectorImpl<AsmToken> &Tokens); 1337 unsigned ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum, 1338 unsigned &RegWidth, 1339 SmallVectorImpl<AsmToken> &Tokens); 1340 unsigned ParseRegList(RegisterKind &RegKind, unsigned &RegNum, 1341 unsigned &RegWidth, SmallVectorImpl<AsmToken> &Tokens); 1342 bool ParseRegRange(unsigned& Num, unsigned& Width); 1343 unsigned getRegularReg(RegisterKind RegKind, unsigned RegNum, unsigned SubReg, 1344 unsigned RegWidth, SMLoc Loc); 1345 1346 bool isRegister(); 1347 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const; 1348 std::optional<StringRef> getGprCountSymbolName(RegisterKind RegKind); 1349 void initializeGprCountSymbol(RegisterKind RegKind); 1350 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex, 1351 unsigned RegWidth); 1352 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, 1353 bool IsAtomic); 1354 1355 public: 1356 enum AMDGPUMatchResultTy { 1357 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 1358 }; 1359 enum OperandMode { 1360 OperandMode_Default, 1361 OperandMode_NSA, 1362 }; 1363 1364 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>; 1365 1366 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 1367 const MCInstrInfo &MII, 1368 const MCTargetOptions &Options) 1369 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) { 1370 MCAsmParserExtension::Initialize(Parser); 1371 1372 if (getFeatureBits().none()) { 1373 // Set default features. 1374 copySTI().ToggleFeature("southern-islands"); 1375 } 1376 1377 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits())); 1378 1379 { 1380 // TODO: make those pre-defined variables read-only. 1381 // Currently there is none suitable machinery in the core llvm-mc for this. 1382 // MCSymbol::isRedefinable is intended for another purpose, and 1383 // AsmParser::parseDirectiveSet() cannot be specialized for specific target. 1384 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 1385 MCContext &Ctx = getContext(); 1386 if (ISA.Major >= 6 && isHsaAbi(getSTI())) { 1387 MCSymbol *Sym = 1388 Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number")); 1389 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1390 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor")); 1391 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1392 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping")); 1393 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1394 } else { 1395 MCSymbol *Sym = 1396 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major")); 1397 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1398 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor")); 1399 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1400 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping")); 1401 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1402 } 1403 if (ISA.Major >= 6 && isHsaAbi(getSTI())) { 1404 initializeGprCountSymbol(IS_VGPR); 1405 initializeGprCountSymbol(IS_SGPR); 1406 } else 1407 KernelScope.initialize(getContext()); 1408 } 1409 } 1410 1411 bool hasMIMG_R128() const { 1412 return AMDGPU::hasMIMG_R128(getSTI()); 1413 } 1414 1415 bool hasPackedD16() const { 1416 return AMDGPU::hasPackedD16(getSTI()); 1417 } 1418 1419 bool hasA16() const { return AMDGPU::hasA16(getSTI()); } 1420 1421 bool hasG16() const { return AMDGPU::hasG16(getSTI()); } 1422 1423 bool hasGDS() const { return AMDGPU::hasGDS(getSTI()); } 1424 1425 bool isSI() const { 1426 return AMDGPU::isSI(getSTI()); 1427 } 1428 1429 bool isCI() const { 1430 return AMDGPU::isCI(getSTI()); 1431 } 1432 1433 bool isVI() const { 1434 return AMDGPU::isVI(getSTI()); 1435 } 1436 1437 bool isGFX9() const { 1438 return AMDGPU::isGFX9(getSTI()); 1439 } 1440 1441 // TODO: isGFX90A is also true for GFX940. We need to clean it. 1442 bool isGFX90A() const { 1443 return AMDGPU::isGFX90A(getSTI()); 1444 } 1445 1446 bool isGFX940() const { 1447 return AMDGPU::isGFX940(getSTI()); 1448 } 1449 1450 bool isGFX9Plus() const { 1451 return AMDGPU::isGFX9Plus(getSTI()); 1452 } 1453 1454 bool isGFX10() const { 1455 return AMDGPU::isGFX10(getSTI()); 1456 } 1457 1458 bool isGFX10Plus() const { return AMDGPU::isGFX10Plus(getSTI()); } 1459 1460 bool isGFX11() const { 1461 return AMDGPU::isGFX11(getSTI()); 1462 } 1463 1464 bool isGFX11Plus() const { 1465 return AMDGPU::isGFX11Plus(getSTI()); 1466 } 1467 1468 bool isGFX12() const { return AMDGPU::isGFX12(getSTI()); } 1469 1470 bool isGFX12Plus() const { return AMDGPU::isGFX12Plus(getSTI()); } 1471 1472 bool isGFX10_AEncoding() const { return AMDGPU::isGFX10_AEncoding(getSTI()); } 1473 1474 bool isGFX10_BEncoding() const { 1475 return AMDGPU::isGFX10_BEncoding(getSTI()); 1476 } 1477 1478 bool hasInv2PiInlineImm() const { 1479 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; 1480 } 1481 1482 bool hasFlatOffsets() const { 1483 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets]; 1484 } 1485 1486 bool hasArchitectedFlatScratch() const { 1487 return getFeatureBits()[AMDGPU::FeatureArchitectedFlatScratch]; 1488 } 1489 1490 bool hasSGPR102_SGPR103() const { 1491 return !isVI() && !isGFX9(); 1492 } 1493 1494 bool hasSGPR104_SGPR105() const { return isGFX10Plus(); } 1495 1496 bool hasIntClamp() const { 1497 return getFeatureBits()[AMDGPU::FeatureIntClamp]; 1498 } 1499 1500 bool hasPartialNSAEncoding() const { 1501 return getFeatureBits()[AMDGPU::FeaturePartialNSAEncoding]; 1502 } 1503 1504 unsigned getNSAMaxSize(bool HasSampler = false) const { 1505 return AMDGPU::getNSAMaxSize(getSTI(), HasSampler); 1506 } 1507 1508 unsigned getMaxNumUserSGPRs() const { 1509 return AMDGPU::getMaxNumUserSGPRs(getSTI()); 1510 } 1511 1512 bool hasKernargPreload() const { return AMDGPU::hasKernargPreload(getSTI()); } 1513 1514 AMDGPUTargetStreamer &getTargetStreamer() { 1515 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 1516 return static_cast<AMDGPUTargetStreamer &>(TS); 1517 } 1518 1519 const MCRegisterInfo *getMRI() const { 1520 // We need this const_cast because for some reason getContext() is not const 1521 // in MCAsmParser. 1522 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo(); 1523 } 1524 1525 const MCInstrInfo *getMII() const { 1526 return &MII; 1527 } 1528 1529 const FeatureBitset &getFeatureBits() const { 1530 return getSTI().getFeatureBits(); 1531 } 1532 1533 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; } 1534 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; } 1535 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; } 1536 1537 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; } 1538 bool isForcedVOP3() const { return ForcedEncodingSize == 64; } 1539 bool isForcedDPP() const { return ForcedDPP; } 1540 bool isForcedSDWA() const { return ForcedSDWA; } 1541 ArrayRef<unsigned> getMatchedVariants() const; 1542 StringRef getMatchedVariantName() const; 1543 1544 std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false); 1545 bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, 1546 bool RestoreOnFailure); 1547 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 1548 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 1549 SMLoc &EndLoc) override; 1550 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 1551 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 1552 unsigned Kind) override; 1553 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1554 OperandVector &Operands, MCStreamer &Out, 1555 uint64_t &ErrorInfo, 1556 bool MatchingInlineAsm) override; 1557 bool ParseDirective(AsmToken DirectiveID) override; 1558 ParseStatus parseOperand(OperandVector &Operands, StringRef Mnemonic, 1559 OperandMode Mode = OperandMode_Default); 1560 StringRef parseMnemonicSuffix(StringRef Name); 1561 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 1562 SMLoc NameLoc, OperandVector &Operands) override; 1563 //bool ProcessInstruction(MCInst &Inst); 1564 1565 ParseStatus parseTokenOp(StringRef Name, OperandVector &Operands); 1566 1567 ParseStatus parseIntWithPrefix(const char *Prefix, int64_t &Int); 1568 1569 ParseStatus 1570 parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1571 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1572 std::function<bool(int64_t &)> ConvertResult = nullptr); 1573 1574 ParseStatus parseOperandArrayWithPrefix( 1575 const char *Prefix, OperandVector &Operands, 1576 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1577 bool (*ConvertResult)(int64_t &) = nullptr); 1578 1579 ParseStatus 1580 parseNamedBit(StringRef Name, OperandVector &Operands, 1581 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone); 1582 unsigned getCPolKind(StringRef Id, StringRef Mnemo, bool &Disabling) const; 1583 ParseStatus parseCPol(OperandVector &Operands); 1584 ParseStatus parseScope(OperandVector &Operands, int64_t &Scope); 1585 ParseStatus parseTH(OperandVector &Operands, int64_t &TH); 1586 ParseStatus parseStringWithPrefix(StringRef Prefix, StringRef &Value, 1587 SMLoc &StringLoc); 1588 1589 bool isModifier(); 1590 bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1591 bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1592 bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1593 bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const; 1594 bool parseSP3NegModifier(); 1595 ParseStatus parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false, 1596 bool HasLit = false); 1597 ParseStatus parseReg(OperandVector &Operands); 1598 ParseStatus parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false, 1599 bool HasLit = false); 1600 ParseStatus parseRegOrImmWithFPInputMods(OperandVector &Operands, 1601 bool AllowImm = true); 1602 ParseStatus parseRegOrImmWithIntInputMods(OperandVector &Operands, 1603 bool AllowImm = true); 1604 ParseStatus parseRegWithFPInputMods(OperandVector &Operands); 1605 ParseStatus parseRegWithIntInputMods(OperandVector &Operands); 1606 ParseStatus parseVReg32OrOff(OperandVector &Operands); 1607 ParseStatus parseDfmtNfmt(int64_t &Format); 1608 ParseStatus parseUfmt(int64_t &Format); 1609 ParseStatus parseSymbolicSplitFormat(StringRef FormatStr, SMLoc Loc, 1610 int64_t &Format); 1611 ParseStatus parseSymbolicUnifiedFormat(StringRef FormatStr, SMLoc Loc, 1612 int64_t &Format); 1613 ParseStatus parseFORMAT(OperandVector &Operands); 1614 ParseStatus parseSymbolicOrNumericFormat(int64_t &Format); 1615 ParseStatus parseNumericFormat(int64_t &Format); 1616 ParseStatus parseFlatOffset(OperandVector &Operands); 1617 ParseStatus parseR128A16(OperandVector &Operands); 1618 ParseStatus parseBLGP(OperandVector &Operands); 1619 bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val); 1620 bool matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt, StringRef FormatStr, SMLoc Loc); 1621 1622 void cvtExp(MCInst &Inst, const OperandVector &Operands); 1623 1624 bool parseCnt(int64_t &IntVal); 1625 ParseStatus parseSWaitCnt(OperandVector &Operands); 1626 1627 bool parseDepCtr(int64_t &IntVal, unsigned &Mask); 1628 void depCtrError(SMLoc Loc, int ErrorId, StringRef DepCtrName); 1629 ParseStatus parseDepCtr(OperandVector &Operands); 1630 1631 bool parseDelay(int64_t &Delay); 1632 ParseStatus parseSDelayALU(OperandVector &Operands); 1633 1634 ParseStatus parseHwreg(OperandVector &Operands); 1635 1636 private: 1637 struct OperandInfoTy { 1638 SMLoc Loc; 1639 int64_t Id; 1640 bool IsSymbolic = false; 1641 bool IsDefined = false; 1642 1643 OperandInfoTy(int64_t Id_) : Id(Id_) {} 1644 }; 1645 1646 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream); 1647 bool validateSendMsg(const OperandInfoTy &Msg, 1648 const OperandInfoTy &Op, 1649 const OperandInfoTy &Stream); 1650 1651 bool parseHwregBody(OperandInfoTy &HwReg, 1652 OperandInfoTy &Offset, 1653 OperandInfoTy &Width); 1654 bool validateHwreg(const OperandInfoTy &HwReg, 1655 const OperandInfoTy &Offset, 1656 const OperandInfoTy &Width); 1657 1658 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const; 1659 SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const; 1660 SMLoc getBLGPLoc(const OperandVector &Operands) const; 1661 1662 SMLoc getOperandLoc(std::function<bool(const AMDGPUOperand&)> Test, 1663 const OperandVector &Operands) const; 1664 SMLoc getImmLoc(AMDGPUOperand::ImmTy Type, const OperandVector &Operands) const; 1665 SMLoc getRegLoc(unsigned Reg, const OperandVector &Operands) const; 1666 SMLoc getLitLoc(const OperandVector &Operands, 1667 bool SearchMandatoryLiterals = false) const; 1668 SMLoc getMandatoryLitLoc(const OperandVector &Operands) const; 1669 SMLoc getConstLoc(const OperandVector &Operands) const; 1670 SMLoc getInstLoc(const OperandVector &Operands) const; 1671 1672 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands); 1673 bool validateOffset(const MCInst &Inst, const OperandVector &Operands); 1674 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands); 1675 bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands); 1676 bool validateSOPLiteral(const MCInst &Inst) const; 1677 bool validateConstantBusLimitations(const MCInst &Inst, const OperandVector &Operands); 1678 bool validateVOPDRegBankConstraints(const MCInst &Inst, 1679 const OperandVector &Operands); 1680 bool validateIntClampSupported(const MCInst &Inst); 1681 bool validateMIMGAtomicDMask(const MCInst &Inst); 1682 bool validateMIMGGatherDMask(const MCInst &Inst); 1683 bool validateMovrels(const MCInst &Inst, const OperandVector &Operands); 1684 bool validateMIMGDataSize(const MCInst &Inst, const SMLoc &IDLoc); 1685 bool validateMIMGAddrSize(const MCInst &Inst, const SMLoc &IDLoc); 1686 bool validateMIMGD16(const MCInst &Inst); 1687 bool validateMIMGMSAA(const MCInst &Inst); 1688 bool validateOpSel(const MCInst &Inst); 1689 bool validateNeg(const MCInst &Inst, int OpName); 1690 bool validateDPP(const MCInst &Inst, const OperandVector &Operands); 1691 bool validateVccOperand(unsigned Reg) const; 1692 bool validateVOPLiteral(const MCInst &Inst, const OperandVector &Operands); 1693 bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands); 1694 bool validateMAISrc2(const MCInst &Inst, const OperandVector &Operands); 1695 bool validateMFMA(const MCInst &Inst, const OperandVector &Operands); 1696 bool validateAGPRLdSt(const MCInst &Inst) const; 1697 bool validateVGPRAlign(const MCInst &Inst) const; 1698 bool validateBLGP(const MCInst &Inst, const OperandVector &Operands); 1699 bool validateDS(const MCInst &Inst, const OperandVector &Operands); 1700 bool validateGWS(const MCInst &Inst, const OperandVector &Operands); 1701 bool validateDivScale(const MCInst &Inst); 1702 bool validateWaitCnt(const MCInst &Inst, const OperandVector &Operands); 1703 bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands, 1704 const SMLoc &IDLoc); 1705 bool validateTHAndScopeBits(const MCInst &Inst, const OperandVector &Operands, 1706 const unsigned CPol); 1707 bool validateExeczVcczOperands(const OperandVector &Operands); 1708 bool validateTFE(const MCInst &Inst, const OperandVector &Operands); 1709 std::optional<StringRef> validateLdsDirect(const MCInst &Inst); 1710 unsigned getConstantBusLimit(unsigned Opcode) const; 1711 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); 1712 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; 1713 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; 1714 1715 bool isSupportedMnemo(StringRef Mnemo, 1716 const FeatureBitset &FBS); 1717 bool isSupportedMnemo(StringRef Mnemo, 1718 const FeatureBitset &FBS, 1719 ArrayRef<unsigned> Variants); 1720 bool checkUnsupportedInstruction(StringRef Name, const SMLoc &IDLoc); 1721 1722 bool isId(const StringRef Id) const; 1723 bool isId(const AsmToken &Token, const StringRef Id) const; 1724 bool isToken(const AsmToken::TokenKind Kind) const; 1725 StringRef getId() const; 1726 bool trySkipId(const StringRef Id); 1727 bool trySkipId(const StringRef Pref, const StringRef Id); 1728 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind); 1729 bool trySkipToken(const AsmToken::TokenKind Kind); 1730 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg); 1731 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string"); 1732 bool parseId(StringRef &Val, const StringRef ErrMsg = ""); 1733 1734 void peekTokens(MutableArrayRef<AsmToken> Tokens); 1735 AsmToken::TokenKind getTokenKind() const; 1736 bool parseExpr(int64_t &Imm, StringRef Expected = ""); 1737 bool parseExpr(OperandVector &Operands); 1738 StringRef getTokenStr() const; 1739 AsmToken peekToken(bool ShouldSkipSpace = true); 1740 AsmToken getToken() const; 1741 SMLoc getLoc() const; 1742 void lex(); 1743 1744 public: 1745 void onBeginOfFile() override; 1746 1747 ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK); 1748 1749 ParseStatus parseExpTgt(OperandVector &Operands); 1750 ParseStatus parseSendMsg(OperandVector &Operands); 1751 ParseStatus parseInterpSlot(OperandVector &Operands); 1752 ParseStatus parseInterpAttr(OperandVector &Operands); 1753 ParseStatus parseSOPPBrTarget(OperandVector &Operands); 1754 ParseStatus parseBoolReg(OperandVector &Operands); 1755 1756 bool parseSwizzleOperand(int64_t &Op, 1757 const unsigned MinVal, 1758 const unsigned MaxVal, 1759 const StringRef ErrMsg, 1760 SMLoc &Loc); 1761 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 1762 const unsigned MinVal, 1763 const unsigned MaxVal, 1764 const StringRef ErrMsg); 1765 ParseStatus parseSwizzle(OperandVector &Operands); 1766 bool parseSwizzleOffset(int64_t &Imm); 1767 bool parseSwizzleMacro(int64_t &Imm); 1768 bool parseSwizzleQuadPerm(int64_t &Imm); 1769 bool parseSwizzleBitmaskPerm(int64_t &Imm); 1770 bool parseSwizzleBroadcast(int64_t &Imm); 1771 bool parseSwizzleSwap(int64_t &Imm); 1772 bool parseSwizzleReverse(int64_t &Imm); 1773 1774 ParseStatus parseGPRIdxMode(OperandVector &Operands); 1775 int64_t parseGPRIdxMacro(); 1776 1777 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false); } 1778 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true); } 1779 1780 ParseStatus parseOModSI(OperandVector &Operands); 1781 1782 void cvtVOP3(MCInst &Inst, const OperandVector &Operands, 1783 OptionalImmIndexMap &OptionalIdx); 1784 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands); 1785 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 1786 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands); 1787 void cvtVOPD(MCInst &Inst, const OperandVector &Operands); 1788 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands, 1789 OptionalImmIndexMap &OptionalIdx); 1790 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands, 1791 OptionalImmIndexMap &OptionalIdx); 1792 1793 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands); 1794 void cvtVINTERP(MCInst &Inst, const OperandVector &Operands); 1795 1796 bool parseDimId(unsigned &Encoding); 1797 ParseStatus parseDim(OperandVector &Operands); 1798 bool convertDppBoundCtrl(int64_t &BoundCtrl); 1799 ParseStatus parseDPP8(OperandVector &Operands); 1800 ParseStatus parseDPPCtrl(OperandVector &Operands); 1801 bool isSupportedDPPCtrl(StringRef Ctrl, const OperandVector &Operands); 1802 int64_t parseDPPCtrlSel(StringRef Ctrl); 1803 int64_t parseDPPCtrlPerm(); 1804 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false); 1805 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { 1806 cvtDPP(Inst, Operands, true); 1807 } 1808 void cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands, 1809 bool IsDPP8 = false); 1810 void cvtVOP3DPP8(MCInst &Inst, const OperandVector &Operands) { 1811 cvtVOP3DPP(Inst, Operands, true); 1812 } 1813 1814 ParseStatus parseSDWASel(OperandVector &Operands, StringRef Prefix, 1815 AMDGPUOperand::ImmTy Type); 1816 ParseStatus parseSDWADstUnused(OperandVector &Operands); 1817 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); 1818 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); 1819 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands); 1820 void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands); 1821 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); 1822 void cvtSDWA(MCInst &Inst, const OperandVector &Operands, 1823 uint64_t BasicInstType, 1824 bool SkipDstVcc = false, 1825 bool SkipSrcVcc = false); 1826 1827 ParseStatus parseEndpgm(OperandVector &Operands); 1828 1829 ParseStatus parseVOPD(OperandVector &Operands); 1830 }; 1831 1832 } // end anonymous namespace 1833 1834 // May be called with integer type with equivalent bitwidth. 1835 static const fltSemantics *getFltSemantics(unsigned Size) { 1836 switch (Size) { 1837 case 4: 1838 return &APFloat::IEEEsingle(); 1839 case 8: 1840 return &APFloat::IEEEdouble(); 1841 case 2: 1842 return &APFloat::IEEEhalf(); 1843 default: 1844 llvm_unreachable("unsupported fp type"); 1845 } 1846 } 1847 1848 static const fltSemantics *getFltSemantics(MVT VT) { 1849 return getFltSemantics(VT.getSizeInBits() / 8); 1850 } 1851 1852 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) { 1853 switch (OperandType) { 1854 case AMDGPU::OPERAND_REG_IMM_INT32: 1855 case AMDGPU::OPERAND_REG_IMM_FP32: 1856 case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED: 1857 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1858 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1859 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1860 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1861 case AMDGPU::OPERAND_REG_INLINE_C_V2FP32: 1862 case AMDGPU::OPERAND_REG_IMM_V2FP32: 1863 case AMDGPU::OPERAND_REG_INLINE_C_V2INT32: 1864 case AMDGPU::OPERAND_REG_IMM_V2INT32: 1865 case AMDGPU::OPERAND_REG_IMM_V2INT16: 1866 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1867 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1868 case AMDGPU::OPERAND_KIMM32: 1869 case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32: 1870 return &APFloat::IEEEsingle(); 1871 case AMDGPU::OPERAND_REG_IMM_INT64: 1872 case AMDGPU::OPERAND_REG_IMM_FP64: 1873 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1874 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1875 case AMDGPU::OPERAND_REG_INLINE_AC_FP64: 1876 return &APFloat::IEEEdouble(); 1877 case AMDGPU::OPERAND_REG_IMM_INT16: 1878 case AMDGPU::OPERAND_REG_IMM_FP16: 1879 case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED: 1880 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1881 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1882 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1883 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1884 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1885 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 1886 case AMDGPU::OPERAND_REG_IMM_V2FP16: 1887 case AMDGPU::OPERAND_KIMM16: 1888 return &APFloat::IEEEhalf(); 1889 default: 1890 llvm_unreachable("unsupported fp type"); 1891 } 1892 } 1893 1894 //===----------------------------------------------------------------------===// 1895 // Operand 1896 //===----------------------------------------------------------------------===// 1897 1898 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) { 1899 bool Lost; 1900 1901 // Convert literal to single precision 1902 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT), 1903 APFloat::rmNearestTiesToEven, 1904 &Lost); 1905 // We allow precision lost but not overflow or underflow 1906 if (Status != APFloat::opOK && 1907 Lost && 1908 ((Status & APFloat::opOverflow) != 0 || 1909 (Status & APFloat::opUnderflow) != 0)) { 1910 return false; 1911 } 1912 1913 return true; 1914 } 1915 1916 static bool isSafeTruncation(int64_t Val, unsigned Size) { 1917 return isUIntN(Size, Val) || isIntN(Size, Val); 1918 } 1919 1920 static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi) { 1921 if (VT.getScalarType() == MVT::i16) { 1922 // FP immediate values are broken. 1923 return isInlinableIntLiteral(Val); 1924 } 1925 1926 // f16/v2f16 operands work correctly for all values. 1927 return AMDGPU::isInlinableLiteral16(Val, HasInv2Pi); 1928 } 1929 1930 bool AMDGPUOperand::isInlinableImm(MVT type) const { 1931 1932 // This is a hack to enable named inline values like 1933 // shared_base with both 32-bit and 64-bit operands. 1934 // Note that these values are defined as 1935 // 32-bit operands only. 1936 if (isInlineValue()) { 1937 return true; 1938 } 1939 1940 if (!isImmTy(ImmTyNone)) { 1941 // Only plain immediates are inlinable (e.g. "clamp" attribute is not) 1942 return false; 1943 } 1944 // TODO: We should avoid using host float here. It would be better to 1945 // check the float bit values which is what a few other places do. 1946 // We've had bot failures before due to weird NaN support on mips hosts. 1947 1948 APInt Literal(64, Imm.Val); 1949 1950 if (Imm.IsFPImm) { // We got fp literal token 1951 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1952 return AMDGPU::isInlinableLiteral64(Imm.Val, 1953 AsmParser->hasInv2PiInlineImm()); 1954 } 1955 1956 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1957 if (!canLosslesslyConvertToFPType(FPLiteral, type)) 1958 return false; 1959 1960 if (type.getScalarSizeInBits() == 16) { 1961 return isInlineableLiteralOp16( 1962 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1963 type, AsmParser->hasInv2PiInlineImm()); 1964 } 1965 1966 // Check if single precision literal is inlinable 1967 return AMDGPU::isInlinableLiteral32( 1968 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1969 AsmParser->hasInv2PiInlineImm()); 1970 } 1971 1972 // We got int literal token. 1973 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1974 return AMDGPU::isInlinableLiteral64(Imm.Val, 1975 AsmParser->hasInv2PiInlineImm()); 1976 } 1977 1978 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) { 1979 return false; 1980 } 1981 1982 if (type.getScalarSizeInBits() == 16) { 1983 return isInlineableLiteralOp16( 1984 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), 1985 type, AsmParser->hasInv2PiInlineImm()); 1986 } 1987 1988 return AMDGPU::isInlinableLiteral32( 1989 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()), 1990 AsmParser->hasInv2PiInlineImm()); 1991 } 1992 1993 bool AMDGPUOperand::isLiteralImm(MVT type) const { 1994 // Check that this immediate can be added as literal 1995 if (!isImmTy(ImmTyNone)) { 1996 return false; 1997 } 1998 1999 if (!Imm.IsFPImm) { 2000 // We got int literal token. 2001 2002 if (type == MVT::f64 && hasFPModifiers()) { 2003 // Cannot apply fp modifiers to int literals preserving the same semantics 2004 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity, 2005 // disable these cases. 2006 return false; 2007 } 2008 2009 unsigned Size = type.getSizeInBits(); 2010 if (Size == 64) 2011 Size = 32; 2012 2013 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP 2014 // types. 2015 return isSafeTruncation(Imm.Val, Size); 2016 } 2017 2018 // We got fp literal token 2019 if (type == MVT::f64) { // Expected 64-bit fp operand 2020 // We would set low 64-bits of literal to zeroes but we accept this literals 2021 return true; 2022 } 2023 2024 if (type == MVT::i64) { // Expected 64-bit int operand 2025 // We don't allow fp literals in 64-bit integer instructions. It is 2026 // unclear how we should encode them. 2027 return false; 2028 } 2029 2030 // We allow fp literals with f16x2 operands assuming that the specified 2031 // literal goes into the lower half and the upper half is zero. We also 2032 // require that the literal may be losslessly converted to f16. 2033 // 2034 // For i16x2 operands, we assume that the specified literal is encoded as a 2035 // single-precision float. This is pretty odd, but it matches SP3 and what 2036 // happens in hardware. 2037 MVT ExpectedType = (type == MVT::v2f16) ? MVT::f16 2038 : (type == MVT::v2i16) ? MVT::f32 2039 : (type == MVT::v2f32) ? MVT::f32 2040 : type; 2041 2042 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 2043 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType); 2044 } 2045 2046 bool AMDGPUOperand::isRegClass(unsigned RCID) const { 2047 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg()); 2048 } 2049 2050 bool AMDGPUOperand::isVRegWithInputMods() const { 2051 return isRegClass(AMDGPU::VGPR_32RegClassID) || 2052 // GFX90A allows DPP on 64-bit operands. 2053 (isRegClass(AMDGPU::VReg_64RegClassID) && 2054 AsmParser->getFeatureBits()[AMDGPU::FeatureDPALU_DPP]); 2055 } 2056 2057 template <bool IsFake16> bool AMDGPUOperand::isT16VRegWithInputMods() const { 2058 return isRegClass(IsFake16 ? AMDGPU::VGPR_32_Lo128RegClassID 2059 : AMDGPU::VGPR_16_Lo128RegClassID); 2060 } 2061 2062 bool AMDGPUOperand::isSDWAOperand(MVT type) const { 2063 if (AsmParser->isVI()) 2064 return isVReg32(); 2065 else if (AsmParser->isGFX9Plus()) 2066 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type); 2067 else 2068 return false; 2069 } 2070 2071 bool AMDGPUOperand::isSDWAFP16Operand() const { 2072 return isSDWAOperand(MVT::f16); 2073 } 2074 2075 bool AMDGPUOperand::isSDWAFP32Operand() const { 2076 return isSDWAOperand(MVT::f32); 2077 } 2078 2079 bool AMDGPUOperand::isSDWAInt16Operand() const { 2080 return isSDWAOperand(MVT::i16); 2081 } 2082 2083 bool AMDGPUOperand::isSDWAInt32Operand() const { 2084 return isSDWAOperand(MVT::i32); 2085 } 2086 2087 bool AMDGPUOperand::isBoolReg() const { 2088 auto FB = AsmParser->getFeatureBits(); 2089 return isReg() && ((FB[AMDGPU::FeatureWavefrontSize64] && isSCSrcB64()) || 2090 (FB[AMDGPU::FeatureWavefrontSize32] && isSCSrcB32())); 2091 } 2092 2093 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const 2094 { 2095 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 2096 assert(Size == 2 || Size == 4 || Size == 8); 2097 2098 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1)); 2099 2100 if (Imm.Mods.Abs) { 2101 Val &= ~FpSignMask; 2102 } 2103 if (Imm.Mods.Neg) { 2104 Val ^= FpSignMask; 2105 } 2106 2107 return Val; 2108 } 2109 2110 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const { 2111 if (isExpr()) { 2112 Inst.addOperand(MCOperand::createExpr(Expr)); 2113 return; 2114 } 2115 2116 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()), 2117 Inst.getNumOperands())) { 2118 addLiteralImmOperand(Inst, Imm.Val, 2119 ApplyModifiers & 2120 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 2121 } else { 2122 assert(!isImmTy(ImmTyNone) || !hasModifiers()); 2123 Inst.addOperand(MCOperand::createImm(Imm.Val)); 2124 setImmKindNone(); 2125 } 2126 } 2127 2128 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const { 2129 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode()); 2130 auto OpNum = Inst.getNumOperands(); 2131 // Check that this operand accepts literals 2132 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum)); 2133 2134 if (ApplyModifiers) { 2135 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum)); 2136 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum); 2137 Val = applyInputFPModifiers(Val, Size); 2138 } 2139 2140 APInt Literal(64, Val); 2141 uint8_t OpTy = InstDesc.operands()[OpNum].OperandType; 2142 2143 if (Imm.IsFPImm) { // We got fp literal token 2144 switch (OpTy) { 2145 case AMDGPU::OPERAND_REG_IMM_INT64: 2146 case AMDGPU::OPERAND_REG_IMM_FP64: 2147 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 2148 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 2149 case AMDGPU::OPERAND_REG_INLINE_AC_FP64: 2150 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(), 2151 AsmParser->hasInv2PiInlineImm())) { 2152 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue())); 2153 setImmKindConst(); 2154 return; 2155 } 2156 2157 // Non-inlineable 2158 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand 2159 // For fp operands we check if low 32 bits are zeros 2160 if (Literal.getLoBits(32) != 0) { 2161 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(), 2162 "Can't encode literal as exact 64-bit floating-point operand. " 2163 "Low 32-bits will be set to zero"); 2164 Val &= 0xffffffff00000000u; 2165 } 2166 2167 Inst.addOperand(MCOperand::createImm(Val)); 2168 setImmKindLiteral(); 2169 return; 2170 } 2171 2172 // We don't allow fp literals in 64-bit integer instructions. It is 2173 // unclear how we should encode them. This case should be checked earlier 2174 // in predicate methods (isLiteralImm()) 2175 llvm_unreachable("fp literal in 64-bit integer instruction."); 2176 2177 case AMDGPU::OPERAND_REG_IMM_INT32: 2178 case AMDGPU::OPERAND_REG_IMM_FP32: 2179 case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED: 2180 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 2181 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 2182 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 2183 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 2184 case AMDGPU::OPERAND_REG_IMM_INT16: 2185 case AMDGPU::OPERAND_REG_IMM_FP16: 2186 case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED: 2187 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 2188 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 2189 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 2190 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 2191 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 2192 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 2193 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 2194 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 2195 case AMDGPU::OPERAND_REG_IMM_V2INT16: 2196 case AMDGPU::OPERAND_REG_IMM_V2FP16: 2197 case AMDGPU::OPERAND_REG_INLINE_C_V2FP32: 2198 case AMDGPU::OPERAND_REG_IMM_V2FP32: 2199 case AMDGPU::OPERAND_REG_INLINE_C_V2INT32: 2200 case AMDGPU::OPERAND_REG_IMM_V2INT32: 2201 case AMDGPU::OPERAND_KIMM32: 2202 case AMDGPU::OPERAND_KIMM16: 2203 case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32: { 2204 bool lost; 2205 APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 2206 // Convert literal to single precision 2207 FPLiteral.convert(*getOpFltSemantics(OpTy), 2208 APFloat::rmNearestTiesToEven, &lost); 2209 // We allow precision lost but not overflow or underflow. This should be 2210 // checked earlier in isLiteralImm() 2211 2212 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue(); 2213 Inst.addOperand(MCOperand::createImm(ImmVal)); 2214 if (OpTy == AMDGPU::OPERAND_KIMM32 || OpTy == AMDGPU::OPERAND_KIMM16) { 2215 setImmKindMandatoryLiteral(); 2216 } else { 2217 setImmKindLiteral(); 2218 } 2219 return; 2220 } 2221 default: 2222 llvm_unreachable("invalid operand size"); 2223 } 2224 2225 return; 2226 } 2227 2228 // We got int literal token. 2229 // Only sign extend inline immediates. 2230 switch (OpTy) { 2231 case AMDGPU::OPERAND_REG_IMM_INT32: 2232 case AMDGPU::OPERAND_REG_IMM_FP32: 2233 case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED: 2234 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 2235 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 2236 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 2237 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 2238 case AMDGPU::OPERAND_REG_IMM_V2INT16: 2239 case AMDGPU::OPERAND_REG_IMM_V2FP16: 2240 case AMDGPU::OPERAND_REG_IMM_V2FP32: 2241 case AMDGPU::OPERAND_REG_INLINE_C_V2FP32: 2242 case AMDGPU::OPERAND_REG_IMM_V2INT32: 2243 case AMDGPU::OPERAND_REG_INLINE_C_V2INT32: 2244 case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32: 2245 if (isSafeTruncation(Val, 32) && 2246 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val), 2247 AsmParser->hasInv2PiInlineImm())) { 2248 Inst.addOperand(MCOperand::createImm(Val)); 2249 setImmKindConst(); 2250 return; 2251 } 2252 2253 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff)); 2254 setImmKindLiteral(); 2255 return; 2256 2257 case AMDGPU::OPERAND_REG_IMM_INT64: 2258 case AMDGPU::OPERAND_REG_IMM_FP64: 2259 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 2260 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 2261 case AMDGPU::OPERAND_REG_INLINE_AC_FP64: 2262 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) { 2263 Inst.addOperand(MCOperand::createImm(Val)); 2264 setImmKindConst(); 2265 return; 2266 } 2267 2268 Val = AMDGPU::isSISrcFPOperand(InstDesc, OpNum) ? (uint64_t)Val << 32 2269 : Lo_32(Val); 2270 2271 Inst.addOperand(MCOperand::createImm(Val)); 2272 setImmKindLiteral(); 2273 return; 2274 2275 case AMDGPU::OPERAND_REG_IMM_INT16: 2276 case AMDGPU::OPERAND_REG_IMM_FP16: 2277 case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED: 2278 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 2279 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 2280 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 2281 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 2282 if (isSafeTruncation(Val, 16) && 2283 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 2284 AsmParser->hasInv2PiInlineImm())) { 2285 Inst.addOperand(MCOperand::createImm(Val)); 2286 setImmKindConst(); 2287 return; 2288 } 2289 2290 Inst.addOperand(MCOperand::createImm(Val & 0xffff)); 2291 setImmKindLiteral(); 2292 return; 2293 2294 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 2295 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 2296 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 2297 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: { 2298 assert(isSafeTruncation(Val, 16)); 2299 assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 2300 AsmParser->hasInv2PiInlineImm())); 2301 2302 Inst.addOperand(MCOperand::createImm(Val)); 2303 return; 2304 } 2305 case AMDGPU::OPERAND_KIMM32: 2306 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(32).getZExtValue())); 2307 setImmKindMandatoryLiteral(); 2308 return; 2309 case AMDGPU::OPERAND_KIMM16: 2310 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(16).getZExtValue())); 2311 setImmKindMandatoryLiteral(); 2312 return; 2313 default: 2314 llvm_unreachable("invalid operand size"); 2315 } 2316 } 2317 2318 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const { 2319 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI()))); 2320 } 2321 2322 bool AMDGPUOperand::isInlineValue() const { 2323 return isRegKind() && ::isInlineValue(getReg()); 2324 } 2325 2326 //===----------------------------------------------------------------------===// 2327 // AsmParser 2328 //===----------------------------------------------------------------------===// 2329 2330 static int getRegClass(RegisterKind Is, unsigned RegWidth) { 2331 if (Is == IS_VGPR) { 2332 switch (RegWidth) { 2333 default: return -1; 2334 case 32: 2335 return AMDGPU::VGPR_32RegClassID; 2336 case 64: 2337 return AMDGPU::VReg_64RegClassID; 2338 case 96: 2339 return AMDGPU::VReg_96RegClassID; 2340 case 128: 2341 return AMDGPU::VReg_128RegClassID; 2342 case 160: 2343 return AMDGPU::VReg_160RegClassID; 2344 case 192: 2345 return AMDGPU::VReg_192RegClassID; 2346 case 224: 2347 return AMDGPU::VReg_224RegClassID; 2348 case 256: 2349 return AMDGPU::VReg_256RegClassID; 2350 case 288: 2351 return AMDGPU::VReg_288RegClassID; 2352 case 320: 2353 return AMDGPU::VReg_320RegClassID; 2354 case 352: 2355 return AMDGPU::VReg_352RegClassID; 2356 case 384: 2357 return AMDGPU::VReg_384RegClassID; 2358 case 512: 2359 return AMDGPU::VReg_512RegClassID; 2360 case 1024: 2361 return AMDGPU::VReg_1024RegClassID; 2362 } 2363 } else if (Is == IS_TTMP) { 2364 switch (RegWidth) { 2365 default: return -1; 2366 case 32: 2367 return AMDGPU::TTMP_32RegClassID; 2368 case 64: 2369 return AMDGPU::TTMP_64RegClassID; 2370 case 128: 2371 return AMDGPU::TTMP_128RegClassID; 2372 case 256: 2373 return AMDGPU::TTMP_256RegClassID; 2374 case 512: 2375 return AMDGPU::TTMP_512RegClassID; 2376 } 2377 } else if (Is == IS_SGPR) { 2378 switch (RegWidth) { 2379 default: return -1; 2380 case 32: 2381 return AMDGPU::SGPR_32RegClassID; 2382 case 64: 2383 return AMDGPU::SGPR_64RegClassID; 2384 case 96: 2385 return AMDGPU::SGPR_96RegClassID; 2386 case 128: 2387 return AMDGPU::SGPR_128RegClassID; 2388 case 160: 2389 return AMDGPU::SGPR_160RegClassID; 2390 case 192: 2391 return AMDGPU::SGPR_192RegClassID; 2392 case 224: 2393 return AMDGPU::SGPR_224RegClassID; 2394 case 256: 2395 return AMDGPU::SGPR_256RegClassID; 2396 case 288: 2397 return AMDGPU::SGPR_288RegClassID; 2398 case 320: 2399 return AMDGPU::SGPR_320RegClassID; 2400 case 352: 2401 return AMDGPU::SGPR_352RegClassID; 2402 case 384: 2403 return AMDGPU::SGPR_384RegClassID; 2404 case 512: 2405 return AMDGPU::SGPR_512RegClassID; 2406 } 2407 } else if (Is == IS_AGPR) { 2408 switch (RegWidth) { 2409 default: return -1; 2410 case 32: 2411 return AMDGPU::AGPR_32RegClassID; 2412 case 64: 2413 return AMDGPU::AReg_64RegClassID; 2414 case 96: 2415 return AMDGPU::AReg_96RegClassID; 2416 case 128: 2417 return AMDGPU::AReg_128RegClassID; 2418 case 160: 2419 return AMDGPU::AReg_160RegClassID; 2420 case 192: 2421 return AMDGPU::AReg_192RegClassID; 2422 case 224: 2423 return AMDGPU::AReg_224RegClassID; 2424 case 256: 2425 return AMDGPU::AReg_256RegClassID; 2426 case 288: 2427 return AMDGPU::AReg_288RegClassID; 2428 case 320: 2429 return AMDGPU::AReg_320RegClassID; 2430 case 352: 2431 return AMDGPU::AReg_352RegClassID; 2432 case 384: 2433 return AMDGPU::AReg_384RegClassID; 2434 case 512: 2435 return AMDGPU::AReg_512RegClassID; 2436 case 1024: 2437 return AMDGPU::AReg_1024RegClassID; 2438 } 2439 } 2440 return -1; 2441 } 2442 2443 static unsigned getSpecialRegForName(StringRef RegName) { 2444 return StringSwitch<unsigned>(RegName) 2445 .Case("exec", AMDGPU::EXEC) 2446 .Case("vcc", AMDGPU::VCC) 2447 .Case("flat_scratch", AMDGPU::FLAT_SCR) 2448 .Case("xnack_mask", AMDGPU::XNACK_MASK) 2449 .Case("shared_base", AMDGPU::SRC_SHARED_BASE) 2450 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE) 2451 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT) 2452 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT) 2453 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE) 2454 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE) 2455 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 2456 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 2457 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 2458 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 2459 .Case("lds_direct", AMDGPU::LDS_DIRECT) 2460 .Case("src_lds_direct", AMDGPU::LDS_DIRECT) 2461 .Case("m0", AMDGPU::M0) 2462 .Case("vccz", AMDGPU::SRC_VCCZ) 2463 .Case("src_vccz", AMDGPU::SRC_VCCZ) 2464 .Case("execz", AMDGPU::SRC_EXECZ) 2465 .Case("src_execz", AMDGPU::SRC_EXECZ) 2466 .Case("scc", AMDGPU::SRC_SCC) 2467 .Case("src_scc", AMDGPU::SRC_SCC) 2468 .Case("tba", AMDGPU::TBA) 2469 .Case("tma", AMDGPU::TMA) 2470 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 2471 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 2472 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO) 2473 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI) 2474 .Case("vcc_lo", AMDGPU::VCC_LO) 2475 .Case("vcc_hi", AMDGPU::VCC_HI) 2476 .Case("exec_lo", AMDGPU::EXEC_LO) 2477 .Case("exec_hi", AMDGPU::EXEC_HI) 2478 .Case("tma_lo", AMDGPU::TMA_LO) 2479 .Case("tma_hi", AMDGPU::TMA_HI) 2480 .Case("tba_lo", AMDGPU::TBA_LO) 2481 .Case("tba_hi", AMDGPU::TBA_HI) 2482 .Case("pc", AMDGPU::PC_REG) 2483 .Case("null", AMDGPU::SGPR_NULL) 2484 .Default(AMDGPU::NoRegister); 2485 } 2486 2487 bool AMDGPUAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, 2488 SMLoc &EndLoc, bool RestoreOnFailure) { 2489 auto R = parseRegister(); 2490 if (!R) return true; 2491 assert(R->isReg()); 2492 RegNo = R->getReg(); 2493 StartLoc = R->getStartLoc(); 2494 EndLoc = R->getEndLoc(); 2495 return false; 2496 } 2497 2498 bool AMDGPUAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 2499 SMLoc &EndLoc) { 2500 return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false); 2501 } 2502 2503 ParseStatus AMDGPUAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 2504 SMLoc &EndLoc) { 2505 bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true); 2506 bool PendingErrors = getParser().hasPendingError(); 2507 getParser().clearPendingErrors(); 2508 if (PendingErrors) 2509 return ParseStatus::Failure; 2510 if (Result) 2511 return ParseStatus::NoMatch; 2512 return ParseStatus::Success; 2513 } 2514 2515 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth, 2516 RegisterKind RegKind, unsigned Reg1, 2517 SMLoc Loc) { 2518 switch (RegKind) { 2519 case IS_SPECIAL: 2520 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { 2521 Reg = AMDGPU::EXEC; 2522 RegWidth = 64; 2523 return true; 2524 } 2525 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { 2526 Reg = AMDGPU::FLAT_SCR; 2527 RegWidth = 64; 2528 return true; 2529 } 2530 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) { 2531 Reg = AMDGPU::XNACK_MASK; 2532 RegWidth = 64; 2533 return true; 2534 } 2535 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { 2536 Reg = AMDGPU::VCC; 2537 RegWidth = 64; 2538 return true; 2539 } 2540 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { 2541 Reg = AMDGPU::TBA; 2542 RegWidth = 64; 2543 return true; 2544 } 2545 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { 2546 Reg = AMDGPU::TMA; 2547 RegWidth = 64; 2548 return true; 2549 } 2550 Error(Loc, "register does not fit in the list"); 2551 return false; 2552 case IS_VGPR: 2553 case IS_SGPR: 2554 case IS_AGPR: 2555 case IS_TTMP: 2556 if (Reg1 != Reg + RegWidth / 32) { 2557 Error(Loc, "registers in a list must have consecutive indices"); 2558 return false; 2559 } 2560 RegWidth += 32; 2561 return true; 2562 default: 2563 llvm_unreachable("unexpected register kind"); 2564 } 2565 } 2566 2567 struct RegInfo { 2568 StringLiteral Name; 2569 RegisterKind Kind; 2570 }; 2571 2572 static constexpr RegInfo RegularRegisters[] = { 2573 {{"v"}, IS_VGPR}, 2574 {{"s"}, IS_SGPR}, 2575 {{"ttmp"}, IS_TTMP}, 2576 {{"acc"}, IS_AGPR}, 2577 {{"a"}, IS_AGPR}, 2578 }; 2579 2580 static bool isRegularReg(RegisterKind Kind) { 2581 return Kind == IS_VGPR || 2582 Kind == IS_SGPR || 2583 Kind == IS_TTMP || 2584 Kind == IS_AGPR; 2585 } 2586 2587 static const RegInfo* getRegularRegInfo(StringRef Str) { 2588 for (const RegInfo &Reg : RegularRegisters) 2589 if (Str.starts_with(Reg.Name)) 2590 return &Reg; 2591 return nullptr; 2592 } 2593 2594 static bool getRegNum(StringRef Str, unsigned& Num) { 2595 return !Str.getAsInteger(10, Num); 2596 } 2597 2598 bool 2599 AMDGPUAsmParser::isRegister(const AsmToken &Token, 2600 const AsmToken &NextToken) const { 2601 2602 // A list of consecutive registers: [s0,s1,s2,s3] 2603 if (Token.is(AsmToken::LBrac)) 2604 return true; 2605 2606 if (!Token.is(AsmToken::Identifier)) 2607 return false; 2608 2609 // A single register like s0 or a range of registers like s[0:1] 2610 2611 StringRef Str = Token.getString(); 2612 const RegInfo *Reg = getRegularRegInfo(Str); 2613 if (Reg) { 2614 StringRef RegName = Reg->Name; 2615 StringRef RegSuffix = Str.substr(RegName.size()); 2616 if (!RegSuffix.empty()) { 2617 RegSuffix.consume_back(".l"); 2618 RegSuffix.consume_back(".h"); 2619 unsigned Num; 2620 // A single register with an index: rXX 2621 if (getRegNum(RegSuffix, Num)) 2622 return true; 2623 } else { 2624 // A range of registers: r[XX:YY]. 2625 if (NextToken.is(AsmToken::LBrac)) 2626 return true; 2627 } 2628 } 2629 2630 return getSpecialRegForName(Str) != AMDGPU::NoRegister; 2631 } 2632 2633 bool 2634 AMDGPUAsmParser::isRegister() 2635 { 2636 return isRegister(getToken(), peekToken()); 2637 } 2638 2639 unsigned AMDGPUAsmParser::getRegularReg(RegisterKind RegKind, unsigned RegNum, 2640 unsigned SubReg, unsigned RegWidth, 2641 SMLoc Loc) { 2642 assert(isRegularReg(RegKind)); 2643 2644 unsigned AlignSize = 1; 2645 if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 2646 // SGPR and TTMP registers must be aligned. 2647 // Max required alignment is 4 dwords. 2648 AlignSize = std::min(llvm::bit_ceil(RegWidth / 32), 4u); 2649 } 2650 2651 if (RegNum % AlignSize != 0) { 2652 Error(Loc, "invalid register alignment"); 2653 return AMDGPU::NoRegister; 2654 } 2655 2656 unsigned RegIdx = RegNum / AlignSize; 2657 int RCID = getRegClass(RegKind, RegWidth); 2658 if (RCID == -1) { 2659 Error(Loc, "invalid or unsupported register size"); 2660 return AMDGPU::NoRegister; 2661 } 2662 2663 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2664 const MCRegisterClass RC = TRI->getRegClass(RCID); 2665 if (RegIdx >= RC.getNumRegs()) { 2666 Error(Loc, "register index is out of range"); 2667 return AMDGPU::NoRegister; 2668 } 2669 2670 unsigned Reg = RC.getRegister(RegIdx); 2671 2672 if (SubReg) { 2673 Reg = TRI->getSubReg(Reg, SubReg); 2674 2675 // Currently all regular registers have their .l and .h subregisters, so 2676 // we should never need to generate an error here. 2677 assert(Reg && "Invalid subregister!"); 2678 } 2679 2680 return Reg; 2681 } 2682 2683 bool AMDGPUAsmParser::ParseRegRange(unsigned &Num, unsigned &RegWidth) { 2684 int64_t RegLo, RegHi; 2685 if (!skipToken(AsmToken::LBrac, "missing register index")) 2686 return false; 2687 2688 SMLoc FirstIdxLoc = getLoc(); 2689 SMLoc SecondIdxLoc; 2690 2691 if (!parseExpr(RegLo)) 2692 return false; 2693 2694 if (trySkipToken(AsmToken::Colon)) { 2695 SecondIdxLoc = getLoc(); 2696 if (!parseExpr(RegHi)) 2697 return false; 2698 } else { 2699 RegHi = RegLo; 2700 } 2701 2702 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 2703 return false; 2704 2705 if (!isUInt<32>(RegLo)) { 2706 Error(FirstIdxLoc, "invalid register index"); 2707 return false; 2708 } 2709 2710 if (!isUInt<32>(RegHi)) { 2711 Error(SecondIdxLoc, "invalid register index"); 2712 return false; 2713 } 2714 2715 if (RegLo > RegHi) { 2716 Error(FirstIdxLoc, "first register index should not exceed second index"); 2717 return false; 2718 } 2719 2720 Num = static_cast<unsigned>(RegLo); 2721 RegWidth = 32 * ((RegHi - RegLo) + 1); 2722 return true; 2723 } 2724 2725 unsigned AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, 2726 unsigned &RegNum, unsigned &RegWidth, 2727 SmallVectorImpl<AsmToken> &Tokens) { 2728 assert(isToken(AsmToken::Identifier)); 2729 unsigned Reg = getSpecialRegForName(getTokenStr()); 2730 if (Reg) { 2731 RegNum = 0; 2732 RegWidth = 32; 2733 RegKind = IS_SPECIAL; 2734 Tokens.push_back(getToken()); 2735 lex(); // skip register name 2736 } 2737 return Reg; 2738 } 2739 2740 unsigned AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, 2741 unsigned &RegNum, unsigned &RegWidth, 2742 SmallVectorImpl<AsmToken> &Tokens) { 2743 assert(isToken(AsmToken::Identifier)); 2744 StringRef RegName = getTokenStr(); 2745 auto Loc = getLoc(); 2746 2747 const RegInfo *RI = getRegularRegInfo(RegName); 2748 if (!RI) { 2749 Error(Loc, "invalid register name"); 2750 return AMDGPU::NoRegister; 2751 } 2752 2753 Tokens.push_back(getToken()); 2754 lex(); // skip register name 2755 2756 RegKind = RI->Kind; 2757 StringRef RegSuffix = RegName.substr(RI->Name.size()); 2758 unsigned SubReg = NoSubRegister; 2759 if (!RegSuffix.empty()) { 2760 // We don't know the opcode till we are done parsing, so we don't know if 2761 // registers should be 16 or 32 bit. It is therefore mandatory to put .l or 2762 // .h to correctly specify 16 bit registers. We also can't determine class 2763 // VGPR_16_Lo128 or VGPR_16, so always parse them as VGPR_16. 2764 if (RegSuffix.consume_back(".l")) 2765 SubReg = AMDGPU::lo16; 2766 else if (RegSuffix.consume_back(".h")) 2767 SubReg = AMDGPU::hi16; 2768 2769 // Single 32-bit register: vXX. 2770 if (!getRegNum(RegSuffix, RegNum)) { 2771 Error(Loc, "invalid register index"); 2772 return AMDGPU::NoRegister; 2773 } 2774 RegWidth = 32; 2775 } else { 2776 // Range of registers: v[XX:YY]. ":YY" is optional. 2777 if (!ParseRegRange(RegNum, RegWidth)) 2778 return AMDGPU::NoRegister; 2779 } 2780 2781 return getRegularReg(RegKind, RegNum, SubReg, RegWidth, Loc); 2782 } 2783 2784 unsigned AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, unsigned &RegNum, 2785 unsigned &RegWidth, 2786 SmallVectorImpl<AsmToken> &Tokens) { 2787 unsigned Reg = AMDGPU::NoRegister; 2788 auto ListLoc = getLoc(); 2789 2790 if (!skipToken(AsmToken::LBrac, 2791 "expected a register or a list of registers")) { 2792 return AMDGPU::NoRegister; 2793 } 2794 2795 // List of consecutive registers, e.g.: [s0,s1,s2,s3] 2796 2797 auto Loc = getLoc(); 2798 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) 2799 return AMDGPU::NoRegister; 2800 if (RegWidth != 32) { 2801 Error(Loc, "expected a single 32-bit register"); 2802 return AMDGPU::NoRegister; 2803 } 2804 2805 for (; trySkipToken(AsmToken::Comma); ) { 2806 RegisterKind NextRegKind; 2807 unsigned NextReg, NextRegNum, NextRegWidth; 2808 Loc = getLoc(); 2809 2810 if (!ParseAMDGPURegister(NextRegKind, NextReg, 2811 NextRegNum, NextRegWidth, 2812 Tokens)) { 2813 return AMDGPU::NoRegister; 2814 } 2815 if (NextRegWidth != 32) { 2816 Error(Loc, "expected a single 32-bit register"); 2817 return AMDGPU::NoRegister; 2818 } 2819 if (NextRegKind != RegKind) { 2820 Error(Loc, "registers in a list must be of the same kind"); 2821 return AMDGPU::NoRegister; 2822 } 2823 if (!AddNextRegisterToList(Reg, RegWidth, RegKind, NextReg, Loc)) 2824 return AMDGPU::NoRegister; 2825 } 2826 2827 if (!skipToken(AsmToken::RBrac, 2828 "expected a comma or a closing square bracket")) { 2829 return AMDGPU::NoRegister; 2830 } 2831 2832 if (isRegularReg(RegKind)) 2833 Reg = getRegularReg(RegKind, RegNum, NoSubRegister, RegWidth, ListLoc); 2834 2835 return Reg; 2836 } 2837 2838 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 2839 unsigned &RegNum, unsigned &RegWidth, 2840 SmallVectorImpl<AsmToken> &Tokens) { 2841 auto Loc = getLoc(); 2842 Reg = AMDGPU::NoRegister; 2843 2844 if (isToken(AsmToken::Identifier)) { 2845 Reg = ParseSpecialReg(RegKind, RegNum, RegWidth, Tokens); 2846 if (Reg == AMDGPU::NoRegister) 2847 Reg = ParseRegularReg(RegKind, RegNum, RegWidth, Tokens); 2848 } else { 2849 Reg = ParseRegList(RegKind, RegNum, RegWidth, Tokens); 2850 } 2851 2852 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2853 if (Reg == AMDGPU::NoRegister) { 2854 assert(Parser.hasPendingError()); 2855 return false; 2856 } 2857 2858 if (!subtargetHasRegister(*TRI, Reg)) { 2859 if (Reg == AMDGPU::SGPR_NULL) { 2860 Error(Loc, "'null' operand is not supported on this GPU"); 2861 } else { 2862 Error(Loc, "register not available on this GPU"); 2863 } 2864 return false; 2865 } 2866 2867 return true; 2868 } 2869 2870 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 2871 unsigned &RegNum, unsigned &RegWidth, 2872 bool RestoreOnFailure /*=false*/) { 2873 Reg = AMDGPU::NoRegister; 2874 2875 SmallVector<AsmToken, 1> Tokens; 2876 if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) { 2877 if (RestoreOnFailure) { 2878 while (!Tokens.empty()) { 2879 getLexer().UnLex(Tokens.pop_back_val()); 2880 } 2881 } 2882 return true; 2883 } 2884 return false; 2885 } 2886 2887 std::optional<StringRef> 2888 AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) { 2889 switch (RegKind) { 2890 case IS_VGPR: 2891 return StringRef(".amdgcn.next_free_vgpr"); 2892 case IS_SGPR: 2893 return StringRef(".amdgcn.next_free_sgpr"); 2894 default: 2895 return std::nullopt; 2896 } 2897 } 2898 2899 void AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) { 2900 auto SymbolName = getGprCountSymbolName(RegKind); 2901 assert(SymbolName && "initializing invalid register kind"); 2902 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2903 Sym->setVariableValue(MCConstantExpr::create(0, getContext())); 2904 } 2905 2906 bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind, 2907 unsigned DwordRegIndex, 2908 unsigned RegWidth) { 2909 // Symbols are only defined for GCN targets 2910 if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6) 2911 return true; 2912 2913 auto SymbolName = getGprCountSymbolName(RegKind); 2914 if (!SymbolName) 2915 return true; 2916 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2917 2918 int64_t NewMax = DwordRegIndex + divideCeil(RegWidth, 32) - 1; 2919 int64_t OldCount; 2920 2921 if (!Sym->isVariable()) 2922 return !Error(getLoc(), 2923 ".amdgcn.next_free_{v,s}gpr symbols must be variable"); 2924 if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount)) 2925 return !Error( 2926 getLoc(), 2927 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions"); 2928 2929 if (OldCount <= NewMax) 2930 Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext())); 2931 2932 return true; 2933 } 2934 2935 std::unique_ptr<AMDGPUOperand> 2936 AMDGPUAsmParser::parseRegister(bool RestoreOnFailure) { 2937 const auto &Tok = getToken(); 2938 SMLoc StartLoc = Tok.getLoc(); 2939 SMLoc EndLoc = Tok.getEndLoc(); 2940 RegisterKind RegKind; 2941 unsigned Reg, RegNum, RegWidth; 2942 2943 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { 2944 return nullptr; 2945 } 2946 if (isHsaAbi(getSTI())) { 2947 if (!updateGprCountSymbols(RegKind, RegNum, RegWidth)) 2948 return nullptr; 2949 } else 2950 KernelScope.usesRegister(RegKind, RegNum, RegWidth); 2951 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc); 2952 } 2953 2954 ParseStatus AMDGPUAsmParser::parseImm(OperandVector &Operands, 2955 bool HasSP3AbsModifier, bool HasLit) { 2956 // TODO: add syntactic sugar for 1/(2*PI) 2957 2958 if (isRegister()) 2959 return ParseStatus::NoMatch; 2960 assert(!isModifier()); 2961 2962 if (!HasLit) { 2963 HasLit = trySkipId("lit"); 2964 if (HasLit) { 2965 if (!skipToken(AsmToken::LParen, "expected left paren after lit")) 2966 return ParseStatus::Failure; 2967 ParseStatus S = parseImm(Operands, HasSP3AbsModifier, HasLit); 2968 if (S.isSuccess() && 2969 !skipToken(AsmToken::RParen, "expected closing parentheses")) 2970 return ParseStatus::Failure; 2971 return S; 2972 } 2973 } 2974 2975 const auto& Tok = getToken(); 2976 const auto& NextTok = peekToken(); 2977 bool IsReal = Tok.is(AsmToken::Real); 2978 SMLoc S = getLoc(); 2979 bool Negate = false; 2980 2981 if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) { 2982 lex(); 2983 IsReal = true; 2984 Negate = true; 2985 } 2986 2987 AMDGPUOperand::Modifiers Mods; 2988 Mods.Lit = HasLit; 2989 2990 if (IsReal) { 2991 // Floating-point expressions are not supported. 2992 // Can only allow floating-point literals with an 2993 // optional sign. 2994 2995 StringRef Num = getTokenStr(); 2996 lex(); 2997 2998 APFloat RealVal(APFloat::IEEEdouble()); 2999 auto roundMode = APFloat::rmNearestTiesToEven; 3000 if (errorToBool(RealVal.convertFromString(Num, roundMode).takeError())) 3001 return ParseStatus::Failure; 3002 if (Negate) 3003 RealVal.changeSign(); 3004 3005 Operands.push_back( 3006 AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S, 3007 AMDGPUOperand::ImmTyNone, true)); 3008 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 3009 Op.setModifiers(Mods); 3010 3011 return ParseStatus::Success; 3012 3013 } else { 3014 int64_t IntVal; 3015 const MCExpr *Expr; 3016 SMLoc S = getLoc(); 3017 3018 if (HasSP3AbsModifier) { 3019 // This is a workaround for handling expressions 3020 // as arguments of SP3 'abs' modifier, for example: 3021 // |1.0| 3022 // |-1| 3023 // |1+x| 3024 // This syntax is not compatible with syntax of standard 3025 // MC expressions (due to the trailing '|'). 3026 SMLoc EndLoc; 3027 if (getParser().parsePrimaryExpr(Expr, EndLoc, nullptr)) 3028 return ParseStatus::Failure; 3029 } else { 3030 if (Parser.parseExpression(Expr)) 3031 return ParseStatus::Failure; 3032 } 3033 3034 if (Expr->evaluateAsAbsolute(IntVal)) { 3035 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 3036 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 3037 Op.setModifiers(Mods); 3038 } else { 3039 if (HasLit) 3040 return ParseStatus::NoMatch; 3041 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 3042 } 3043 3044 return ParseStatus::Success; 3045 } 3046 3047 return ParseStatus::NoMatch; 3048 } 3049 3050 ParseStatus AMDGPUAsmParser::parseReg(OperandVector &Operands) { 3051 if (!isRegister()) 3052 return ParseStatus::NoMatch; 3053 3054 if (auto R = parseRegister()) { 3055 assert(R->isReg()); 3056 Operands.push_back(std::move(R)); 3057 return ParseStatus::Success; 3058 } 3059 return ParseStatus::Failure; 3060 } 3061 3062 ParseStatus AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, 3063 bool HasSP3AbsMod, bool HasLit) { 3064 ParseStatus Res = parseReg(Operands); 3065 if (!Res.isNoMatch()) 3066 return Res; 3067 if (isModifier()) 3068 return ParseStatus::NoMatch; 3069 return parseImm(Operands, HasSP3AbsMod, HasLit); 3070 } 3071 3072 bool 3073 AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 3074 if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) { 3075 const auto &str = Token.getString(); 3076 return str == "abs" || str == "neg" || str == "sext"; 3077 } 3078 return false; 3079 } 3080 3081 bool 3082 AMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const { 3083 return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon); 3084 } 3085 3086 bool 3087 AMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 3088 return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe); 3089 } 3090 3091 bool 3092 AMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 3093 return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken); 3094 } 3095 3096 // Check if this is an operand modifier or an opcode modifier 3097 // which may look like an expression but it is not. We should 3098 // avoid parsing these modifiers as expressions. Currently 3099 // recognized sequences are: 3100 // |...| 3101 // abs(...) 3102 // neg(...) 3103 // sext(...) 3104 // -reg 3105 // -|...| 3106 // -abs(...) 3107 // name:... 3108 // 3109 bool 3110 AMDGPUAsmParser::isModifier() { 3111 3112 AsmToken Tok = getToken(); 3113 AsmToken NextToken[2]; 3114 peekTokens(NextToken); 3115 3116 return isOperandModifier(Tok, NextToken[0]) || 3117 (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) || 3118 isOpcodeModifierWithVal(Tok, NextToken[0]); 3119 } 3120 3121 // Check if the current token is an SP3 'neg' modifier. 3122 // Currently this modifier is allowed in the following context: 3123 // 3124 // 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]". 3125 // 2. Before an 'abs' modifier: -abs(...) 3126 // 3. Before an SP3 'abs' modifier: -|...| 3127 // 3128 // In all other cases "-" is handled as a part 3129 // of an expression that follows the sign. 3130 // 3131 // Note: When "-" is followed by an integer literal, 3132 // this is interpreted as integer negation rather 3133 // than a floating-point NEG modifier applied to N. 3134 // Beside being contr-intuitive, such use of floating-point 3135 // NEG modifier would have resulted in different meaning 3136 // of integer literals used with VOP1/2/C and VOP3, 3137 // for example: 3138 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF 3139 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001 3140 // Negative fp literals with preceding "-" are 3141 // handled likewise for uniformity 3142 // 3143 bool 3144 AMDGPUAsmParser::parseSP3NegModifier() { 3145 3146 AsmToken NextToken[2]; 3147 peekTokens(NextToken); 3148 3149 if (isToken(AsmToken::Minus) && 3150 (isRegister(NextToken[0], NextToken[1]) || 3151 NextToken[0].is(AsmToken::Pipe) || 3152 isId(NextToken[0], "abs"))) { 3153 lex(); 3154 return true; 3155 } 3156 3157 return false; 3158 } 3159 3160 ParseStatus 3161 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, 3162 bool AllowImm) { 3163 bool Neg, SP3Neg; 3164 bool Abs, SP3Abs; 3165 bool Lit; 3166 SMLoc Loc; 3167 3168 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead. 3169 if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) 3170 return Error(getLoc(), "invalid syntax, expected 'neg' modifier"); 3171 3172 SP3Neg = parseSP3NegModifier(); 3173 3174 Loc = getLoc(); 3175 Neg = trySkipId("neg"); 3176 if (Neg && SP3Neg) 3177 return Error(Loc, "expected register or immediate"); 3178 if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg")) 3179 return ParseStatus::Failure; 3180 3181 Abs = trySkipId("abs"); 3182 if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs")) 3183 return ParseStatus::Failure; 3184 3185 Lit = trySkipId("lit"); 3186 if (Lit && !skipToken(AsmToken::LParen, "expected left paren after lit")) 3187 return ParseStatus::Failure; 3188 3189 Loc = getLoc(); 3190 SP3Abs = trySkipToken(AsmToken::Pipe); 3191 if (Abs && SP3Abs) 3192 return Error(Loc, "expected register or immediate"); 3193 3194 ParseStatus Res; 3195 if (AllowImm) { 3196 Res = parseRegOrImm(Operands, SP3Abs, Lit); 3197 } else { 3198 Res = parseReg(Operands); 3199 } 3200 if (!Res.isSuccess()) 3201 return (SP3Neg || Neg || SP3Abs || Abs || Lit) ? ParseStatus::Failure : Res; 3202 3203 if (Lit && !Operands.back()->isImm()) 3204 Error(Loc, "expected immediate with lit modifier"); 3205 3206 if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar")) 3207 return ParseStatus::Failure; 3208 if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses")) 3209 return ParseStatus::Failure; 3210 if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses")) 3211 return ParseStatus::Failure; 3212 if (Lit && !skipToken(AsmToken::RParen, "expected closing parentheses")) 3213 return ParseStatus::Failure; 3214 3215 AMDGPUOperand::Modifiers Mods; 3216 Mods.Abs = Abs || SP3Abs; 3217 Mods.Neg = Neg || SP3Neg; 3218 Mods.Lit = Lit; 3219 3220 if (Mods.hasFPModifiers() || Lit) { 3221 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 3222 if (Op.isExpr()) 3223 return Error(Op.getStartLoc(), "expected an absolute expression"); 3224 Op.setModifiers(Mods); 3225 } 3226 return ParseStatus::Success; 3227 } 3228 3229 ParseStatus 3230 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, 3231 bool AllowImm) { 3232 bool Sext = trySkipId("sext"); 3233 if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext")) 3234 return ParseStatus::Failure; 3235 3236 ParseStatus Res; 3237 if (AllowImm) { 3238 Res = parseRegOrImm(Operands); 3239 } else { 3240 Res = parseReg(Operands); 3241 } 3242 if (!Res.isSuccess()) 3243 return Sext ? ParseStatus::Failure : Res; 3244 3245 if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses")) 3246 return ParseStatus::Failure; 3247 3248 AMDGPUOperand::Modifiers Mods; 3249 Mods.Sext = Sext; 3250 3251 if (Mods.hasIntModifiers()) { 3252 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 3253 if (Op.isExpr()) 3254 return Error(Op.getStartLoc(), "expected an absolute expression"); 3255 Op.setModifiers(Mods); 3256 } 3257 3258 return ParseStatus::Success; 3259 } 3260 3261 ParseStatus AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) { 3262 return parseRegOrImmWithFPInputMods(Operands, false); 3263 } 3264 3265 ParseStatus AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) { 3266 return parseRegOrImmWithIntInputMods(Operands, false); 3267 } 3268 3269 ParseStatus AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) { 3270 auto Loc = getLoc(); 3271 if (trySkipId("off")) { 3272 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc, 3273 AMDGPUOperand::ImmTyOff, false)); 3274 return ParseStatus::Success; 3275 } 3276 3277 if (!isRegister()) 3278 return ParseStatus::NoMatch; 3279 3280 std::unique_ptr<AMDGPUOperand> Reg = parseRegister(); 3281 if (Reg) { 3282 Operands.push_back(std::move(Reg)); 3283 return ParseStatus::Success; 3284 } 3285 3286 return ParseStatus::Failure; 3287 } 3288 3289 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 3290 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 3291 3292 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 3293 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) || 3294 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) || 3295 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) ) 3296 return Match_InvalidOperand; 3297 3298 if ((TSFlags & SIInstrFlags::VOP3) && 3299 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 3300 getForcedEncodingSize() != 64) 3301 return Match_PreferE32; 3302 3303 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 3304 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 3305 // v_mac_f32/16 allow only dst_sel == DWORD; 3306 auto OpNum = 3307 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel); 3308 const auto &Op = Inst.getOperand(OpNum); 3309 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) { 3310 return Match_InvalidOperand; 3311 } 3312 } 3313 3314 return Match_Success; 3315 } 3316 3317 static ArrayRef<unsigned> getAllVariants() { 3318 static const unsigned Variants[] = { 3319 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, 3320 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, 3321 AMDGPUAsmVariants::DPP, AMDGPUAsmVariants::VOP3_DPP 3322 }; 3323 3324 return ArrayRef(Variants); 3325 } 3326 3327 // What asm variants we should check 3328 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const { 3329 if (isForcedDPP() && isForcedVOP3()) { 3330 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3_DPP}; 3331 return ArrayRef(Variants); 3332 } 3333 if (getForcedEncodingSize() == 32) { 3334 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT}; 3335 return ArrayRef(Variants); 3336 } 3337 3338 if (isForcedVOP3()) { 3339 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; 3340 return ArrayRef(Variants); 3341 } 3342 3343 if (isForcedSDWA()) { 3344 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA, 3345 AMDGPUAsmVariants::SDWA9}; 3346 return ArrayRef(Variants); 3347 } 3348 3349 if (isForcedDPP()) { 3350 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; 3351 return ArrayRef(Variants); 3352 } 3353 3354 return getAllVariants(); 3355 } 3356 3357 StringRef AMDGPUAsmParser::getMatchedVariantName() const { 3358 if (isForcedDPP() && isForcedVOP3()) 3359 return "e64_dpp"; 3360 3361 if (getForcedEncodingSize() == 32) 3362 return "e32"; 3363 3364 if (isForcedVOP3()) 3365 return "e64"; 3366 3367 if (isForcedSDWA()) 3368 return "sdwa"; 3369 3370 if (isForcedDPP()) 3371 return "dpp"; 3372 3373 return ""; 3374 } 3375 3376 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const { 3377 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3378 for (MCPhysReg Reg : Desc.implicit_uses()) { 3379 switch (Reg) { 3380 case AMDGPU::FLAT_SCR: 3381 case AMDGPU::VCC: 3382 case AMDGPU::VCC_LO: 3383 case AMDGPU::VCC_HI: 3384 case AMDGPU::M0: 3385 return Reg; 3386 default: 3387 break; 3388 } 3389 } 3390 return AMDGPU::NoRegister; 3391 } 3392 3393 // NB: This code is correct only when used to check constant 3394 // bus limitations because GFX7 support no f16 inline constants. 3395 // Note that there are no cases when a GFX7 opcode violates 3396 // constant bus limitations due to the use of an f16 constant. 3397 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, 3398 unsigned OpIdx) const { 3399 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3400 3401 if (!AMDGPU::isSISrcOperand(Desc, OpIdx) || 3402 AMDGPU::isKImmOperand(Desc, OpIdx)) { 3403 return false; 3404 } 3405 3406 const MCOperand &MO = Inst.getOperand(OpIdx); 3407 3408 int64_t Val = MO.getImm(); 3409 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx); 3410 3411 switch (OpSize) { // expected operand size 3412 case 8: 3413 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm()); 3414 case 4: 3415 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm()); 3416 case 2: { 3417 const unsigned OperandType = Desc.operands()[OpIdx].OperandType; 3418 if (OperandType == AMDGPU::OPERAND_REG_IMM_INT16 || 3419 OperandType == AMDGPU::OPERAND_REG_INLINE_C_INT16 || 3420 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_INT16) 3421 return AMDGPU::isInlinableIntLiteral(Val); 3422 3423 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 || 3424 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 || 3425 OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16) 3426 return AMDGPU::isInlinableLiteralV2I16(Val); 3427 3428 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 || 3429 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 || 3430 OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) 3431 return AMDGPU::isInlinableLiteralV2F16(Val); 3432 3433 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm()); 3434 } 3435 default: 3436 llvm_unreachable("invalid operand size"); 3437 } 3438 } 3439 3440 unsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const { 3441 if (!isGFX10Plus()) 3442 return 1; 3443 3444 switch (Opcode) { 3445 // 64-bit shift instructions can use only one scalar value input 3446 case AMDGPU::V_LSHLREV_B64_e64: 3447 case AMDGPU::V_LSHLREV_B64_gfx10: 3448 case AMDGPU::V_LSHLREV_B64_e64_gfx11: 3449 case AMDGPU::V_LSHLREV_B64_e32_gfx12: 3450 case AMDGPU::V_LSHLREV_B64_e64_gfx12: 3451 case AMDGPU::V_LSHRREV_B64_e64: 3452 case AMDGPU::V_LSHRREV_B64_gfx10: 3453 case AMDGPU::V_LSHRREV_B64_e64_gfx11: 3454 case AMDGPU::V_LSHRREV_B64_e64_gfx12: 3455 case AMDGPU::V_ASHRREV_I64_e64: 3456 case AMDGPU::V_ASHRREV_I64_gfx10: 3457 case AMDGPU::V_ASHRREV_I64_e64_gfx11: 3458 case AMDGPU::V_ASHRREV_I64_e64_gfx12: 3459 case AMDGPU::V_LSHL_B64_e64: 3460 case AMDGPU::V_LSHR_B64_e64: 3461 case AMDGPU::V_ASHR_I64_e64: 3462 return 1; 3463 default: 3464 return 2; 3465 } 3466 } 3467 3468 constexpr unsigned MAX_SRC_OPERANDS_NUM = 6; 3469 using OperandIndices = SmallVector<int16_t, MAX_SRC_OPERANDS_NUM>; 3470 3471 // Get regular operand indices in the same order as specified 3472 // in the instruction (but append mandatory literals to the end). 3473 static OperandIndices getSrcOperandIndices(unsigned Opcode, 3474 bool AddMandatoryLiterals = false) { 3475 3476 int16_t ImmIdx = 3477 AddMandatoryLiterals ? getNamedOperandIdx(Opcode, OpName::imm) : -1; 3478 3479 if (isVOPD(Opcode)) { 3480 int16_t ImmDeferredIdx = 3481 AddMandatoryLiterals ? getNamedOperandIdx(Opcode, OpName::immDeferred) 3482 : -1; 3483 3484 return {getNamedOperandIdx(Opcode, OpName::src0X), 3485 getNamedOperandIdx(Opcode, OpName::vsrc1X), 3486 getNamedOperandIdx(Opcode, OpName::src0Y), 3487 getNamedOperandIdx(Opcode, OpName::vsrc1Y), 3488 ImmDeferredIdx, 3489 ImmIdx}; 3490 } 3491 3492 return {getNamedOperandIdx(Opcode, OpName::src0), 3493 getNamedOperandIdx(Opcode, OpName::src1), 3494 getNamedOperandIdx(Opcode, OpName::src2), ImmIdx}; 3495 } 3496 3497 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { 3498 const MCOperand &MO = Inst.getOperand(OpIdx); 3499 if (MO.isImm()) { 3500 return !isInlineConstant(Inst, OpIdx); 3501 } else if (MO.isReg()) { 3502 auto Reg = MO.getReg(); 3503 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3504 auto PReg = mc2PseudoReg(Reg); 3505 return isSGPR(PReg, TRI) && PReg != SGPR_NULL; 3506 } else { 3507 return true; 3508 } 3509 } 3510 3511 bool AMDGPUAsmParser::validateConstantBusLimitations( 3512 const MCInst &Inst, const OperandVector &Operands) { 3513 const unsigned Opcode = Inst.getOpcode(); 3514 const MCInstrDesc &Desc = MII.get(Opcode); 3515 unsigned LastSGPR = AMDGPU::NoRegister; 3516 unsigned ConstantBusUseCount = 0; 3517 unsigned NumLiterals = 0; 3518 unsigned LiteralSize; 3519 3520 if (!(Desc.TSFlags & 3521 (SIInstrFlags::VOPC | SIInstrFlags::VOP1 | SIInstrFlags::VOP2 | 3522 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P | SIInstrFlags::SDWA)) && 3523 !isVOPD(Opcode)) 3524 return true; 3525 3526 // Check special imm operands (used by madmk, etc) 3527 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::imm)) { 3528 ++NumLiterals; 3529 LiteralSize = 4; 3530 } 3531 3532 SmallDenseSet<unsigned> SGPRsUsed; 3533 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst); 3534 if (SGPRUsed != AMDGPU::NoRegister) { 3535 SGPRsUsed.insert(SGPRUsed); 3536 ++ConstantBusUseCount; 3537 } 3538 3539 OperandIndices OpIndices = getSrcOperandIndices(Opcode); 3540 3541 for (int OpIdx : OpIndices) { 3542 if (OpIdx == -1) 3543 continue; 3544 3545 const MCOperand &MO = Inst.getOperand(OpIdx); 3546 if (usesConstantBus(Inst, OpIdx)) { 3547 if (MO.isReg()) { 3548 LastSGPR = mc2PseudoReg(MO.getReg()); 3549 // Pairs of registers with a partial intersections like these 3550 // s0, s[0:1] 3551 // flat_scratch_lo, flat_scratch 3552 // flat_scratch_lo, flat_scratch_hi 3553 // are theoretically valid but they are disabled anyway. 3554 // Note that this code mimics SIInstrInfo::verifyInstruction 3555 if (SGPRsUsed.insert(LastSGPR).second) { 3556 ++ConstantBusUseCount; 3557 } 3558 } else { // Expression or a literal 3559 3560 if (Desc.operands()[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE) 3561 continue; // special operand like VINTERP attr_chan 3562 3563 // An instruction may use only one literal. 3564 // This has been validated on the previous step. 3565 // See validateVOPLiteral. 3566 // This literal may be used as more than one operand. 3567 // If all these operands are of the same size, 3568 // this literal counts as one scalar value. 3569 // Otherwise it counts as 2 scalar values. 3570 // See "GFX10 Shader Programming", section 3.6.2.3. 3571 3572 unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx); 3573 if (Size < 4) 3574 Size = 4; 3575 3576 if (NumLiterals == 0) { 3577 NumLiterals = 1; 3578 LiteralSize = Size; 3579 } else if (LiteralSize != Size) { 3580 NumLiterals = 2; 3581 } 3582 } 3583 } 3584 } 3585 ConstantBusUseCount += NumLiterals; 3586 3587 if (ConstantBusUseCount <= getConstantBusLimit(Opcode)) 3588 return true; 3589 3590 SMLoc LitLoc = getLitLoc(Operands); 3591 SMLoc RegLoc = getRegLoc(LastSGPR, Operands); 3592 SMLoc Loc = (LitLoc.getPointer() < RegLoc.getPointer()) ? RegLoc : LitLoc; 3593 Error(Loc, "invalid operand (violates constant bus restrictions)"); 3594 return false; 3595 } 3596 3597 bool AMDGPUAsmParser::validateVOPDRegBankConstraints( 3598 const MCInst &Inst, const OperandVector &Operands) { 3599 3600 const unsigned Opcode = Inst.getOpcode(); 3601 if (!isVOPD(Opcode)) 3602 return true; 3603 3604 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3605 3606 auto getVRegIdx = [&](unsigned, unsigned OperandIdx) { 3607 const MCOperand &Opr = Inst.getOperand(OperandIdx); 3608 return (Opr.isReg() && !isSGPR(mc2PseudoReg(Opr.getReg()), TRI)) 3609 ? Opr.getReg() 3610 : MCRegister::NoRegister; 3611 }; 3612 3613 // On GFX12 if both OpX and OpY are V_MOV_B32 then OPY uses SRC2 source-cache. 3614 bool SkipSrc = Opcode == AMDGPU::V_DUAL_MOV_B32_e32_X_MOV_B32_e32_gfx12; 3615 3616 const auto &InstInfo = getVOPDInstInfo(Opcode, &MII); 3617 auto InvalidCompOprIdx = 3618 InstInfo.getInvalidCompOperandIndex(getVRegIdx, SkipSrc); 3619 if (!InvalidCompOprIdx) 3620 return true; 3621 3622 auto CompOprIdx = *InvalidCompOprIdx; 3623 auto ParsedIdx = 3624 std::max(InstInfo[VOPD::X].getIndexInParsedOperands(CompOprIdx), 3625 InstInfo[VOPD::Y].getIndexInParsedOperands(CompOprIdx)); 3626 assert(ParsedIdx > 0 && ParsedIdx < Operands.size()); 3627 3628 auto Loc = ((AMDGPUOperand &)*Operands[ParsedIdx]).getStartLoc(); 3629 if (CompOprIdx == VOPD::Component::DST) { 3630 Error(Loc, "one dst register must be even and the other odd"); 3631 } else { 3632 auto CompSrcIdx = CompOprIdx - VOPD::Component::DST_NUM; 3633 Error(Loc, Twine("src") + Twine(CompSrcIdx) + 3634 " operands must use different VGPR banks"); 3635 } 3636 3637 return false; 3638 } 3639 3640 bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) { 3641 3642 const unsigned Opc = Inst.getOpcode(); 3643 const MCInstrDesc &Desc = MII.get(Opc); 3644 3645 if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) { 3646 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp); 3647 assert(ClampIdx != -1); 3648 return Inst.getOperand(ClampIdx).getImm() == 0; 3649 } 3650 3651 return true; 3652 } 3653 3654 constexpr uint64_t MIMGFlags = 3655 SIInstrFlags::MIMG | SIInstrFlags::VIMAGE | SIInstrFlags::VSAMPLE; 3656 3657 bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst, 3658 const SMLoc &IDLoc) { 3659 3660 const unsigned Opc = Inst.getOpcode(); 3661 const MCInstrDesc &Desc = MII.get(Opc); 3662 3663 if ((Desc.TSFlags & MIMGFlags) == 0) 3664 return true; 3665 3666 int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata); 3667 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3668 int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe); 3669 3670 assert(VDataIdx != -1); 3671 3672 if ((DMaskIdx == -1 || TFEIdx == -1) && isGFX10_AEncoding()) // intersect_ray 3673 return true; 3674 3675 unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx); 3676 unsigned TFESize = (TFEIdx != -1 && Inst.getOperand(TFEIdx).getImm()) ? 1 : 0; 3677 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3678 if (DMask == 0) 3679 DMask = 1; 3680 3681 bool IsPackedD16 = false; 3682 unsigned DataSize = 3683 (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : llvm::popcount(DMask); 3684 if (hasPackedD16()) { 3685 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 3686 IsPackedD16 = D16Idx >= 0; 3687 if (IsPackedD16 && Inst.getOperand(D16Idx).getImm()) 3688 DataSize = (DataSize + 1) / 2; 3689 } 3690 3691 if ((VDataSize / 4) == DataSize + TFESize) 3692 return true; 3693 3694 StringRef Modifiers; 3695 if (isGFX90A()) 3696 Modifiers = IsPackedD16 ? "dmask and d16" : "dmask"; 3697 else 3698 Modifiers = IsPackedD16 ? "dmask, d16 and tfe" : "dmask and tfe"; 3699 3700 Error(IDLoc, Twine("image data size does not match ") + Modifiers); 3701 return false; 3702 } 3703 3704 bool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst, 3705 const SMLoc &IDLoc) { 3706 const unsigned Opc = Inst.getOpcode(); 3707 const MCInstrDesc &Desc = MII.get(Opc); 3708 3709 if ((Desc.TSFlags & MIMGFlags) == 0 || !isGFX10Plus()) 3710 return true; 3711 3712 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc); 3713 3714 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 3715 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 3716 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0); 3717 int RSrcOpName = Desc.TSFlags & SIInstrFlags::MIMG ? AMDGPU::OpName::srsrc 3718 : AMDGPU::OpName::rsrc; 3719 int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RSrcOpName); 3720 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 3721 int A16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::a16); 3722 3723 assert(VAddr0Idx != -1); 3724 assert(SrsrcIdx != -1); 3725 assert(SrsrcIdx > VAddr0Idx); 3726 3727 bool IsA16 = (A16Idx != -1 && Inst.getOperand(A16Idx).getImm()); 3728 if (BaseOpcode->BVH) { 3729 if (IsA16 == BaseOpcode->A16) 3730 return true; 3731 Error(IDLoc, "image address size does not match a16"); 3732 return false; 3733 } 3734 3735 unsigned Dim = Inst.getOperand(DimIdx).getImm(); 3736 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim); 3737 bool IsNSA = SrsrcIdx - VAddr0Idx > 1; 3738 unsigned ActualAddrSize = 3739 IsNSA ? SrsrcIdx - VAddr0Idx 3740 : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4; 3741 3742 unsigned ExpectedAddrSize = 3743 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, DimInfo, IsA16, hasG16()); 3744 3745 if (IsNSA) { 3746 if (hasPartialNSAEncoding() && 3747 ExpectedAddrSize > 3748 getNSAMaxSize(Desc.TSFlags & SIInstrFlags::VSAMPLE)) { 3749 int VAddrLastIdx = SrsrcIdx - 1; 3750 unsigned VAddrLastSize = 3751 AMDGPU::getRegOperandSize(getMRI(), Desc, VAddrLastIdx) / 4; 3752 3753 ActualAddrSize = VAddrLastIdx - VAddr0Idx + VAddrLastSize; 3754 } 3755 } else { 3756 if (ExpectedAddrSize > 12) 3757 ExpectedAddrSize = 16; 3758 3759 // Allow oversized 8 VGPR vaddr when only 5/6/7 VGPRs are required. 3760 // This provides backward compatibility for assembly created 3761 // before 160b/192b/224b types were directly supported. 3762 if (ActualAddrSize == 8 && (ExpectedAddrSize >= 5 && ExpectedAddrSize <= 7)) 3763 return true; 3764 } 3765 3766 if (ActualAddrSize == ExpectedAddrSize) 3767 return true; 3768 3769 Error(IDLoc, "image address size does not match dim and a16"); 3770 return false; 3771 } 3772 3773 bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) { 3774 3775 const unsigned Opc = Inst.getOpcode(); 3776 const MCInstrDesc &Desc = MII.get(Opc); 3777 3778 if ((Desc.TSFlags & MIMGFlags) == 0) 3779 return true; 3780 if (!Desc.mayLoad() || !Desc.mayStore()) 3781 return true; // Not atomic 3782 3783 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3784 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3785 3786 // This is an incomplete check because image_atomic_cmpswap 3787 // may only use 0x3 and 0xf while other atomic operations 3788 // may use 0x1 and 0x3. However these limitations are 3789 // verified when we check that dmask matches dst size. 3790 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf; 3791 } 3792 3793 bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) { 3794 3795 const unsigned Opc = Inst.getOpcode(); 3796 const MCInstrDesc &Desc = MII.get(Opc); 3797 3798 if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0) 3799 return true; 3800 3801 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3802 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3803 3804 // GATHER4 instructions use dmask in a different fashion compared to 3805 // other MIMG instructions. The only useful DMASK values are 3806 // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns 3807 // (red,red,red,red) etc.) The ISA document doesn't mention 3808 // this. 3809 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8; 3810 } 3811 3812 bool AMDGPUAsmParser::validateMIMGMSAA(const MCInst &Inst) { 3813 const unsigned Opc = Inst.getOpcode(); 3814 const MCInstrDesc &Desc = MII.get(Opc); 3815 3816 if ((Desc.TSFlags & MIMGFlags) == 0) 3817 return true; 3818 3819 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc); 3820 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 3821 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 3822 3823 if (!BaseOpcode->MSAA) 3824 return true; 3825 3826 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 3827 assert(DimIdx != -1); 3828 3829 unsigned Dim = Inst.getOperand(DimIdx).getImm(); 3830 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim); 3831 3832 return DimInfo->MSAA; 3833 } 3834 3835 static bool IsMovrelsSDWAOpcode(const unsigned Opcode) 3836 { 3837 switch (Opcode) { 3838 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10: 3839 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10: 3840 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10: 3841 return true; 3842 default: 3843 return false; 3844 } 3845 } 3846 3847 // movrels* opcodes should only allow VGPRS as src0. 3848 // This is specified in .td description for vop1/vop3, 3849 // but sdwa is handled differently. See isSDWAOperand. 3850 bool AMDGPUAsmParser::validateMovrels(const MCInst &Inst, 3851 const OperandVector &Operands) { 3852 3853 const unsigned Opc = Inst.getOpcode(); 3854 const MCInstrDesc &Desc = MII.get(Opc); 3855 3856 if ((Desc.TSFlags & SIInstrFlags::SDWA) == 0 || !IsMovrelsSDWAOpcode(Opc)) 3857 return true; 3858 3859 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3860 assert(Src0Idx != -1); 3861 3862 SMLoc ErrLoc; 3863 const MCOperand &Src0 = Inst.getOperand(Src0Idx); 3864 if (Src0.isReg()) { 3865 auto Reg = mc2PseudoReg(Src0.getReg()); 3866 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3867 if (!isSGPR(Reg, TRI)) 3868 return true; 3869 ErrLoc = getRegLoc(Reg, Operands); 3870 } else { 3871 ErrLoc = getConstLoc(Operands); 3872 } 3873 3874 Error(ErrLoc, "source operand must be a VGPR"); 3875 return false; 3876 } 3877 3878 bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst, 3879 const OperandVector &Operands) { 3880 3881 const unsigned Opc = Inst.getOpcode(); 3882 3883 if (Opc != AMDGPU::V_ACCVGPR_WRITE_B32_vi) 3884 return true; 3885 3886 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3887 assert(Src0Idx != -1); 3888 3889 const MCOperand &Src0 = Inst.getOperand(Src0Idx); 3890 if (!Src0.isReg()) 3891 return true; 3892 3893 auto Reg = mc2PseudoReg(Src0.getReg()); 3894 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3895 if (!isGFX90A() && isSGPR(Reg, TRI)) { 3896 Error(getRegLoc(Reg, Operands), 3897 "source operand must be either a VGPR or an inline constant"); 3898 return false; 3899 } 3900 3901 return true; 3902 } 3903 3904 bool AMDGPUAsmParser::validateMAISrc2(const MCInst &Inst, 3905 const OperandVector &Operands) { 3906 unsigned Opcode = Inst.getOpcode(); 3907 const MCInstrDesc &Desc = MII.get(Opcode); 3908 3909 if (!(Desc.TSFlags & SIInstrFlags::IsMAI) || 3910 !getFeatureBits()[FeatureMFMAInlineLiteralBug]) 3911 return true; 3912 3913 const int Src2Idx = getNamedOperandIdx(Opcode, OpName::src2); 3914 if (Src2Idx == -1) 3915 return true; 3916 3917 if (Inst.getOperand(Src2Idx).isImm() && isInlineConstant(Inst, Src2Idx)) { 3918 Error(getConstLoc(Operands), 3919 "inline constants are not allowed for this operand"); 3920 return false; 3921 } 3922 3923 return true; 3924 } 3925 3926 bool AMDGPUAsmParser::validateMFMA(const MCInst &Inst, 3927 const OperandVector &Operands) { 3928 const unsigned Opc = Inst.getOpcode(); 3929 const MCInstrDesc &Desc = MII.get(Opc); 3930 3931 if ((Desc.TSFlags & SIInstrFlags::IsMAI) == 0) 3932 return true; 3933 3934 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2); 3935 if (Src2Idx == -1) 3936 return true; 3937 3938 const MCOperand &Src2 = Inst.getOperand(Src2Idx); 3939 if (!Src2.isReg()) 3940 return true; 3941 3942 MCRegister Src2Reg = Src2.getReg(); 3943 MCRegister DstReg = Inst.getOperand(0).getReg(); 3944 if (Src2Reg == DstReg) 3945 return true; 3946 3947 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3948 if (TRI->getRegClass(Desc.operands()[0].RegClass).getSizeInBits() <= 128) 3949 return true; 3950 3951 if (TRI->regsOverlap(Src2Reg, DstReg)) { 3952 Error(getRegLoc(mc2PseudoReg(Src2Reg), Operands), 3953 "source 2 operand must not partially overlap with dst"); 3954 return false; 3955 } 3956 3957 return true; 3958 } 3959 3960 bool AMDGPUAsmParser::validateDivScale(const MCInst &Inst) { 3961 switch (Inst.getOpcode()) { 3962 default: 3963 return true; 3964 case V_DIV_SCALE_F32_gfx6_gfx7: 3965 case V_DIV_SCALE_F32_vi: 3966 case V_DIV_SCALE_F32_gfx10: 3967 case V_DIV_SCALE_F64_gfx6_gfx7: 3968 case V_DIV_SCALE_F64_vi: 3969 case V_DIV_SCALE_F64_gfx10: 3970 break; 3971 } 3972 3973 // TODO: Check that src0 = src1 or src2. 3974 3975 for (auto Name : {AMDGPU::OpName::src0_modifiers, 3976 AMDGPU::OpName::src2_modifiers, 3977 AMDGPU::OpName::src2_modifiers}) { 3978 if (Inst.getOperand(AMDGPU::getNamedOperandIdx(Inst.getOpcode(), Name)) 3979 .getImm() & 3980 SISrcMods::ABS) { 3981 return false; 3982 } 3983 } 3984 3985 return true; 3986 } 3987 3988 bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) { 3989 3990 const unsigned Opc = Inst.getOpcode(); 3991 const MCInstrDesc &Desc = MII.get(Opc); 3992 3993 if ((Desc.TSFlags & MIMGFlags) == 0) 3994 return true; 3995 3996 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 3997 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) { 3998 if (isCI() || isSI()) 3999 return false; 4000 } 4001 4002 return true; 4003 } 4004 4005 static bool IsRevOpcode(const unsigned Opcode) 4006 { 4007 switch (Opcode) { 4008 case AMDGPU::V_SUBREV_F32_e32: 4009 case AMDGPU::V_SUBREV_F32_e64: 4010 case AMDGPU::V_SUBREV_F32_e32_gfx10: 4011 case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7: 4012 case AMDGPU::V_SUBREV_F32_e32_vi: 4013 case AMDGPU::V_SUBREV_F32_e64_gfx10: 4014 case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7: 4015 case AMDGPU::V_SUBREV_F32_e64_vi: 4016 4017 case AMDGPU::V_SUBREV_CO_U32_e32: 4018 case AMDGPU::V_SUBREV_CO_U32_e64: 4019 case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7: 4020 case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7: 4021 4022 case AMDGPU::V_SUBBREV_U32_e32: 4023 case AMDGPU::V_SUBBREV_U32_e64: 4024 case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7: 4025 case AMDGPU::V_SUBBREV_U32_e32_vi: 4026 case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7: 4027 case AMDGPU::V_SUBBREV_U32_e64_vi: 4028 4029 case AMDGPU::V_SUBREV_U32_e32: 4030 case AMDGPU::V_SUBREV_U32_e64: 4031 case AMDGPU::V_SUBREV_U32_e32_gfx9: 4032 case AMDGPU::V_SUBREV_U32_e32_vi: 4033 case AMDGPU::V_SUBREV_U32_e64_gfx9: 4034 case AMDGPU::V_SUBREV_U32_e64_vi: 4035 4036 case AMDGPU::V_SUBREV_F16_e32: 4037 case AMDGPU::V_SUBREV_F16_e64: 4038 case AMDGPU::V_SUBREV_F16_e32_gfx10: 4039 case AMDGPU::V_SUBREV_F16_e32_vi: 4040 case AMDGPU::V_SUBREV_F16_e64_gfx10: 4041 case AMDGPU::V_SUBREV_F16_e64_vi: 4042 4043 case AMDGPU::V_SUBREV_U16_e32: 4044 case AMDGPU::V_SUBREV_U16_e64: 4045 case AMDGPU::V_SUBREV_U16_e32_vi: 4046 case AMDGPU::V_SUBREV_U16_e64_vi: 4047 4048 case AMDGPU::V_SUBREV_CO_U32_e32_gfx9: 4049 case AMDGPU::V_SUBREV_CO_U32_e64_gfx10: 4050 case AMDGPU::V_SUBREV_CO_U32_e64_gfx9: 4051 4052 case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9: 4053 case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9: 4054 4055 case AMDGPU::V_SUBREV_NC_U32_e32_gfx10: 4056 case AMDGPU::V_SUBREV_NC_U32_e64_gfx10: 4057 4058 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10: 4059 case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10: 4060 4061 case AMDGPU::V_LSHRREV_B32_e32: 4062 case AMDGPU::V_LSHRREV_B32_e64: 4063 case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7: 4064 case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7: 4065 case AMDGPU::V_LSHRREV_B32_e32_vi: 4066 case AMDGPU::V_LSHRREV_B32_e64_vi: 4067 case AMDGPU::V_LSHRREV_B32_e32_gfx10: 4068 case AMDGPU::V_LSHRREV_B32_e64_gfx10: 4069 4070 case AMDGPU::V_ASHRREV_I32_e32: 4071 case AMDGPU::V_ASHRREV_I32_e64: 4072 case AMDGPU::V_ASHRREV_I32_e32_gfx10: 4073 case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7: 4074 case AMDGPU::V_ASHRREV_I32_e32_vi: 4075 case AMDGPU::V_ASHRREV_I32_e64_gfx10: 4076 case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7: 4077 case AMDGPU::V_ASHRREV_I32_e64_vi: 4078 4079 case AMDGPU::V_LSHLREV_B32_e32: 4080 case AMDGPU::V_LSHLREV_B32_e64: 4081 case AMDGPU::V_LSHLREV_B32_e32_gfx10: 4082 case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7: 4083 case AMDGPU::V_LSHLREV_B32_e32_vi: 4084 case AMDGPU::V_LSHLREV_B32_e64_gfx10: 4085 case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7: 4086 case AMDGPU::V_LSHLREV_B32_e64_vi: 4087 4088 case AMDGPU::V_LSHLREV_B16_e32: 4089 case AMDGPU::V_LSHLREV_B16_e64: 4090 case AMDGPU::V_LSHLREV_B16_e32_vi: 4091 case AMDGPU::V_LSHLREV_B16_e64_vi: 4092 case AMDGPU::V_LSHLREV_B16_gfx10: 4093 4094 case AMDGPU::V_LSHRREV_B16_e32: 4095 case AMDGPU::V_LSHRREV_B16_e64: 4096 case AMDGPU::V_LSHRREV_B16_e32_vi: 4097 case AMDGPU::V_LSHRREV_B16_e64_vi: 4098 case AMDGPU::V_LSHRREV_B16_gfx10: 4099 4100 case AMDGPU::V_ASHRREV_I16_e32: 4101 case AMDGPU::V_ASHRREV_I16_e64: 4102 case AMDGPU::V_ASHRREV_I16_e32_vi: 4103 case AMDGPU::V_ASHRREV_I16_e64_vi: 4104 case AMDGPU::V_ASHRREV_I16_gfx10: 4105 4106 case AMDGPU::V_LSHLREV_B64_e64: 4107 case AMDGPU::V_LSHLREV_B64_gfx10: 4108 case AMDGPU::V_LSHLREV_B64_vi: 4109 4110 case AMDGPU::V_LSHRREV_B64_e64: 4111 case AMDGPU::V_LSHRREV_B64_gfx10: 4112 case AMDGPU::V_LSHRREV_B64_vi: 4113 4114 case AMDGPU::V_ASHRREV_I64_e64: 4115 case AMDGPU::V_ASHRREV_I64_gfx10: 4116 case AMDGPU::V_ASHRREV_I64_vi: 4117 4118 case AMDGPU::V_PK_LSHLREV_B16: 4119 case AMDGPU::V_PK_LSHLREV_B16_gfx10: 4120 case AMDGPU::V_PK_LSHLREV_B16_vi: 4121 4122 case AMDGPU::V_PK_LSHRREV_B16: 4123 case AMDGPU::V_PK_LSHRREV_B16_gfx10: 4124 case AMDGPU::V_PK_LSHRREV_B16_vi: 4125 case AMDGPU::V_PK_ASHRREV_I16: 4126 case AMDGPU::V_PK_ASHRREV_I16_gfx10: 4127 case AMDGPU::V_PK_ASHRREV_I16_vi: 4128 return true; 4129 default: 4130 return false; 4131 } 4132 } 4133 4134 std::optional<StringRef> 4135 AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) { 4136 4137 using namespace SIInstrFlags; 4138 const unsigned Opcode = Inst.getOpcode(); 4139 const MCInstrDesc &Desc = MII.get(Opcode); 4140 4141 // lds_direct register is defined so that it can be used 4142 // with 9-bit operands only. Ignore encodings which do not accept these. 4143 const auto Enc = VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA; 4144 if ((Desc.TSFlags & Enc) == 0) 4145 return std::nullopt; 4146 4147 for (auto SrcName : {OpName::src0, OpName::src1, OpName::src2}) { 4148 auto SrcIdx = getNamedOperandIdx(Opcode, SrcName); 4149 if (SrcIdx == -1) 4150 break; 4151 const auto &Src = Inst.getOperand(SrcIdx); 4152 if (Src.isReg() && Src.getReg() == LDS_DIRECT) { 4153 4154 if (isGFX90A() || isGFX11Plus()) 4155 return StringRef("lds_direct is not supported on this GPU"); 4156 4157 if (IsRevOpcode(Opcode) || (Desc.TSFlags & SIInstrFlags::SDWA)) 4158 return StringRef("lds_direct cannot be used with this instruction"); 4159 4160 if (SrcName != OpName::src0) 4161 return StringRef("lds_direct may be used as src0 only"); 4162 } 4163 } 4164 4165 return std::nullopt; 4166 } 4167 4168 SMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const { 4169 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 4170 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4171 if (Op.isFlatOffset()) 4172 return Op.getStartLoc(); 4173 } 4174 return getLoc(); 4175 } 4176 4177 bool AMDGPUAsmParser::validateOffset(const MCInst &Inst, 4178 const OperandVector &Operands) { 4179 auto Opcode = Inst.getOpcode(); 4180 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 4181 if (OpNum == -1) 4182 return true; 4183 4184 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4185 if ((TSFlags & SIInstrFlags::FLAT)) 4186 return validateFlatOffset(Inst, Operands); 4187 4188 if ((TSFlags & SIInstrFlags::SMRD)) 4189 return validateSMEMOffset(Inst, Operands); 4190 4191 const auto &Op = Inst.getOperand(OpNum); 4192 if (isGFX12Plus() && 4193 (TSFlags & (SIInstrFlags::MUBUF | SIInstrFlags::MTBUF))) { 4194 const unsigned OffsetSize = 24; 4195 if (!isIntN(OffsetSize, Op.getImm())) { 4196 Error(getFlatOffsetLoc(Operands), 4197 Twine("expected a ") + Twine(OffsetSize) + "-bit signed offset"); 4198 return false; 4199 } 4200 } else { 4201 const unsigned OffsetSize = 16; 4202 if (!isUIntN(OffsetSize, Op.getImm())) { 4203 Error(getFlatOffsetLoc(Operands), 4204 Twine("expected a ") + Twine(OffsetSize) + "-bit unsigned offset"); 4205 return false; 4206 } 4207 } 4208 return true; 4209 } 4210 4211 bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst, 4212 const OperandVector &Operands) { 4213 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4214 if ((TSFlags & SIInstrFlags::FLAT) == 0) 4215 return true; 4216 4217 auto Opcode = Inst.getOpcode(); 4218 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 4219 assert(OpNum != -1); 4220 4221 const auto &Op = Inst.getOperand(OpNum); 4222 if (!hasFlatOffsets() && Op.getImm() != 0) { 4223 Error(getFlatOffsetLoc(Operands), 4224 "flat offset modifier is not supported on this GPU"); 4225 return false; 4226 } 4227 4228 // For pre-GFX12 FLAT instructions the offset must be positive; 4229 // MSB is ignored and forced to zero. 4230 unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI()); 4231 bool AllowNegative = 4232 (TSFlags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch)) || 4233 isGFX12Plus(); 4234 if (!isIntN(OffsetSize, Op.getImm()) || (!AllowNegative && Op.getImm() < 0)) { 4235 Error(getFlatOffsetLoc(Operands), 4236 Twine("expected a ") + 4237 (AllowNegative ? Twine(OffsetSize) + "-bit signed offset" 4238 : Twine(OffsetSize - 1) + "-bit unsigned offset")); 4239 return false; 4240 } 4241 4242 return true; 4243 } 4244 4245 SMLoc AMDGPUAsmParser::getSMEMOffsetLoc(const OperandVector &Operands) const { 4246 // Start with second operand because SMEM Offset cannot be dst or src0. 4247 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 4248 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4249 if (Op.isSMEMOffset() || Op.isSMEMOffsetMod()) 4250 return Op.getStartLoc(); 4251 } 4252 return getLoc(); 4253 } 4254 4255 bool AMDGPUAsmParser::validateSMEMOffset(const MCInst &Inst, 4256 const OperandVector &Operands) { 4257 if (isCI() || isSI()) 4258 return true; 4259 4260 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4261 if ((TSFlags & SIInstrFlags::SMRD) == 0) 4262 return true; 4263 4264 auto Opcode = Inst.getOpcode(); 4265 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 4266 if (OpNum == -1) 4267 return true; 4268 4269 const auto &Op = Inst.getOperand(OpNum); 4270 if (!Op.isImm()) 4271 return true; 4272 4273 uint64_t Offset = Op.getImm(); 4274 bool IsBuffer = AMDGPU::getSMEMIsBuffer(Opcode); 4275 if (AMDGPU::isLegalSMRDEncodedUnsignedOffset(getSTI(), Offset) || 4276 AMDGPU::isLegalSMRDEncodedSignedOffset(getSTI(), Offset, IsBuffer)) 4277 return true; 4278 4279 Error(getSMEMOffsetLoc(Operands), 4280 isGFX12Plus() ? "expected a 24-bit signed offset" 4281 : (isVI() || IsBuffer) ? "expected a 20-bit unsigned offset" 4282 : "expected a 21-bit signed offset"); 4283 4284 return false; 4285 } 4286 4287 bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const { 4288 unsigned Opcode = Inst.getOpcode(); 4289 const MCInstrDesc &Desc = MII.get(Opcode); 4290 if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC))) 4291 return true; 4292 4293 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 4294 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 4295 4296 const int OpIndices[] = { Src0Idx, Src1Idx }; 4297 4298 unsigned NumExprs = 0; 4299 unsigned NumLiterals = 0; 4300 uint32_t LiteralValue; 4301 4302 for (int OpIdx : OpIndices) { 4303 if (OpIdx == -1) break; 4304 4305 const MCOperand &MO = Inst.getOperand(OpIdx); 4306 // Exclude special imm operands (like that used by s_set_gpr_idx_on) 4307 if (AMDGPU::isSISrcOperand(Desc, OpIdx)) { 4308 if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 4309 uint32_t Value = static_cast<uint32_t>(MO.getImm()); 4310 if (NumLiterals == 0 || LiteralValue != Value) { 4311 LiteralValue = Value; 4312 ++NumLiterals; 4313 } 4314 } else if (MO.isExpr()) { 4315 ++NumExprs; 4316 } 4317 } 4318 } 4319 4320 return NumLiterals + NumExprs <= 1; 4321 } 4322 4323 bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) { 4324 const unsigned Opc = Inst.getOpcode(); 4325 if (isPermlane16(Opc)) { 4326 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 4327 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 4328 4329 if (OpSel & ~3) 4330 return false; 4331 } 4332 4333 uint64_t TSFlags = MII.get(Opc).TSFlags; 4334 4335 if (isGFX940() && (TSFlags & SIInstrFlags::IsDOT)) { 4336 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 4337 if (OpSelIdx != -1) { 4338 if (Inst.getOperand(OpSelIdx).getImm() != 0) 4339 return false; 4340 } 4341 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi); 4342 if (OpSelHiIdx != -1) { 4343 if (Inst.getOperand(OpSelHiIdx).getImm() != -1) 4344 return false; 4345 } 4346 } 4347 4348 // op_sel[0:1] must be 0 for v_dot2_bf16_bf16 and v_dot2_f16_f16 (VOP3 Dot). 4349 if (isGFX11Plus() && (TSFlags & SIInstrFlags::IsDOT) && 4350 (TSFlags & SIInstrFlags::VOP3) && !(TSFlags & SIInstrFlags::VOP3P)) { 4351 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 4352 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 4353 if (OpSel & 3) 4354 return false; 4355 } 4356 4357 return true; 4358 } 4359 4360 bool AMDGPUAsmParser::validateNeg(const MCInst &Inst, int OpName) { 4361 assert(OpName == AMDGPU::OpName::neg_lo || OpName == AMDGPU::OpName::neg_hi); 4362 4363 const unsigned Opc = Inst.getOpcode(); 4364 uint64_t TSFlags = MII.get(Opc).TSFlags; 4365 4366 // v_dot4 fp8/bf8 neg_lo/neg_hi not allowed on src0 and src1 (allowed on src2) 4367 if (!(TSFlags & SIInstrFlags::IsDOT)) 4368 return true; 4369 4370 int NegIdx = AMDGPU::getNamedOperandIdx(Opc, OpName); 4371 if (NegIdx == -1) 4372 return true; 4373 4374 unsigned Neg = Inst.getOperand(NegIdx).getImm(); 4375 4376 // Instructions that have neg_lo or neg_hi operand but neg modifier is allowed 4377 // on some src operands but not allowed on other. 4378 // It is convenient that such instructions don't have src_modifiers operand 4379 // for src operands that don't allow neg because they also don't allow opsel. 4380 4381 int SrcMods[3] = {AMDGPU::OpName::src0_modifiers, 4382 AMDGPU::OpName::src1_modifiers, 4383 AMDGPU::OpName::src2_modifiers}; 4384 4385 for (unsigned i = 0; i < 3; ++i) { 4386 if (!AMDGPU::hasNamedOperand(Opc, SrcMods[i])) { 4387 if (Neg & (1 << i)) 4388 return false; 4389 } 4390 } 4391 4392 return true; 4393 } 4394 4395 bool AMDGPUAsmParser::validateDPP(const MCInst &Inst, 4396 const OperandVector &Operands) { 4397 const unsigned Opc = Inst.getOpcode(); 4398 int DppCtrlIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dpp_ctrl); 4399 if (DppCtrlIdx >= 0) { 4400 unsigned DppCtrl = Inst.getOperand(DppCtrlIdx).getImm(); 4401 4402 if (!AMDGPU::isLegalDPALU_DPPControl(DppCtrl) && 4403 AMDGPU::isDPALU_DPP(MII.get(Opc))) { 4404 // DP ALU DPP is supported for row_newbcast only on GFX9* 4405 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyDppCtrl, Operands); 4406 Error(S, "DP ALU dpp only supports row_newbcast"); 4407 return false; 4408 } 4409 } 4410 4411 int Dpp8Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dpp8); 4412 bool IsDPP = DppCtrlIdx >= 0 || Dpp8Idx >= 0; 4413 4414 if (IsDPP && !hasDPPSrc1SGPR(getSTI())) { 4415 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1); 4416 if (Src1Idx >= 0) { 4417 const MCOperand &Src1 = Inst.getOperand(Src1Idx); 4418 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 4419 if (Src1.isImm() || 4420 (Src1.isReg() && isSGPR(mc2PseudoReg(Src1.getReg()), TRI))) { 4421 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[Src1Idx]); 4422 Error(Op.getStartLoc(), "invalid operand for instruction"); 4423 return false; 4424 } 4425 } 4426 } 4427 4428 return true; 4429 } 4430 4431 // Check if VCC register matches wavefront size 4432 bool AMDGPUAsmParser::validateVccOperand(unsigned Reg) const { 4433 auto FB = getFeatureBits(); 4434 return (FB[AMDGPU::FeatureWavefrontSize64] && Reg == AMDGPU::VCC) || 4435 (FB[AMDGPU::FeatureWavefrontSize32] && Reg == AMDGPU::VCC_LO); 4436 } 4437 4438 // One unique literal can be used. VOP3 literal is only allowed in GFX10+ 4439 bool AMDGPUAsmParser::validateVOPLiteral(const MCInst &Inst, 4440 const OperandVector &Operands) { 4441 unsigned Opcode = Inst.getOpcode(); 4442 const MCInstrDesc &Desc = MII.get(Opcode); 4443 bool HasMandatoryLiteral = getNamedOperandIdx(Opcode, OpName::imm) != -1; 4444 if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P)) && 4445 !HasMandatoryLiteral && !isVOPD(Opcode)) 4446 return true; 4447 4448 OperandIndices OpIndices = getSrcOperandIndices(Opcode, HasMandatoryLiteral); 4449 4450 unsigned NumExprs = 0; 4451 unsigned NumLiterals = 0; 4452 uint32_t LiteralValue; 4453 4454 for (int OpIdx : OpIndices) { 4455 if (OpIdx == -1) 4456 continue; 4457 4458 const MCOperand &MO = Inst.getOperand(OpIdx); 4459 if (!MO.isImm() && !MO.isExpr()) 4460 continue; 4461 if (!isSISrcOperand(Desc, OpIdx)) 4462 continue; 4463 4464 if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 4465 uint64_t Value = static_cast<uint64_t>(MO.getImm()); 4466 bool IsFP64 = AMDGPU::isSISrcFPOperand(Desc, OpIdx) && 4467 AMDGPU::getOperandSize(Desc.operands()[OpIdx]) == 8; 4468 bool IsValid32Op = AMDGPU::isValid32BitLiteral(Value, IsFP64); 4469 4470 if (!IsValid32Op && !isInt<32>(Value) && !isUInt<32>(Value)) { 4471 Error(getLitLoc(Operands), "invalid operand for instruction"); 4472 return false; 4473 } 4474 4475 if (IsFP64 && IsValid32Op) 4476 Value = Hi_32(Value); 4477 4478 if (NumLiterals == 0 || LiteralValue != Value) { 4479 LiteralValue = Value; 4480 ++NumLiterals; 4481 } 4482 } else if (MO.isExpr()) { 4483 ++NumExprs; 4484 } 4485 } 4486 NumLiterals += NumExprs; 4487 4488 if (!NumLiterals) 4489 return true; 4490 4491 if (!HasMandatoryLiteral && !getFeatureBits()[FeatureVOP3Literal]) { 4492 Error(getLitLoc(Operands), "literal operands are not supported"); 4493 return false; 4494 } 4495 4496 if (NumLiterals > 1) { 4497 Error(getLitLoc(Operands, true), "only one unique literal operand is allowed"); 4498 return false; 4499 } 4500 4501 return true; 4502 } 4503 4504 // Returns -1 if not a register, 0 if VGPR and 1 if AGPR. 4505 static int IsAGPROperand(const MCInst &Inst, uint16_t NameIdx, 4506 const MCRegisterInfo *MRI) { 4507 int OpIdx = AMDGPU::getNamedOperandIdx(Inst.getOpcode(), NameIdx); 4508 if (OpIdx < 0) 4509 return -1; 4510 4511 const MCOperand &Op = Inst.getOperand(OpIdx); 4512 if (!Op.isReg()) 4513 return -1; 4514 4515 unsigned Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0); 4516 auto Reg = Sub ? Sub : Op.getReg(); 4517 const MCRegisterClass &AGPR32 = MRI->getRegClass(AMDGPU::AGPR_32RegClassID); 4518 return AGPR32.contains(Reg) ? 1 : 0; 4519 } 4520 4521 bool AMDGPUAsmParser::validateAGPRLdSt(const MCInst &Inst) const { 4522 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4523 if ((TSFlags & (SIInstrFlags::FLAT | SIInstrFlags::MUBUF | 4524 SIInstrFlags::MTBUF | SIInstrFlags::MIMG | 4525 SIInstrFlags::DS)) == 0) 4526 return true; 4527 4528 uint16_t DataNameIdx = (TSFlags & SIInstrFlags::DS) ? AMDGPU::OpName::data0 4529 : AMDGPU::OpName::vdata; 4530 4531 const MCRegisterInfo *MRI = getMRI(); 4532 int DstAreg = IsAGPROperand(Inst, AMDGPU::OpName::vdst, MRI); 4533 int DataAreg = IsAGPROperand(Inst, DataNameIdx, MRI); 4534 4535 if ((TSFlags & SIInstrFlags::DS) && DataAreg >= 0) { 4536 int Data2Areg = IsAGPROperand(Inst, AMDGPU::OpName::data1, MRI); 4537 if (Data2Areg >= 0 && Data2Areg != DataAreg) 4538 return false; 4539 } 4540 4541 auto FB = getFeatureBits(); 4542 if (FB[AMDGPU::FeatureGFX90AInsts]) { 4543 if (DataAreg < 0 || DstAreg < 0) 4544 return true; 4545 return DstAreg == DataAreg; 4546 } 4547 4548 return DstAreg < 1 && DataAreg < 1; 4549 } 4550 4551 bool AMDGPUAsmParser::validateVGPRAlign(const MCInst &Inst) const { 4552 auto FB = getFeatureBits(); 4553 if (!FB[AMDGPU::FeatureGFX90AInsts]) 4554 return true; 4555 4556 const MCRegisterInfo *MRI = getMRI(); 4557 const MCRegisterClass &VGPR32 = MRI->getRegClass(AMDGPU::VGPR_32RegClassID); 4558 const MCRegisterClass &AGPR32 = MRI->getRegClass(AMDGPU::AGPR_32RegClassID); 4559 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { 4560 const MCOperand &Op = Inst.getOperand(I); 4561 if (!Op.isReg()) 4562 continue; 4563 4564 unsigned Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0); 4565 if (!Sub) 4566 continue; 4567 4568 if (VGPR32.contains(Sub) && ((Sub - AMDGPU::VGPR0) & 1)) 4569 return false; 4570 if (AGPR32.contains(Sub) && ((Sub - AMDGPU::AGPR0) & 1)) 4571 return false; 4572 } 4573 4574 return true; 4575 } 4576 4577 SMLoc AMDGPUAsmParser::getBLGPLoc(const OperandVector &Operands) const { 4578 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 4579 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 4580 if (Op.isBLGP()) 4581 return Op.getStartLoc(); 4582 } 4583 return SMLoc(); 4584 } 4585 4586 bool AMDGPUAsmParser::validateBLGP(const MCInst &Inst, 4587 const OperandVector &Operands) { 4588 unsigned Opc = Inst.getOpcode(); 4589 int BlgpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::blgp); 4590 if (BlgpIdx == -1) 4591 return true; 4592 SMLoc BLGPLoc = getBLGPLoc(Operands); 4593 if (!BLGPLoc.isValid()) 4594 return true; 4595 bool IsNeg = StringRef(BLGPLoc.getPointer()).starts_with("neg:"); 4596 auto FB = getFeatureBits(); 4597 bool UsesNeg = false; 4598 if (FB[AMDGPU::FeatureGFX940Insts]) { 4599 switch (Opc) { 4600 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_acd: 4601 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_vcd: 4602 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_acd: 4603 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_vcd: 4604 UsesNeg = true; 4605 } 4606 } 4607 4608 if (IsNeg == UsesNeg) 4609 return true; 4610 4611 Error(BLGPLoc, 4612 UsesNeg ? "invalid modifier: blgp is not supported" 4613 : "invalid modifier: neg is not supported"); 4614 4615 return false; 4616 } 4617 4618 bool AMDGPUAsmParser::validateWaitCnt(const MCInst &Inst, 4619 const OperandVector &Operands) { 4620 if (!isGFX11Plus()) 4621 return true; 4622 4623 unsigned Opc = Inst.getOpcode(); 4624 if (Opc != AMDGPU::S_WAITCNT_EXPCNT_gfx11 && 4625 Opc != AMDGPU::S_WAITCNT_LGKMCNT_gfx11 && 4626 Opc != AMDGPU::S_WAITCNT_VMCNT_gfx11 && 4627 Opc != AMDGPU::S_WAITCNT_VSCNT_gfx11) 4628 return true; 4629 4630 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst); 4631 assert(Src0Idx >= 0 && Inst.getOperand(Src0Idx).isReg()); 4632 auto Reg = mc2PseudoReg(Inst.getOperand(Src0Idx).getReg()); 4633 if (Reg == AMDGPU::SGPR_NULL) 4634 return true; 4635 4636 SMLoc RegLoc = getRegLoc(Reg, Operands); 4637 Error(RegLoc, "src0 must be null"); 4638 return false; 4639 } 4640 4641 bool AMDGPUAsmParser::validateDS(const MCInst &Inst, 4642 const OperandVector &Operands) { 4643 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4644 if ((TSFlags & SIInstrFlags::DS) == 0) 4645 return true; 4646 if (TSFlags & SIInstrFlags::GWS) 4647 return validateGWS(Inst, Operands); 4648 // Only validate GDS for non-GWS instructions. 4649 if (hasGDS()) 4650 return true; 4651 int GDSIdx = 4652 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::gds); 4653 if (GDSIdx < 0) 4654 return true; 4655 unsigned GDS = Inst.getOperand(GDSIdx).getImm(); 4656 if (GDS) { 4657 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyGDS, Operands); 4658 Error(S, "gds modifier is not supported on this GPU"); 4659 return false; 4660 } 4661 return true; 4662 } 4663 4664 // gfx90a has an undocumented limitation: 4665 // DS_GWS opcodes must use even aligned registers. 4666 bool AMDGPUAsmParser::validateGWS(const MCInst &Inst, 4667 const OperandVector &Operands) { 4668 if (!getFeatureBits()[AMDGPU::FeatureGFX90AInsts]) 4669 return true; 4670 4671 int Opc = Inst.getOpcode(); 4672 if (Opc != AMDGPU::DS_GWS_INIT_vi && Opc != AMDGPU::DS_GWS_BARRIER_vi && 4673 Opc != AMDGPU::DS_GWS_SEMA_BR_vi) 4674 return true; 4675 4676 const MCRegisterInfo *MRI = getMRI(); 4677 const MCRegisterClass &VGPR32 = MRI->getRegClass(AMDGPU::VGPR_32RegClassID); 4678 int Data0Pos = 4679 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::data0); 4680 assert(Data0Pos != -1); 4681 auto Reg = Inst.getOperand(Data0Pos).getReg(); 4682 auto RegIdx = Reg - (VGPR32.contains(Reg) ? AMDGPU::VGPR0 : AMDGPU::AGPR0); 4683 if (RegIdx & 1) { 4684 SMLoc RegLoc = getRegLoc(Reg, Operands); 4685 Error(RegLoc, "vgpr must be even aligned"); 4686 return false; 4687 } 4688 4689 return true; 4690 } 4691 4692 bool AMDGPUAsmParser::validateCoherencyBits(const MCInst &Inst, 4693 const OperandVector &Operands, 4694 const SMLoc &IDLoc) { 4695 int CPolPos = AMDGPU::getNamedOperandIdx(Inst.getOpcode(), 4696 AMDGPU::OpName::cpol); 4697 if (CPolPos == -1) 4698 return true; 4699 4700 unsigned CPol = Inst.getOperand(CPolPos).getImm(); 4701 4702 if (isGFX12Plus()) 4703 return validateTHAndScopeBits(Inst, Operands, CPol); 4704 4705 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 4706 if (TSFlags & SIInstrFlags::SMRD) { 4707 if (CPol && (isSI() || isCI())) { 4708 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands); 4709 Error(S, "cache policy is not supported for SMRD instructions"); 4710 return false; 4711 } 4712 if (CPol & ~(AMDGPU::CPol::GLC | AMDGPU::CPol::DLC)) { 4713 Error(IDLoc, "invalid cache policy for SMEM instruction"); 4714 return false; 4715 } 4716 } 4717 4718 if (isGFX90A() && !isGFX940() && (CPol & CPol::SCC)) { 4719 const uint64_t AllowSCCModifier = SIInstrFlags::MUBUF | 4720 SIInstrFlags::MTBUF | SIInstrFlags::MIMG | 4721 SIInstrFlags::FLAT; 4722 if (!(TSFlags & AllowSCCModifier)) { 4723 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands); 4724 StringRef CStr(S.getPointer()); 4725 S = SMLoc::getFromPointer(&CStr.data()[CStr.find("scc")]); 4726 Error(S, 4727 "scc modifier is not supported for this instruction on this GPU"); 4728 return false; 4729 } 4730 } 4731 4732 if (!(TSFlags & (SIInstrFlags::IsAtomicNoRet | SIInstrFlags::IsAtomicRet))) 4733 return true; 4734 4735 if (TSFlags & SIInstrFlags::IsAtomicRet) { 4736 if (!(TSFlags & SIInstrFlags::MIMG) && !(CPol & CPol::GLC)) { 4737 Error(IDLoc, isGFX940() ? "instruction must use sc0" 4738 : "instruction must use glc"); 4739 return false; 4740 } 4741 } else { 4742 if (CPol & CPol::GLC) { 4743 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands); 4744 StringRef CStr(S.getPointer()); 4745 S = SMLoc::getFromPointer( 4746 &CStr.data()[CStr.find(isGFX940() ? "sc0" : "glc")]); 4747 Error(S, isGFX940() ? "instruction must not use sc0" 4748 : "instruction must not use glc"); 4749 return false; 4750 } 4751 } 4752 4753 return true; 4754 } 4755 4756 bool AMDGPUAsmParser::validateTHAndScopeBits(const MCInst &Inst, 4757 const OperandVector &Operands, 4758 const unsigned CPol) { 4759 const unsigned TH = CPol & AMDGPU::CPol::TH; 4760 const unsigned Scope = CPol & AMDGPU::CPol::SCOPE; 4761 4762 const unsigned Opcode = Inst.getOpcode(); 4763 const MCInstrDesc &TID = MII.get(Opcode); 4764 4765 auto PrintError = [&](StringRef Msg) { 4766 SMLoc S = getImmLoc(AMDGPUOperand::ImmTyCPol, Operands); 4767 Error(S, Msg); 4768 return false; 4769 }; 4770 4771 if ((TID.TSFlags & SIInstrFlags::IsAtomicRet) && 4772 (TID.TSFlags & (SIInstrFlags::FLAT | SIInstrFlags::MUBUF)) && 4773 (!(TH & AMDGPU::CPol::TH_ATOMIC_RETURN))) 4774 return PrintError("instruction must use th:TH_ATOMIC_RETURN"); 4775 4776 if (TH == 0) 4777 return true; 4778 4779 if ((TID.TSFlags & SIInstrFlags::SMRD) && 4780 ((TH == AMDGPU::CPol::TH_NT_RT) || (TH == AMDGPU::CPol::TH_RT_NT) || 4781 (TH == AMDGPU::CPol::TH_NT_HT))) 4782 return PrintError("invalid th value for SMEM instruction"); 4783 4784 if (TH == AMDGPU::CPol::TH_BYPASS) { 4785 if ((Scope != AMDGPU::CPol::SCOPE_SYS && 4786 CPol & AMDGPU::CPol::TH_REAL_BYPASS) || 4787 (Scope == AMDGPU::CPol::SCOPE_SYS && 4788 !(CPol & AMDGPU::CPol::TH_REAL_BYPASS))) 4789 return PrintError("scope and th combination is not valid"); 4790 } 4791 4792 bool IsStore = TID.mayStore(); 4793 bool IsAtomic = 4794 TID.TSFlags & (SIInstrFlags::IsAtomicNoRet | SIInstrFlags::IsAtomicRet); 4795 4796 if (IsAtomic) { 4797 if (!(CPol & AMDGPU::CPol::TH_TYPE_ATOMIC)) 4798 return PrintError("invalid th value for atomic instructions"); 4799 } else if (IsStore) { 4800 if (!(CPol & AMDGPU::CPol::TH_TYPE_STORE)) 4801 return PrintError("invalid th value for store instructions"); 4802 } else { 4803 if (!(CPol & AMDGPU::CPol::TH_TYPE_LOAD)) 4804 return PrintError("invalid th value for load instructions"); 4805 } 4806 4807 return true; 4808 } 4809 4810 bool AMDGPUAsmParser::validateExeczVcczOperands(const OperandVector &Operands) { 4811 if (!isGFX11Plus()) 4812 return true; 4813 for (auto &Operand : Operands) { 4814 if (!Operand->isReg()) 4815 continue; 4816 unsigned Reg = Operand->getReg(); 4817 if (Reg == SRC_EXECZ || Reg == SRC_VCCZ) { 4818 Error(getRegLoc(Reg, Operands), 4819 "execz and vccz are not supported on this GPU"); 4820 return false; 4821 } 4822 } 4823 return true; 4824 } 4825 4826 bool AMDGPUAsmParser::validateTFE(const MCInst &Inst, 4827 const OperandVector &Operands) { 4828 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 4829 if (Desc.mayStore() && 4830 (Desc.TSFlags & (SIInstrFlags::MUBUF | SIInstrFlags::MTBUF))) { 4831 SMLoc Loc = getImmLoc(AMDGPUOperand::ImmTyTFE, Operands); 4832 if (Loc != getInstLoc(Operands)) { 4833 Error(Loc, "TFE modifier has no meaning for store instructions"); 4834 return false; 4835 } 4836 } 4837 4838 return true; 4839 } 4840 4841 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, 4842 const SMLoc &IDLoc, 4843 const OperandVector &Operands) { 4844 if (auto ErrMsg = validateLdsDirect(Inst)) { 4845 Error(getRegLoc(LDS_DIRECT, Operands), *ErrMsg); 4846 return false; 4847 } 4848 if (!validateSOPLiteral(Inst)) { 4849 Error(getLitLoc(Operands), 4850 "only one unique literal operand is allowed"); 4851 return false; 4852 } 4853 if (!validateVOPLiteral(Inst, Operands)) { 4854 return false; 4855 } 4856 if (!validateConstantBusLimitations(Inst, Operands)) { 4857 return false; 4858 } 4859 if (!validateVOPDRegBankConstraints(Inst, Operands)) { 4860 return false; 4861 } 4862 if (!validateIntClampSupported(Inst)) { 4863 Error(getImmLoc(AMDGPUOperand::ImmTyClampSI, Operands), 4864 "integer clamping is not supported on this GPU"); 4865 return false; 4866 } 4867 if (!validateOpSel(Inst)) { 4868 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands), 4869 "invalid op_sel operand"); 4870 return false; 4871 } 4872 if (!validateNeg(Inst, AMDGPU::OpName::neg_lo)) { 4873 Error(getImmLoc(AMDGPUOperand::ImmTyNegLo, Operands), 4874 "invalid neg_lo operand"); 4875 return false; 4876 } 4877 if (!validateNeg(Inst, AMDGPU::OpName::neg_hi)) { 4878 Error(getImmLoc(AMDGPUOperand::ImmTyNegHi, Operands), 4879 "invalid neg_hi operand"); 4880 return false; 4881 } 4882 if (!validateDPP(Inst, Operands)) { 4883 return false; 4884 } 4885 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate. 4886 if (!validateMIMGD16(Inst)) { 4887 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands), 4888 "d16 modifier is not supported on this GPU"); 4889 return false; 4890 } 4891 if (!validateMIMGMSAA(Inst)) { 4892 Error(getImmLoc(AMDGPUOperand::ImmTyDim, Operands), 4893 "invalid dim; must be MSAA type"); 4894 return false; 4895 } 4896 if (!validateMIMGDataSize(Inst, IDLoc)) { 4897 return false; 4898 } 4899 if (!validateMIMGAddrSize(Inst, IDLoc)) 4900 return false; 4901 if (!validateMIMGAtomicDMask(Inst)) { 4902 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands), 4903 "invalid atomic image dmask"); 4904 return false; 4905 } 4906 if (!validateMIMGGatherDMask(Inst)) { 4907 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands), 4908 "invalid image_gather dmask: only one bit must be set"); 4909 return false; 4910 } 4911 if (!validateMovrels(Inst, Operands)) { 4912 return false; 4913 } 4914 if (!validateOffset(Inst, Operands)) { 4915 return false; 4916 } 4917 if (!validateMAIAccWrite(Inst, Operands)) { 4918 return false; 4919 } 4920 if (!validateMAISrc2(Inst, Operands)) { 4921 return false; 4922 } 4923 if (!validateMFMA(Inst, Operands)) { 4924 return false; 4925 } 4926 if (!validateCoherencyBits(Inst, Operands, IDLoc)) { 4927 return false; 4928 } 4929 4930 if (!validateAGPRLdSt(Inst)) { 4931 Error(IDLoc, getFeatureBits()[AMDGPU::FeatureGFX90AInsts] 4932 ? "invalid register class: data and dst should be all VGPR or AGPR" 4933 : "invalid register class: agpr loads and stores not supported on this GPU" 4934 ); 4935 return false; 4936 } 4937 if (!validateVGPRAlign(Inst)) { 4938 Error(IDLoc, 4939 "invalid register class: vgpr tuples must be 64 bit aligned"); 4940 return false; 4941 } 4942 if (!validateDS(Inst, Operands)) { 4943 return false; 4944 } 4945 4946 if (!validateBLGP(Inst, Operands)) { 4947 return false; 4948 } 4949 4950 if (!validateDivScale(Inst)) { 4951 Error(IDLoc, "ABS not allowed in VOP3B instructions"); 4952 return false; 4953 } 4954 if (!validateWaitCnt(Inst, Operands)) { 4955 return false; 4956 } 4957 if (!validateExeczVcczOperands(Operands)) { 4958 return false; 4959 } 4960 if (!validateTFE(Inst, Operands)) { 4961 return false; 4962 } 4963 4964 return true; 4965 } 4966 4967 static std::string AMDGPUMnemonicSpellCheck(StringRef S, 4968 const FeatureBitset &FBS, 4969 unsigned VariantID = 0); 4970 4971 static bool AMDGPUCheckMnemonic(StringRef Mnemonic, 4972 const FeatureBitset &AvailableFeatures, 4973 unsigned VariantID); 4974 4975 bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo, 4976 const FeatureBitset &FBS) { 4977 return isSupportedMnemo(Mnemo, FBS, getAllVariants()); 4978 } 4979 4980 bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo, 4981 const FeatureBitset &FBS, 4982 ArrayRef<unsigned> Variants) { 4983 for (auto Variant : Variants) { 4984 if (AMDGPUCheckMnemonic(Mnemo, FBS, Variant)) 4985 return true; 4986 } 4987 4988 return false; 4989 } 4990 4991 bool AMDGPUAsmParser::checkUnsupportedInstruction(StringRef Mnemo, 4992 const SMLoc &IDLoc) { 4993 FeatureBitset FBS = ComputeAvailableFeatures(getFeatureBits()); 4994 4995 // Check if requested instruction variant is supported. 4996 if (isSupportedMnemo(Mnemo, FBS, getMatchedVariants())) 4997 return false; 4998 4999 // This instruction is not supported. 5000 // Clear any other pending errors because they are no longer relevant. 5001 getParser().clearPendingErrors(); 5002 5003 // Requested instruction variant is not supported. 5004 // Check if any other variants are supported. 5005 StringRef VariantName = getMatchedVariantName(); 5006 if (!VariantName.empty() && isSupportedMnemo(Mnemo, FBS)) { 5007 return Error(IDLoc, 5008 Twine(VariantName, 5009 " variant of this instruction is not supported")); 5010 } 5011 5012 // Check if this instruction may be used with a different wavesize. 5013 if (isGFX10Plus() && getFeatureBits()[AMDGPU::FeatureWavefrontSize64] && 5014 !getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) { 5015 5016 FeatureBitset FeaturesWS32 = getFeatureBits(); 5017 FeaturesWS32.flip(AMDGPU::FeatureWavefrontSize64) 5018 .flip(AMDGPU::FeatureWavefrontSize32); 5019 FeatureBitset AvailableFeaturesWS32 = 5020 ComputeAvailableFeatures(FeaturesWS32); 5021 5022 if (isSupportedMnemo(Mnemo, AvailableFeaturesWS32, getMatchedVariants())) 5023 return Error(IDLoc, "instruction requires wavesize=32"); 5024 } 5025 5026 // Finally check if this instruction is supported on any other GPU. 5027 if (isSupportedMnemo(Mnemo, FeatureBitset().set())) { 5028 return Error(IDLoc, "instruction not supported on this GPU"); 5029 } 5030 5031 // Instruction not supported on any GPU. Probably a typo. 5032 std::string Suggestion = AMDGPUMnemonicSpellCheck(Mnemo, FBS); 5033 return Error(IDLoc, "invalid instruction" + Suggestion); 5034 } 5035 5036 static bool isInvalidVOPDY(const OperandVector &Operands, 5037 uint64_t InvalidOprIdx) { 5038 assert(InvalidOprIdx < Operands.size()); 5039 const auto &Op = ((AMDGPUOperand &)*Operands[InvalidOprIdx]); 5040 if (Op.isToken() && InvalidOprIdx > 1) { 5041 const auto &PrevOp = ((AMDGPUOperand &)*Operands[InvalidOprIdx - 1]); 5042 return PrevOp.isToken() && PrevOp.getToken() == "::"; 5043 } 5044 return false; 5045 } 5046 5047 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 5048 OperandVector &Operands, 5049 MCStreamer &Out, 5050 uint64_t &ErrorInfo, 5051 bool MatchingInlineAsm) { 5052 MCInst Inst; 5053 unsigned Result = Match_Success; 5054 for (auto Variant : getMatchedVariants()) { 5055 uint64_t EI; 5056 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, 5057 Variant); 5058 // We order match statuses from least to most specific. We use most specific 5059 // status as resulting 5060 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 5061 if ((R == Match_Success) || 5062 (R == Match_PreferE32) || 5063 (R == Match_MissingFeature && Result != Match_PreferE32) || 5064 (R == Match_InvalidOperand && Result != Match_MissingFeature 5065 && Result != Match_PreferE32) || 5066 (R == Match_MnemonicFail && Result != Match_InvalidOperand 5067 && Result != Match_MissingFeature 5068 && Result != Match_PreferE32)) { 5069 Result = R; 5070 ErrorInfo = EI; 5071 } 5072 if (R == Match_Success) 5073 break; 5074 } 5075 5076 if (Result == Match_Success) { 5077 if (!validateInstruction(Inst, IDLoc, Operands)) { 5078 return true; 5079 } 5080 Inst.setLoc(IDLoc); 5081 Out.emitInstruction(Inst, getSTI()); 5082 return false; 5083 } 5084 5085 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken(); 5086 if (checkUnsupportedInstruction(Mnemo, IDLoc)) { 5087 return true; 5088 } 5089 5090 switch (Result) { 5091 default: break; 5092 case Match_MissingFeature: 5093 // It has been verified that the specified instruction 5094 // mnemonic is valid. A match was found but it requires 5095 // features which are not supported on this GPU. 5096 return Error(IDLoc, "operands are not valid for this GPU or mode"); 5097 5098 case Match_InvalidOperand: { 5099 SMLoc ErrorLoc = IDLoc; 5100 if (ErrorInfo != ~0ULL) { 5101 if (ErrorInfo >= Operands.size()) { 5102 return Error(IDLoc, "too few operands for instruction"); 5103 } 5104 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 5105 if (ErrorLoc == SMLoc()) 5106 ErrorLoc = IDLoc; 5107 5108 if (isInvalidVOPDY(Operands, ErrorInfo)) 5109 return Error(ErrorLoc, "invalid VOPDY instruction"); 5110 } 5111 return Error(ErrorLoc, "invalid operand for instruction"); 5112 } 5113 5114 case Match_PreferE32: 5115 return Error(IDLoc, "internal error: instruction without _e64 suffix " 5116 "should be encoded as e32"); 5117 case Match_MnemonicFail: 5118 llvm_unreachable("Invalid instructions should have been handled already"); 5119 } 5120 llvm_unreachable("Implement any new match types added!"); 5121 } 5122 5123 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) { 5124 int64_t Tmp = -1; 5125 if (!isToken(AsmToken::Integer) && !isToken(AsmToken::Identifier)) { 5126 return true; 5127 } 5128 if (getParser().parseAbsoluteExpression(Tmp)) { 5129 return true; 5130 } 5131 Ret = static_cast<uint32_t>(Tmp); 5132 return false; 5133 } 5134 5135 bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() { 5136 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 5137 return TokError("directive only supported for amdgcn architecture"); 5138 5139 std::string TargetIDDirective; 5140 SMLoc TargetStart = getTok().getLoc(); 5141 if (getParser().parseEscapedString(TargetIDDirective)) 5142 return true; 5143 5144 SMRange TargetRange = SMRange(TargetStart, getTok().getLoc()); 5145 if (getTargetStreamer().getTargetID()->toString() != TargetIDDirective) 5146 return getParser().Error(TargetRange.Start, 5147 (Twine(".amdgcn_target directive's target id ") + 5148 Twine(TargetIDDirective) + 5149 Twine(" does not match the specified target id ") + 5150 Twine(getTargetStreamer().getTargetID()->toString())).str()); 5151 5152 return false; 5153 } 5154 5155 bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) { 5156 return Error(Range.Start, "value out of range", Range); 5157 } 5158 5159 bool AMDGPUAsmParser::calculateGPRBlocks( 5160 const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed, 5161 bool XNACKUsed, std::optional<bool> EnableWavefrontSize32, 5162 unsigned NextFreeVGPR, SMRange VGPRRange, unsigned NextFreeSGPR, 5163 SMRange SGPRRange, unsigned &VGPRBlocks, unsigned &SGPRBlocks) { 5164 // TODO(scott.linder): These calculations are duplicated from 5165 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified. 5166 IsaVersion Version = getIsaVersion(getSTI().getCPU()); 5167 5168 unsigned NumVGPRs = NextFreeVGPR; 5169 unsigned NumSGPRs = NextFreeSGPR; 5170 5171 if (Version.Major >= 10) 5172 NumSGPRs = 0; 5173 else { 5174 unsigned MaxAddressableNumSGPRs = 5175 IsaInfo::getAddressableNumSGPRs(&getSTI()); 5176 5177 if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) && 5178 NumSGPRs > MaxAddressableNumSGPRs) 5179 return OutOfRangeError(SGPRRange); 5180 5181 NumSGPRs += 5182 IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed); 5183 5184 if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) && 5185 NumSGPRs > MaxAddressableNumSGPRs) 5186 return OutOfRangeError(SGPRRange); 5187 5188 if (Features.test(FeatureSGPRInitBug)) 5189 NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG; 5190 } 5191 5192 VGPRBlocks = 5193 IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs, EnableWavefrontSize32); 5194 SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs); 5195 5196 return false; 5197 } 5198 5199 bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { 5200 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 5201 return TokError("directive only supported for amdgcn architecture"); 5202 5203 if (!isHsaAbi(getSTI())) 5204 return TokError("directive only supported for amdhsa OS"); 5205 5206 StringRef KernelName; 5207 if (getParser().parseIdentifier(KernelName)) 5208 return true; 5209 5210 kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI()); 5211 5212 StringSet<> Seen; 5213 5214 IsaVersion IVersion = getIsaVersion(getSTI().getCPU()); 5215 5216 SMRange VGPRRange; 5217 uint64_t NextFreeVGPR = 0; 5218 uint64_t AccumOffset = 0; 5219 uint64_t SharedVGPRCount = 0; 5220 uint64_t PreloadLength = 0; 5221 uint64_t PreloadOffset = 0; 5222 SMRange SGPRRange; 5223 uint64_t NextFreeSGPR = 0; 5224 5225 // Count the number of user SGPRs implied from the enabled feature bits. 5226 unsigned ImpliedUserSGPRCount = 0; 5227 5228 // Track if the asm explicitly contains the directive for the user SGPR 5229 // count. 5230 std::optional<unsigned> ExplicitUserSGPRCount; 5231 bool ReserveVCC = true; 5232 bool ReserveFlatScr = true; 5233 std::optional<bool> EnableWavefrontSize32; 5234 5235 while (true) { 5236 while (trySkipToken(AsmToken::EndOfStatement)); 5237 5238 StringRef ID; 5239 SMRange IDRange = getTok().getLocRange(); 5240 if (!parseId(ID, "expected .amdhsa_ directive or .end_amdhsa_kernel")) 5241 return true; 5242 5243 if (ID == ".end_amdhsa_kernel") 5244 break; 5245 5246 if (!Seen.insert(ID).second) 5247 return TokError(".amdhsa_ directives cannot be repeated"); 5248 5249 SMLoc ValStart = getLoc(); 5250 int64_t IVal; 5251 if (getParser().parseAbsoluteExpression(IVal)) 5252 return true; 5253 SMLoc ValEnd = getLoc(); 5254 SMRange ValRange = SMRange(ValStart, ValEnd); 5255 5256 if (IVal < 0) 5257 return OutOfRangeError(ValRange); 5258 5259 uint64_t Val = IVal; 5260 5261 #define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ 5262 if (!isUInt<ENTRY##_WIDTH>(VALUE)) \ 5263 return OutOfRangeError(RANGE); \ 5264 AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); 5265 5266 if (ID == ".amdhsa_group_segment_fixed_size") { 5267 if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val)) 5268 return OutOfRangeError(ValRange); 5269 KD.group_segment_fixed_size = Val; 5270 } else if (ID == ".amdhsa_private_segment_fixed_size") { 5271 if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val)) 5272 return OutOfRangeError(ValRange); 5273 KD.private_segment_fixed_size = Val; 5274 } else if (ID == ".amdhsa_kernarg_size") { 5275 if (!isUInt<sizeof(KD.kernarg_size) * CHAR_BIT>(Val)) 5276 return OutOfRangeError(ValRange); 5277 KD.kernarg_size = Val; 5278 } else if (ID == ".amdhsa_user_sgpr_count") { 5279 ExplicitUserSGPRCount = Val; 5280 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") { 5281 if (hasArchitectedFlatScratch()) 5282 return Error(IDRange.Start, 5283 "directive is not supported with architected flat scratch", 5284 IDRange); 5285 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5286 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 5287 Val, ValRange); 5288 if (Val) 5289 ImpliedUserSGPRCount += 4; 5290 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") { 5291 if (!hasKernargPreload()) 5292 return Error(IDRange.Start, "directive requires gfx90a+", IDRange); 5293 5294 if (Val > getMaxNumUserSGPRs()) 5295 return OutOfRangeError(ValRange); 5296 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, Val, 5297 ValRange); 5298 if (Val) { 5299 ImpliedUserSGPRCount += Val; 5300 PreloadLength = Val; 5301 } 5302 } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") { 5303 if (!hasKernargPreload()) 5304 return Error(IDRange.Start, "directive requires gfx90a+", IDRange); 5305 5306 if (Val >= 1024) 5307 return OutOfRangeError(ValRange); 5308 PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, Val, 5309 ValRange); 5310 if (Val) 5311 PreloadOffset = Val; 5312 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") { 5313 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5314 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val, 5315 ValRange); 5316 if (Val) 5317 ImpliedUserSGPRCount += 2; 5318 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") { 5319 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5320 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val, 5321 ValRange); 5322 if (Val) 5323 ImpliedUserSGPRCount += 2; 5324 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") { 5325 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5326 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, 5327 Val, ValRange); 5328 if (Val) 5329 ImpliedUserSGPRCount += 2; 5330 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") { 5331 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5332 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val, 5333 ValRange); 5334 if (Val) 5335 ImpliedUserSGPRCount += 2; 5336 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") { 5337 if (hasArchitectedFlatScratch()) 5338 return Error(IDRange.Start, 5339 "directive is not supported with architected flat scratch", 5340 IDRange); 5341 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5342 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val, 5343 ValRange); 5344 if (Val) 5345 ImpliedUserSGPRCount += 2; 5346 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") { 5347 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5348 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 5349 Val, ValRange); 5350 if (Val) 5351 ImpliedUserSGPRCount += 1; 5352 } else if (ID == ".amdhsa_wavefront_size32") { 5353 if (IVersion.Major < 10) 5354 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 5355 EnableWavefrontSize32 = Val; 5356 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5357 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, 5358 Val, ValRange); 5359 } else if (ID == ".amdhsa_uses_dynamic_stack") { 5360 PARSE_BITS_ENTRY(KD.kernel_code_properties, 5361 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, Val, ValRange); 5362 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") { 5363 if (hasArchitectedFlatScratch()) 5364 return Error(IDRange.Start, 5365 "directive is not supported with architected flat scratch", 5366 IDRange); 5367 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5368 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); 5369 } else if (ID == ".amdhsa_enable_private_segment") { 5370 if (!hasArchitectedFlatScratch()) 5371 return Error( 5372 IDRange.Start, 5373 "directive is not supported without architected flat scratch", 5374 IDRange); 5375 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5376 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); 5377 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") { 5378 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5379 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val, 5380 ValRange); 5381 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") { 5382 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5383 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val, 5384 ValRange); 5385 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") { 5386 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5387 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val, 5388 ValRange); 5389 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") { 5390 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5391 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val, 5392 ValRange); 5393 } else if (ID == ".amdhsa_system_vgpr_workitem_id") { 5394 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5395 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val, 5396 ValRange); 5397 } else if (ID == ".amdhsa_next_free_vgpr") { 5398 VGPRRange = ValRange; 5399 NextFreeVGPR = Val; 5400 } else if (ID == ".amdhsa_next_free_sgpr") { 5401 SGPRRange = ValRange; 5402 NextFreeSGPR = Val; 5403 } else if (ID == ".amdhsa_accum_offset") { 5404 if (!isGFX90A()) 5405 return Error(IDRange.Start, "directive requires gfx90a+", IDRange); 5406 AccumOffset = Val; 5407 } else if (ID == ".amdhsa_reserve_vcc") { 5408 if (!isUInt<1>(Val)) 5409 return OutOfRangeError(ValRange); 5410 ReserveVCC = Val; 5411 } else if (ID == ".amdhsa_reserve_flat_scratch") { 5412 if (IVersion.Major < 7) 5413 return Error(IDRange.Start, "directive requires gfx7+", IDRange); 5414 if (hasArchitectedFlatScratch()) 5415 return Error(IDRange.Start, 5416 "directive is not supported with architected flat scratch", 5417 IDRange); 5418 if (!isUInt<1>(Val)) 5419 return OutOfRangeError(ValRange); 5420 ReserveFlatScr = Val; 5421 } else if (ID == ".amdhsa_reserve_xnack_mask") { 5422 if (IVersion.Major < 8) 5423 return Error(IDRange.Start, "directive requires gfx8+", IDRange); 5424 if (!isUInt<1>(Val)) 5425 return OutOfRangeError(ValRange); 5426 if (Val != getTargetStreamer().getTargetID()->isXnackOnOrAny()) 5427 return getParser().Error(IDRange.Start, ".amdhsa_reserve_xnack_mask does not match target id", 5428 IDRange); 5429 } else if (ID == ".amdhsa_float_round_mode_32") { 5430 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5431 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange); 5432 } else if (ID == ".amdhsa_float_round_mode_16_64") { 5433 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5434 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange); 5435 } else if (ID == ".amdhsa_float_denorm_mode_32") { 5436 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5437 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange); 5438 } else if (ID == ".amdhsa_float_denorm_mode_16_64") { 5439 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5440 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val, 5441 ValRange); 5442 } else if (ID == ".amdhsa_dx10_clamp") { 5443 if (IVersion.Major >= 12) 5444 return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); 5445 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5446 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, Val, 5447 ValRange); 5448 } else if (ID == ".amdhsa_ieee_mode") { 5449 if (IVersion.Major >= 12) 5450 return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); 5451 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5452 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, Val, 5453 ValRange); 5454 } else if (ID == ".amdhsa_fp16_overflow") { 5455 if (IVersion.Major < 9) 5456 return Error(IDRange.Start, "directive requires gfx9+", IDRange); 5457 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, Val, 5458 ValRange); 5459 } else if (ID == ".amdhsa_tg_split") { 5460 if (!isGFX90A()) 5461 return Error(IDRange.Start, "directive requires gfx90a+", IDRange); 5462 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Val, 5463 ValRange); 5464 } else if (ID == ".amdhsa_workgroup_processor_mode") { 5465 if (IVersion.Major < 10) 5466 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 5467 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, Val, 5468 ValRange); 5469 } else if (ID == ".amdhsa_memory_ordered") { 5470 if (IVersion.Major < 10) 5471 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 5472 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, Val, 5473 ValRange); 5474 } else if (ID == ".amdhsa_forward_progress") { 5475 if (IVersion.Major < 10) 5476 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 5477 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, Val, 5478 ValRange); 5479 } else if (ID == ".amdhsa_shared_vgpr_count") { 5480 if (IVersion.Major < 10 || IVersion.Major >= 12) 5481 return Error(IDRange.Start, "directive requires gfx10 or gfx11", 5482 IDRange); 5483 SharedVGPRCount = Val; 5484 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, 5485 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, Val, 5486 ValRange); 5487 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { 5488 PARSE_BITS_ENTRY( 5489 KD.compute_pgm_rsrc2, 5490 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val, 5491 ValRange); 5492 } else if (ID == ".amdhsa_exception_fp_denorm_src") { 5493 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5494 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 5495 Val, ValRange); 5496 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") { 5497 PARSE_BITS_ENTRY( 5498 KD.compute_pgm_rsrc2, 5499 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val, 5500 ValRange); 5501 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") { 5502 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5503 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 5504 Val, ValRange); 5505 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") { 5506 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5507 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 5508 Val, ValRange); 5509 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") { 5510 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5511 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 5512 Val, ValRange); 5513 } else if (ID == ".amdhsa_exception_int_div_zero") { 5514 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 5515 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 5516 Val, ValRange); 5517 } else if (ID == ".amdhsa_round_robin_scheduling") { 5518 if (IVersion.Major < 12) 5519 return Error(IDRange.Start, "directive requires gfx12+", IDRange); 5520 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 5521 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, Val, 5522 ValRange); 5523 } else { 5524 return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange); 5525 } 5526 5527 #undef PARSE_BITS_ENTRY 5528 } 5529 5530 if (!Seen.contains(".amdhsa_next_free_vgpr")) 5531 return TokError(".amdhsa_next_free_vgpr directive is required"); 5532 5533 if (!Seen.contains(".amdhsa_next_free_sgpr")) 5534 return TokError(".amdhsa_next_free_sgpr directive is required"); 5535 5536 unsigned VGPRBlocks; 5537 unsigned SGPRBlocks; 5538 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr, 5539 getTargetStreamer().getTargetID()->isXnackOnOrAny(), 5540 EnableWavefrontSize32, NextFreeVGPR, 5541 VGPRRange, NextFreeSGPR, SGPRRange, VGPRBlocks, 5542 SGPRBlocks)) 5543 return true; 5544 5545 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>( 5546 VGPRBlocks)) 5547 return OutOfRangeError(VGPRRange); 5548 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 5549 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks); 5550 5551 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>( 5552 SGPRBlocks)) 5553 return OutOfRangeError(SGPRRange); 5554 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 5555 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, 5556 SGPRBlocks); 5557 5558 if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount) 5559 return TokError("amdgpu_user_sgpr_count smaller than than implied by " 5560 "enabled user SGPRs"); 5561 5562 unsigned UserSGPRCount = 5563 ExplicitUserSGPRCount ? *ExplicitUserSGPRCount : ImpliedUserSGPRCount; 5564 5565 if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount)) 5566 return TokError("too many user SGPRs enabled"); 5567 AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, 5568 UserSGPRCount); 5569 5570 if (PreloadLength && KD.kernarg_size && 5571 (PreloadLength * 4 + PreloadOffset * 4 > KD.kernarg_size)) 5572 return TokError("Kernarg preload length + offset is larger than the " 5573 "kernarg segment size"); 5574 5575 if (isGFX90A()) { 5576 if (!Seen.contains(".amdhsa_accum_offset")) 5577 return TokError(".amdhsa_accum_offset directive is required"); 5578 if (AccumOffset < 4 || AccumOffset > 256 || (AccumOffset & 3)) 5579 return TokError("accum_offset should be in range [4..256] in " 5580 "increments of 4"); 5581 if (AccumOffset > alignTo(std::max((uint64_t)1, NextFreeVGPR), 4)) 5582 return TokError("accum_offset exceeds total VGPR allocation"); 5583 AMDHSA_BITS_SET(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, 5584 (AccumOffset / 4 - 1)); 5585 } 5586 5587 if (IVersion.Major >= 10 && IVersion.Major < 12) { 5588 // SharedVGPRCount < 16 checked by PARSE_ENTRY_BITS 5589 if (SharedVGPRCount && EnableWavefrontSize32 && *EnableWavefrontSize32) { 5590 return TokError("shared_vgpr_count directive not valid on " 5591 "wavefront size 32"); 5592 } 5593 if (SharedVGPRCount * 2 + VGPRBlocks > 63) { 5594 return TokError("shared_vgpr_count*2 + " 5595 "compute_pgm_rsrc1.GRANULATED_WORKITEM_VGPR_COUNT cannot " 5596 "exceed 63\n"); 5597 } 5598 } 5599 5600 getTargetStreamer().EmitAmdhsaKernelDescriptor(getSTI(), KernelName, KD, 5601 NextFreeVGPR, NextFreeSGPR, 5602 ReserveVCC, ReserveFlatScr); 5603 return false; 5604 } 5605 5606 bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() { 5607 uint32_t Version; 5608 if (ParseAsAbsoluteExpression(Version)) 5609 return true; 5610 5611 getTargetStreamer().EmitDirectiveAMDHSACodeObjectVersion(Version); 5612 return false; 5613 } 5614 5615 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 5616 amd_kernel_code_t &Header) { 5617 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing 5618 // assembly for backwards compatibility. 5619 if (ID == "max_scratch_backing_memory_byte_size") { 5620 Parser.eatToEndOfStatement(); 5621 return false; 5622 } 5623 5624 SmallString<40> ErrStr; 5625 raw_svector_ostream Err(ErrStr); 5626 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) { 5627 return TokError(Err.str()); 5628 } 5629 Lex(); 5630 5631 if (ID == "enable_dx10_clamp") { 5632 if (G_00B848_DX10_CLAMP(Header.compute_pgm_resource_registers) && 5633 isGFX12Plus()) 5634 return TokError("enable_dx10_clamp=1 is not allowed on GFX12+"); 5635 } 5636 5637 if (ID == "enable_ieee_mode") { 5638 if (G_00B848_IEEE_MODE(Header.compute_pgm_resource_registers) && 5639 isGFX12Plus()) 5640 return TokError("enable_ieee_mode=1 is not allowed on GFX12+"); 5641 } 5642 5643 if (ID == "enable_wavefront_size32") { 5644 if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) { 5645 if (!isGFX10Plus()) 5646 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+"); 5647 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 5648 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32"); 5649 } else { 5650 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 5651 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64"); 5652 } 5653 } 5654 5655 if (ID == "wavefront_size") { 5656 if (Header.wavefront_size == 5) { 5657 if (!isGFX10Plus()) 5658 return TokError("wavefront_size=5 is only allowed on GFX10+"); 5659 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 5660 return TokError("wavefront_size=5 requires +WavefrontSize32"); 5661 } else if (Header.wavefront_size == 6) { 5662 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 5663 return TokError("wavefront_size=6 requires +WavefrontSize64"); 5664 } 5665 } 5666 5667 if (ID == "enable_wgp_mode") { 5668 if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && 5669 !isGFX10Plus()) 5670 return TokError("enable_wgp_mode=1 is only allowed on GFX10+"); 5671 } 5672 5673 if (ID == "enable_mem_ordered") { 5674 if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && 5675 !isGFX10Plus()) 5676 return TokError("enable_mem_ordered=1 is only allowed on GFX10+"); 5677 } 5678 5679 if (ID == "enable_fwd_progress") { 5680 if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && 5681 !isGFX10Plus()) 5682 return TokError("enable_fwd_progress=1 is only allowed on GFX10+"); 5683 } 5684 5685 return false; 5686 } 5687 5688 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 5689 amd_kernel_code_t Header; 5690 AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI()); 5691 5692 while (true) { 5693 // Lex EndOfStatement. This is in a while loop, because lexing a comment 5694 // will set the current token to EndOfStatement. 5695 while(trySkipToken(AsmToken::EndOfStatement)); 5696 5697 StringRef ID; 5698 if (!parseId(ID, "expected value identifier or .end_amd_kernel_code_t")) 5699 return true; 5700 5701 if (ID == ".end_amd_kernel_code_t") 5702 break; 5703 5704 if (ParseAMDKernelCodeTValue(ID, Header)) 5705 return true; 5706 } 5707 5708 getTargetStreamer().EmitAMDKernelCodeT(Header); 5709 5710 return false; 5711 } 5712 5713 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 5714 StringRef KernelName; 5715 if (!parseId(KernelName, "expected symbol name")) 5716 return true; 5717 5718 getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 5719 ELF::STT_AMDGPU_HSA_KERNEL); 5720 5721 KernelScope.initialize(getContext()); 5722 return false; 5723 } 5724 5725 bool AMDGPUAsmParser::ParseDirectiveISAVersion() { 5726 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) { 5727 return Error(getLoc(), 5728 ".amd_amdgpu_isa directive is not available on non-amdgcn " 5729 "architectures"); 5730 } 5731 5732 auto TargetIDDirective = getLexer().getTok().getStringContents(); 5733 if (getTargetStreamer().getTargetID()->toString() != TargetIDDirective) 5734 return Error(getParser().getTok().getLoc(), "target id must match options"); 5735 5736 getTargetStreamer().EmitISAVersion(); 5737 Lex(); 5738 5739 return false; 5740 } 5741 5742 bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() { 5743 assert(isHsaAbi(getSTI())); 5744 5745 std::string HSAMetadataString; 5746 if (ParseToEndDirective(HSAMD::V3::AssemblerDirectiveBegin, 5747 HSAMD::V3::AssemblerDirectiveEnd, HSAMetadataString)) 5748 return true; 5749 5750 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString)) 5751 return Error(getLoc(), "invalid HSA metadata"); 5752 5753 return false; 5754 } 5755 5756 /// Common code to parse out a block of text (typically YAML) between start and 5757 /// end directives. 5758 bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin, 5759 const char *AssemblerDirectiveEnd, 5760 std::string &CollectString) { 5761 5762 raw_string_ostream CollectStream(CollectString); 5763 5764 getLexer().setSkipSpace(false); 5765 5766 bool FoundEnd = false; 5767 while (!isToken(AsmToken::Eof)) { 5768 while (isToken(AsmToken::Space)) { 5769 CollectStream << getTokenStr(); 5770 Lex(); 5771 } 5772 5773 if (trySkipId(AssemblerDirectiveEnd)) { 5774 FoundEnd = true; 5775 break; 5776 } 5777 5778 CollectStream << Parser.parseStringToEndOfStatement() 5779 << getContext().getAsmInfo()->getSeparatorString(); 5780 5781 Parser.eatToEndOfStatement(); 5782 } 5783 5784 getLexer().setSkipSpace(true); 5785 5786 if (isToken(AsmToken::Eof) && !FoundEnd) { 5787 return TokError(Twine("expected directive ") + 5788 Twine(AssemblerDirectiveEnd) + Twine(" not found")); 5789 } 5790 5791 CollectStream.flush(); 5792 return false; 5793 } 5794 5795 /// Parse the assembler directive for new MsgPack-format PAL metadata. 5796 bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() { 5797 std::string String; 5798 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin, 5799 AMDGPU::PALMD::AssemblerDirectiveEnd, String)) 5800 return true; 5801 5802 auto PALMetadata = getTargetStreamer().getPALMetadata(); 5803 if (!PALMetadata->setFromString(String)) 5804 return Error(getLoc(), "invalid PAL metadata"); 5805 return false; 5806 } 5807 5808 /// Parse the assembler directive for old linear-format PAL metadata. 5809 bool AMDGPUAsmParser::ParseDirectivePALMetadata() { 5810 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) { 5811 return Error(getLoc(), 5812 (Twine(PALMD::AssemblerDirective) + Twine(" directive is " 5813 "not available on non-amdpal OSes")).str()); 5814 } 5815 5816 auto PALMetadata = getTargetStreamer().getPALMetadata(); 5817 PALMetadata->setLegacy(); 5818 for (;;) { 5819 uint32_t Key, Value; 5820 if (ParseAsAbsoluteExpression(Key)) { 5821 return TokError(Twine("invalid value in ") + 5822 Twine(PALMD::AssemblerDirective)); 5823 } 5824 if (!trySkipToken(AsmToken::Comma)) { 5825 return TokError(Twine("expected an even number of values in ") + 5826 Twine(PALMD::AssemblerDirective)); 5827 } 5828 if (ParseAsAbsoluteExpression(Value)) { 5829 return TokError(Twine("invalid value in ") + 5830 Twine(PALMD::AssemblerDirective)); 5831 } 5832 PALMetadata->setRegister(Key, Value); 5833 if (!trySkipToken(AsmToken::Comma)) 5834 break; 5835 } 5836 return false; 5837 } 5838 5839 /// ParseDirectiveAMDGPULDS 5840 /// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression] 5841 bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() { 5842 if (getParser().checkForValidSection()) 5843 return true; 5844 5845 StringRef Name; 5846 SMLoc NameLoc = getLoc(); 5847 if (getParser().parseIdentifier(Name)) 5848 return TokError("expected identifier in directive"); 5849 5850 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name); 5851 if (getParser().parseComma()) 5852 return true; 5853 5854 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(&getSTI()); 5855 5856 int64_t Size; 5857 SMLoc SizeLoc = getLoc(); 5858 if (getParser().parseAbsoluteExpression(Size)) 5859 return true; 5860 if (Size < 0) 5861 return Error(SizeLoc, "size must be non-negative"); 5862 if (Size > LocalMemorySize) 5863 return Error(SizeLoc, "size is too large"); 5864 5865 int64_t Alignment = 4; 5866 if (trySkipToken(AsmToken::Comma)) { 5867 SMLoc AlignLoc = getLoc(); 5868 if (getParser().parseAbsoluteExpression(Alignment)) 5869 return true; 5870 if (Alignment < 0 || !isPowerOf2_64(Alignment)) 5871 return Error(AlignLoc, "alignment must be a power of two"); 5872 5873 // Alignment larger than the size of LDS is possible in theory, as long 5874 // as the linker manages to place to symbol at address 0, but we do want 5875 // to make sure the alignment fits nicely into a 32-bit integer. 5876 if (Alignment >= 1u << 31) 5877 return Error(AlignLoc, "alignment is too large"); 5878 } 5879 5880 if (parseEOL()) 5881 return true; 5882 5883 Symbol->redefineIfPossible(); 5884 if (!Symbol->isUndefined()) 5885 return Error(NameLoc, "invalid symbol redefinition"); 5886 5887 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment)); 5888 return false; 5889 } 5890 5891 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 5892 StringRef IDVal = DirectiveID.getString(); 5893 5894 if (isHsaAbi(getSTI())) { 5895 if (IDVal == ".amdhsa_kernel") 5896 return ParseDirectiveAMDHSAKernel(); 5897 5898 if (IDVal == ".amdhsa_code_object_version") 5899 return ParseDirectiveAMDHSACodeObjectVersion(); 5900 5901 // TODO: Restructure/combine with PAL metadata directive. 5902 if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin) 5903 return ParseDirectiveHSAMetadata(); 5904 } else { 5905 if (IDVal == ".amd_kernel_code_t") 5906 return ParseDirectiveAMDKernelCodeT(); 5907 5908 if (IDVal == ".amdgpu_hsa_kernel") 5909 return ParseDirectiveAMDGPUHsaKernel(); 5910 5911 if (IDVal == ".amd_amdgpu_isa") 5912 return ParseDirectiveISAVersion(); 5913 5914 if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin) { 5915 return Error(getLoc(), (Twine(HSAMD::AssemblerDirectiveBegin) + 5916 Twine(" directive is " 5917 "not available on non-amdhsa OSes")) 5918 .str()); 5919 } 5920 } 5921 5922 if (IDVal == ".amdgcn_target") 5923 return ParseDirectiveAMDGCNTarget(); 5924 5925 if (IDVal == ".amdgpu_lds") 5926 return ParseDirectiveAMDGPULDS(); 5927 5928 if (IDVal == PALMD::AssemblerDirectiveBegin) 5929 return ParseDirectivePALMetadataBegin(); 5930 5931 if (IDVal == PALMD::AssemblerDirective) 5932 return ParseDirectivePALMetadata(); 5933 5934 return true; 5935 } 5936 5937 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 5938 unsigned RegNo) { 5939 5940 if (MRI.regsOverlap(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, RegNo)) 5941 return isGFX9Plus(); 5942 5943 // GFX10+ has 2 more SGPRs 104 and 105. 5944 if (MRI.regsOverlap(AMDGPU::SGPR104_SGPR105, RegNo)) 5945 return hasSGPR104_SGPR105(); 5946 5947 switch (RegNo) { 5948 case AMDGPU::SRC_SHARED_BASE_LO: 5949 case AMDGPU::SRC_SHARED_BASE: 5950 case AMDGPU::SRC_SHARED_LIMIT_LO: 5951 case AMDGPU::SRC_SHARED_LIMIT: 5952 case AMDGPU::SRC_PRIVATE_BASE_LO: 5953 case AMDGPU::SRC_PRIVATE_BASE: 5954 case AMDGPU::SRC_PRIVATE_LIMIT_LO: 5955 case AMDGPU::SRC_PRIVATE_LIMIT: 5956 return isGFX9Plus(); 5957 case AMDGPU::SRC_POPS_EXITING_WAVE_ID: 5958 return isGFX9Plus() && !isGFX11Plus(); 5959 case AMDGPU::TBA: 5960 case AMDGPU::TBA_LO: 5961 case AMDGPU::TBA_HI: 5962 case AMDGPU::TMA: 5963 case AMDGPU::TMA_LO: 5964 case AMDGPU::TMA_HI: 5965 return !isGFX9Plus(); 5966 case AMDGPU::XNACK_MASK: 5967 case AMDGPU::XNACK_MASK_LO: 5968 case AMDGPU::XNACK_MASK_HI: 5969 return (isVI() || isGFX9()) && getTargetStreamer().getTargetID()->isXnackSupported(); 5970 case AMDGPU::SGPR_NULL: 5971 return isGFX10Plus(); 5972 default: 5973 break; 5974 } 5975 5976 if (isCI()) 5977 return true; 5978 5979 if (isSI() || isGFX10Plus()) { 5980 // No flat_scr on SI. 5981 // On GFX10Plus flat scratch is not a valid register operand and can only be 5982 // accessed with s_setreg/s_getreg. 5983 switch (RegNo) { 5984 case AMDGPU::FLAT_SCR: 5985 case AMDGPU::FLAT_SCR_LO: 5986 case AMDGPU::FLAT_SCR_HI: 5987 return false; 5988 default: 5989 return true; 5990 } 5991 } 5992 5993 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 5994 // SI/CI have. 5995 if (MRI.regsOverlap(AMDGPU::SGPR102_SGPR103, RegNo)) 5996 return hasSGPR102_SGPR103(); 5997 5998 return true; 5999 } 6000 6001 ParseStatus AMDGPUAsmParser::parseOperand(OperandVector &Operands, 6002 StringRef Mnemonic, 6003 OperandMode Mode) { 6004 ParseStatus Res = parseVOPD(Operands); 6005 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement)) 6006 return Res; 6007 6008 // Try to parse with a custom parser 6009 Res = MatchOperandParserImpl(Operands, Mnemonic); 6010 6011 // If we successfully parsed the operand or if there as an error parsing, 6012 // we are done. 6013 // 6014 // If we are parsing after we reach EndOfStatement then this means we 6015 // are appending default values to the Operands list. This is only done 6016 // by custom parser, so we shouldn't continue on to the generic parsing. 6017 if (Res.isSuccess() || Res.isFailure() || isToken(AsmToken::EndOfStatement)) 6018 return Res; 6019 6020 SMLoc RBraceLoc; 6021 SMLoc LBraceLoc = getLoc(); 6022 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) { 6023 unsigned Prefix = Operands.size(); 6024 6025 for (;;) { 6026 auto Loc = getLoc(); 6027 Res = parseReg(Operands); 6028 if (Res.isNoMatch()) 6029 Error(Loc, "expected a register"); 6030 if (!Res.isSuccess()) 6031 return ParseStatus::Failure; 6032 6033 RBraceLoc = getLoc(); 6034 if (trySkipToken(AsmToken::RBrac)) 6035 break; 6036 6037 if (!skipToken(AsmToken::Comma, 6038 "expected a comma or a closing square bracket")) 6039 return ParseStatus::Failure; 6040 } 6041 6042 if (Operands.size() - Prefix > 1) { 6043 Operands.insert(Operands.begin() + Prefix, 6044 AMDGPUOperand::CreateToken(this, "[", LBraceLoc)); 6045 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc)); 6046 } 6047 6048 return ParseStatus::Success; 6049 } 6050 6051 return parseRegOrImm(Operands); 6052 } 6053 6054 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) { 6055 // Clear any forced encodings from the previous instruction. 6056 setForcedEncodingSize(0); 6057 setForcedDPP(false); 6058 setForcedSDWA(false); 6059 6060 if (Name.ends_with("_e64_dpp")) { 6061 setForcedDPP(true); 6062 setForcedEncodingSize(64); 6063 return Name.substr(0, Name.size() - 8); 6064 } else if (Name.ends_with("_e64")) { 6065 setForcedEncodingSize(64); 6066 return Name.substr(0, Name.size() - 4); 6067 } else if (Name.ends_with("_e32")) { 6068 setForcedEncodingSize(32); 6069 return Name.substr(0, Name.size() - 4); 6070 } else if (Name.ends_with("_dpp")) { 6071 setForcedDPP(true); 6072 return Name.substr(0, Name.size() - 4); 6073 } else if (Name.ends_with("_sdwa")) { 6074 setForcedSDWA(true); 6075 return Name.substr(0, Name.size() - 5); 6076 } 6077 return Name; 6078 } 6079 6080 static void applyMnemonicAliases(StringRef &Mnemonic, 6081 const FeatureBitset &Features, 6082 unsigned VariantID); 6083 6084 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 6085 StringRef Name, 6086 SMLoc NameLoc, OperandVector &Operands) { 6087 // Add the instruction mnemonic 6088 Name = parseMnemonicSuffix(Name); 6089 6090 // If the target architecture uses MnemonicAlias, call it here to parse 6091 // operands correctly. 6092 applyMnemonicAliases(Name, getAvailableFeatures(), 0); 6093 6094 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc)); 6095 6096 bool IsMIMG = Name.starts_with("image_"); 6097 6098 while (!trySkipToken(AsmToken::EndOfStatement)) { 6099 OperandMode Mode = OperandMode_Default; 6100 if (IsMIMG && isGFX10Plus() && Operands.size() == 2) 6101 Mode = OperandMode_NSA; 6102 ParseStatus Res = parseOperand(Operands, Name, Mode); 6103 6104 if (!Res.isSuccess()) { 6105 checkUnsupportedInstruction(Name, NameLoc); 6106 if (!Parser.hasPendingError()) { 6107 // FIXME: use real operand location rather than the current location. 6108 StringRef Msg = Res.isFailure() ? "failed parsing operand." 6109 : "not a valid operand."; 6110 Error(getLoc(), Msg); 6111 } 6112 while (!trySkipToken(AsmToken::EndOfStatement)) { 6113 lex(); 6114 } 6115 return true; 6116 } 6117 6118 // Eat the comma or space if there is one. 6119 trySkipToken(AsmToken::Comma); 6120 } 6121 6122 return false; 6123 } 6124 6125 //===----------------------------------------------------------------------===// 6126 // Utility functions 6127 //===----------------------------------------------------------------------===// 6128 6129 ParseStatus AMDGPUAsmParser::parseTokenOp(StringRef Name, 6130 OperandVector &Operands) { 6131 SMLoc S = getLoc(); 6132 if (!trySkipId(Name)) 6133 return ParseStatus::NoMatch; 6134 6135 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, S)); 6136 return ParseStatus::Success; 6137 } 6138 6139 ParseStatus AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, 6140 int64_t &IntVal) { 6141 6142 if (!trySkipId(Prefix, AsmToken::Colon)) 6143 return ParseStatus::NoMatch; 6144 6145 return parseExpr(IntVal) ? ParseStatus::Success : ParseStatus::Failure; 6146 } 6147 6148 ParseStatus AMDGPUAsmParser::parseIntWithPrefix( 6149 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy, 6150 std::function<bool(int64_t &)> ConvertResult) { 6151 SMLoc S = getLoc(); 6152 int64_t Value = 0; 6153 6154 ParseStatus Res = parseIntWithPrefix(Prefix, Value); 6155 if (!Res.isSuccess()) 6156 return Res; 6157 6158 if (ConvertResult && !ConvertResult(Value)) { 6159 Error(S, "invalid " + StringRef(Prefix) + " value."); 6160 } 6161 6162 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy)); 6163 return ParseStatus::Success; 6164 } 6165 6166 ParseStatus AMDGPUAsmParser::parseOperandArrayWithPrefix( 6167 const char *Prefix, OperandVector &Operands, AMDGPUOperand::ImmTy ImmTy, 6168 bool (*ConvertResult)(int64_t &)) { 6169 SMLoc S = getLoc(); 6170 if (!trySkipId(Prefix, AsmToken::Colon)) 6171 return ParseStatus::NoMatch; 6172 6173 if (!skipToken(AsmToken::LBrac, "expected a left square bracket")) 6174 return ParseStatus::Failure; 6175 6176 unsigned Val = 0; 6177 const unsigned MaxSize = 4; 6178 6179 // FIXME: How to verify the number of elements matches the number of src 6180 // operands? 6181 for (int I = 0; ; ++I) { 6182 int64_t Op; 6183 SMLoc Loc = getLoc(); 6184 if (!parseExpr(Op)) 6185 return ParseStatus::Failure; 6186 6187 if (Op != 0 && Op != 1) 6188 return Error(Loc, "invalid " + StringRef(Prefix) + " value."); 6189 6190 Val |= (Op << I); 6191 6192 if (trySkipToken(AsmToken::RBrac)) 6193 break; 6194 6195 if (I + 1 == MaxSize) 6196 return Error(getLoc(), "expected a closing square bracket"); 6197 6198 if (!skipToken(AsmToken::Comma, "expected a comma")) 6199 return ParseStatus::Failure; 6200 } 6201 6202 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy)); 6203 return ParseStatus::Success; 6204 } 6205 6206 ParseStatus AMDGPUAsmParser::parseNamedBit(StringRef Name, 6207 OperandVector &Operands, 6208 AMDGPUOperand::ImmTy ImmTy) { 6209 int64_t Bit; 6210 SMLoc S = getLoc(); 6211 6212 if (trySkipId(Name)) { 6213 Bit = 1; 6214 } else if (trySkipId("no", Name)) { 6215 Bit = 0; 6216 } else { 6217 return ParseStatus::NoMatch; 6218 } 6219 6220 if (Name == "r128" && !hasMIMG_R128()) 6221 return Error(S, "r128 modifier is not supported on this GPU"); 6222 if (Name == "a16" && !hasA16()) 6223 return Error(S, "a16 modifier is not supported on this GPU"); 6224 6225 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16) 6226 ImmTy = AMDGPUOperand::ImmTyR128A16; 6227 6228 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy)); 6229 return ParseStatus::Success; 6230 } 6231 6232 unsigned AMDGPUAsmParser::getCPolKind(StringRef Id, StringRef Mnemo, 6233 bool &Disabling) const { 6234 Disabling = Id.consume_front("no"); 6235 6236 if (isGFX940() && !Mnemo.starts_with("s_")) { 6237 return StringSwitch<unsigned>(Id) 6238 .Case("nt", AMDGPU::CPol::NT) 6239 .Case("sc0", AMDGPU::CPol::SC0) 6240 .Case("sc1", AMDGPU::CPol::SC1) 6241 .Default(0); 6242 } 6243 6244 return StringSwitch<unsigned>(Id) 6245 .Case("dlc", AMDGPU::CPol::DLC) 6246 .Case("glc", AMDGPU::CPol::GLC) 6247 .Case("scc", AMDGPU::CPol::SCC) 6248 .Case("slc", AMDGPU::CPol::SLC) 6249 .Default(0); 6250 } 6251 6252 ParseStatus AMDGPUAsmParser::parseCPol(OperandVector &Operands) { 6253 if (isGFX12Plus()) { 6254 SMLoc StringLoc = getLoc(); 6255 6256 int64_t CPolVal = 0; 6257 ParseStatus ResTH = ParseStatus::NoMatch; 6258 ParseStatus ResScope = ParseStatus::NoMatch; 6259 6260 for (;;) { 6261 if (ResTH.isNoMatch()) { 6262 int64_t TH; 6263 ResTH = parseTH(Operands, TH); 6264 if (ResTH.isFailure()) 6265 return ResTH; 6266 if (ResTH.isSuccess()) { 6267 CPolVal |= TH; 6268 continue; 6269 } 6270 } 6271 6272 if (ResScope.isNoMatch()) { 6273 int64_t Scope; 6274 ResScope = parseScope(Operands, Scope); 6275 if (ResScope.isFailure()) 6276 return ResScope; 6277 if (ResScope.isSuccess()) { 6278 CPolVal |= Scope; 6279 continue; 6280 } 6281 } 6282 6283 break; 6284 } 6285 6286 if (ResTH.isNoMatch() && ResScope.isNoMatch()) 6287 return ParseStatus::NoMatch; 6288 6289 Operands.push_back(AMDGPUOperand::CreateImm(this, CPolVal, StringLoc, 6290 AMDGPUOperand::ImmTyCPol)); 6291 return ParseStatus::Success; 6292 } 6293 6294 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken(); 6295 SMLoc OpLoc = getLoc(); 6296 unsigned Enabled = 0, Seen = 0; 6297 for (;;) { 6298 SMLoc S = getLoc(); 6299 bool Disabling; 6300 unsigned CPol = getCPolKind(getId(), Mnemo, Disabling); 6301 if (!CPol) 6302 break; 6303 6304 lex(); 6305 6306 if (!isGFX10Plus() && CPol == AMDGPU::CPol::DLC) 6307 return Error(S, "dlc modifier is not supported on this GPU"); 6308 6309 if (!isGFX90A() && CPol == AMDGPU::CPol::SCC) 6310 return Error(S, "scc modifier is not supported on this GPU"); 6311 6312 if (Seen & CPol) 6313 return Error(S, "duplicate cache policy modifier"); 6314 6315 if (!Disabling) 6316 Enabled |= CPol; 6317 6318 Seen |= CPol; 6319 } 6320 6321 if (!Seen) 6322 return ParseStatus::NoMatch; 6323 6324 Operands.push_back( 6325 AMDGPUOperand::CreateImm(this, Enabled, OpLoc, AMDGPUOperand::ImmTyCPol)); 6326 return ParseStatus::Success; 6327 } 6328 6329 ParseStatus AMDGPUAsmParser::parseScope(OperandVector &Operands, 6330 int64_t &Scope) { 6331 Scope = AMDGPU::CPol::SCOPE_CU; // default; 6332 6333 StringRef Value; 6334 SMLoc StringLoc; 6335 ParseStatus Res; 6336 6337 Res = parseStringWithPrefix("scope", Value, StringLoc); 6338 if (!Res.isSuccess()) 6339 return Res; 6340 6341 Scope = StringSwitch<int64_t>(Value) 6342 .Case("SCOPE_CU", AMDGPU::CPol::SCOPE_CU) 6343 .Case("SCOPE_SE", AMDGPU::CPol::SCOPE_SE) 6344 .Case("SCOPE_DEV", AMDGPU::CPol::SCOPE_DEV) 6345 .Case("SCOPE_SYS", AMDGPU::CPol::SCOPE_SYS) 6346 .Default(0xffffffff); 6347 6348 if (Scope == 0xffffffff) 6349 return Error(StringLoc, "invalid scope value"); 6350 6351 return ParseStatus::Success; 6352 } 6353 6354 ParseStatus AMDGPUAsmParser::parseTH(OperandVector &Operands, int64_t &TH) { 6355 TH = AMDGPU::CPol::TH_RT; // default 6356 6357 StringRef Value; 6358 SMLoc StringLoc; 6359 ParseStatus Res = parseStringWithPrefix("th", Value, StringLoc); 6360 if (!Res.isSuccess()) 6361 return Res; 6362 6363 if (Value == "TH_DEFAULT") 6364 TH = AMDGPU::CPol::TH_RT; 6365 else if (Value == "TH_STORE_LU" || Value == "TH_LOAD_RT_WB" || 6366 Value == "TH_LOAD_NT_WB") { 6367 return Error(StringLoc, "invalid th value"); 6368 } else if (Value.starts_with("TH_ATOMIC_")) { 6369 Value = Value.drop_front(10); 6370 TH = AMDGPU::CPol::TH_TYPE_ATOMIC; 6371 } else if (Value.starts_with("TH_LOAD_")) { 6372 Value = Value.drop_front(8); 6373 TH = AMDGPU::CPol::TH_TYPE_LOAD; 6374 } else if (Value.starts_with("TH_STORE_")) { 6375 Value = Value.drop_front(9); 6376 TH = AMDGPU::CPol::TH_TYPE_STORE; 6377 } else { 6378 return Error(StringLoc, "invalid th value"); 6379 } 6380 6381 if (Value == "BYPASS") 6382 TH |= AMDGPU::CPol::TH_REAL_BYPASS; 6383 6384 if (TH != 0) { 6385 if (TH & AMDGPU::CPol::TH_TYPE_ATOMIC) 6386 TH |= StringSwitch<int64_t>(Value) 6387 .Case("RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN) 6388 .Case("RT", AMDGPU::CPol::TH_RT) 6389 .Case("RT_RETURN", AMDGPU::CPol::TH_ATOMIC_RETURN) 6390 .Case("NT", AMDGPU::CPol::TH_ATOMIC_NT) 6391 .Case("NT_RETURN", AMDGPU::CPol::TH_ATOMIC_NT | 6392 AMDGPU::CPol::TH_ATOMIC_RETURN) 6393 .Case("CASCADE_RT", AMDGPU::CPol::TH_ATOMIC_CASCADE) 6394 .Case("CASCADE_NT", AMDGPU::CPol::TH_ATOMIC_CASCADE | 6395 AMDGPU::CPol::TH_ATOMIC_NT) 6396 .Default(0xffffffff); 6397 else 6398 TH |= StringSwitch<int64_t>(Value) 6399 .Case("RT", AMDGPU::CPol::TH_RT) 6400 .Case("NT", AMDGPU::CPol::TH_NT) 6401 .Case("HT", AMDGPU::CPol::TH_HT) 6402 .Case("LU", AMDGPU::CPol::TH_LU) 6403 .Case("RT_WB", AMDGPU::CPol::TH_RT_WB) 6404 .Case("NT_RT", AMDGPU::CPol::TH_NT_RT) 6405 .Case("RT_NT", AMDGPU::CPol::TH_RT_NT) 6406 .Case("NT_HT", AMDGPU::CPol::TH_NT_HT) 6407 .Case("NT_WB", AMDGPU::CPol::TH_NT_WB) 6408 .Case("BYPASS", AMDGPU::CPol::TH_BYPASS) 6409 .Default(0xffffffff); 6410 } 6411 6412 if (TH == 0xffffffff) 6413 return Error(StringLoc, "invalid th value"); 6414 6415 return ParseStatus::Success; 6416 } 6417 6418 static void addOptionalImmOperand( 6419 MCInst& Inst, const OperandVector& Operands, 6420 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx, 6421 AMDGPUOperand::ImmTy ImmT, 6422 int64_t Default = 0) { 6423 auto i = OptionalIdx.find(ImmT); 6424 if (i != OptionalIdx.end()) { 6425 unsigned Idx = i->second; 6426 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 6427 } else { 6428 Inst.addOperand(MCOperand::createImm(Default)); 6429 } 6430 } 6431 6432 ParseStatus AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, 6433 StringRef &Value, 6434 SMLoc &StringLoc) { 6435 if (!trySkipId(Prefix, AsmToken::Colon)) 6436 return ParseStatus::NoMatch; 6437 6438 StringLoc = getLoc(); 6439 return parseId(Value, "expected an identifier") ? ParseStatus::Success 6440 : ParseStatus::Failure; 6441 } 6442 6443 //===----------------------------------------------------------------------===// 6444 // MTBUF format 6445 //===----------------------------------------------------------------------===// 6446 6447 bool AMDGPUAsmParser::tryParseFmt(const char *Pref, 6448 int64_t MaxVal, 6449 int64_t &Fmt) { 6450 int64_t Val; 6451 SMLoc Loc = getLoc(); 6452 6453 auto Res = parseIntWithPrefix(Pref, Val); 6454 if (Res.isFailure()) 6455 return false; 6456 if (Res.isNoMatch()) 6457 return true; 6458 6459 if (Val < 0 || Val > MaxVal) { 6460 Error(Loc, Twine("out of range ", StringRef(Pref))); 6461 return false; 6462 } 6463 6464 Fmt = Val; 6465 return true; 6466 } 6467 6468 // dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their 6469 // values to live in a joint format operand in the MCInst encoding. 6470 ParseStatus AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) { 6471 using namespace llvm::AMDGPU::MTBUFFormat; 6472 6473 int64_t Dfmt = DFMT_UNDEF; 6474 int64_t Nfmt = NFMT_UNDEF; 6475 6476 // dfmt and nfmt can appear in either order, and each is optional. 6477 for (int I = 0; I < 2; ++I) { 6478 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt)) 6479 return ParseStatus::Failure; 6480 6481 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt)) 6482 return ParseStatus::Failure; 6483 6484 // Skip optional comma between dfmt/nfmt 6485 // but guard against 2 commas following each other. 6486 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) && 6487 !peekToken().is(AsmToken::Comma)) { 6488 trySkipToken(AsmToken::Comma); 6489 } 6490 } 6491 6492 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF) 6493 return ParseStatus::NoMatch; 6494 6495 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt; 6496 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt; 6497 6498 Format = encodeDfmtNfmt(Dfmt, Nfmt); 6499 return ParseStatus::Success; 6500 } 6501 6502 ParseStatus AMDGPUAsmParser::parseUfmt(int64_t &Format) { 6503 using namespace llvm::AMDGPU::MTBUFFormat; 6504 6505 int64_t Fmt = UFMT_UNDEF; 6506 6507 if (!tryParseFmt("format", UFMT_MAX, Fmt)) 6508 return ParseStatus::Failure; 6509 6510 if (Fmt == UFMT_UNDEF) 6511 return ParseStatus::NoMatch; 6512 6513 Format = Fmt; 6514 return ParseStatus::Success; 6515 } 6516 6517 bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, 6518 int64_t &Nfmt, 6519 StringRef FormatStr, 6520 SMLoc Loc) { 6521 using namespace llvm::AMDGPU::MTBUFFormat; 6522 int64_t Format; 6523 6524 Format = getDfmt(FormatStr); 6525 if (Format != DFMT_UNDEF) { 6526 Dfmt = Format; 6527 return true; 6528 } 6529 6530 Format = getNfmt(FormatStr, getSTI()); 6531 if (Format != NFMT_UNDEF) { 6532 Nfmt = Format; 6533 return true; 6534 } 6535 6536 Error(Loc, "unsupported format"); 6537 return false; 6538 } 6539 6540 ParseStatus AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr, 6541 SMLoc FormatLoc, 6542 int64_t &Format) { 6543 using namespace llvm::AMDGPU::MTBUFFormat; 6544 6545 int64_t Dfmt = DFMT_UNDEF; 6546 int64_t Nfmt = NFMT_UNDEF; 6547 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc)) 6548 return ParseStatus::Failure; 6549 6550 if (trySkipToken(AsmToken::Comma)) { 6551 StringRef Str; 6552 SMLoc Loc = getLoc(); 6553 if (!parseId(Str, "expected a format string") || 6554 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc)) 6555 return ParseStatus::Failure; 6556 if (Dfmt == DFMT_UNDEF) 6557 return Error(Loc, "duplicate numeric format"); 6558 if (Nfmt == NFMT_UNDEF) 6559 return Error(Loc, "duplicate data format"); 6560 } 6561 6562 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt; 6563 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt; 6564 6565 if (isGFX10Plus()) { 6566 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt, getSTI()); 6567 if (Ufmt == UFMT_UNDEF) 6568 return Error(FormatLoc, "unsupported format"); 6569 Format = Ufmt; 6570 } else { 6571 Format = encodeDfmtNfmt(Dfmt, Nfmt); 6572 } 6573 6574 return ParseStatus::Success; 6575 } 6576 6577 ParseStatus AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr, 6578 SMLoc Loc, 6579 int64_t &Format) { 6580 using namespace llvm::AMDGPU::MTBUFFormat; 6581 6582 auto Id = getUnifiedFormat(FormatStr, getSTI()); 6583 if (Id == UFMT_UNDEF) 6584 return ParseStatus::NoMatch; 6585 6586 if (!isGFX10Plus()) 6587 return Error(Loc, "unified format is not supported on this GPU"); 6588 6589 Format = Id; 6590 return ParseStatus::Success; 6591 } 6592 6593 ParseStatus AMDGPUAsmParser::parseNumericFormat(int64_t &Format) { 6594 using namespace llvm::AMDGPU::MTBUFFormat; 6595 SMLoc Loc = getLoc(); 6596 6597 if (!parseExpr(Format)) 6598 return ParseStatus::Failure; 6599 if (!isValidFormatEncoding(Format, getSTI())) 6600 return Error(Loc, "out of range format"); 6601 6602 return ParseStatus::Success; 6603 } 6604 6605 ParseStatus AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) { 6606 using namespace llvm::AMDGPU::MTBUFFormat; 6607 6608 if (!trySkipId("format", AsmToken::Colon)) 6609 return ParseStatus::NoMatch; 6610 6611 if (trySkipToken(AsmToken::LBrac)) { 6612 StringRef FormatStr; 6613 SMLoc Loc = getLoc(); 6614 if (!parseId(FormatStr, "expected a format string")) 6615 return ParseStatus::Failure; 6616 6617 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format); 6618 if (Res.isNoMatch()) 6619 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format); 6620 if (!Res.isSuccess()) 6621 return Res; 6622 6623 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 6624 return ParseStatus::Failure; 6625 6626 return ParseStatus::Success; 6627 } 6628 6629 return parseNumericFormat(Format); 6630 } 6631 6632 ParseStatus AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) { 6633 using namespace llvm::AMDGPU::MTBUFFormat; 6634 6635 int64_t Format = getDefaultFormatEncoding(getSTI()); 6636 ParseStatus Res; 6637 SMLoc Loc = getLoc(); 6638 6639 // Parse legacy format syntax. 6640 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format); 6641 if (Res.isFailure()) 6642 return Res; 6643 6644 bool FormatFound = Res.isSuccess(); 6645 6646 Operands.push_back( 6647 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT)); 6648 6649 if (FormatFound) 6650 trySkipToken(AsmToken::Comma); 6651 6652 if (isToken(AsmToken::EndOfStatement)) { 6653 // We are expecting an soffset operand, 6654 // but let matcher handle the error. 6655 return ParseStatus::Success; 6656 } 6657 6658 // Parse soffset. 6659 Res = parseRegOrImm(Operands); 6660 if (!Res.isSuccess()) 6661 return Res; 6662 6663 trySkipToken(AsmToken::Comma); 6664 6665 if (!FormatFound) { 6666 Res = parseSymbolicOrNumericFormat(Format); 6667 if (Res.isFailure()) 6668 return Res; 6669 if (Res.isSuccess()) { 6670 auto Size = Operands.size(); 6671 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]); 6672 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT); 6673 Op.setImm(Format); 6674 } 6675 return ParseStatus::Success; 6676 } 6677 6678 if (isId("format") && peekToken().is(AsmToken::Colon)) 6679 return Error(getLoc(), "duplicate format"); 6680 return ParseStatus::Success; 6681 } 6682 6683 ParseStatus AMDGPUAsmParser::parseFlatOffset(OperandVector &Operands) { 6684 ParseStatus Res = 6685 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset); 6686 if (Res.isNoMatch()) { 6687 Res = parseIntWithPrefix("inst_offset", Operands, 6688 AMDGPUOperand::ImmTyInstOffset); 6689 } 6690 return Res; 6691 } 6692 6693 ParseStatus AMDGPUAsmParser::parseR128A16(OperandVector &Operands) { 6694 ParseStatus Res = 6695 parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128A16); 6696 if (Res.isNoMatch()) 6697 Res = parseNamedBit("a16", Operands, AMDGPUOperand::ImmTyA16); 6698 return Res; 6699 } 6700 6701 ParseStatus AMDGPUAsmParser::parseBLGP(OperandVector &Operands) { 6702 ParseStatus Res = 6703 parseIntWithPrefix("blgp", Operands, AMDGPUOperand::ImmTyBLGP); 6704 if (Res.isNoMatch()) { 6705 Res = 6706 parseOperandArrayWithPrefix("neg", Operands, AMDGPUOperand::ImmTyBLGP); 6707 } 6708 return Res; 6709 } 6710 6711 //===----------------------------------------------------------------------===// 6712 // Exp 6713 //===----------------------------------------------------------------------===// 6714 6715 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) { 6716 OptionalImmIndexMap OptionalIdx; 6717 6718 unsigned OperandIdx[4]; 6719 unsigned EnMask = 0; 6720 int SrcIdx = 0; 6721 6722 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 6723 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 6724 6725 // Add the register arguments 6726 if (Op.isReg()) { 6727 assert(SrcIdx < 4); 6728 OperandIdx[SrcIdx] = Inst.size(); 6729 Op.addRegOperands(Inst, 1); 6730 ++SrcIdx; 6731 continue; 6732 } 6733 6734 if (Op.isOff()) { 6735 assert(SrcIdx < 4); 6736 OperandIdx[SrcIdx] = Inst.size(); 6737 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister)); 6738 ++SrcIdx; 6739 continue; 6740 } 6741 6742 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) { 6743 Op.addImmOperands(Inst, 1); 6744 continue; 6745 } 6746 6747 if (Op.isToken() && (Op.getToken() == "done" || Op.getToken() == "row_en")) 6748 continue; 6749 6750 // Handle optional arguments 6751 OptionalIdx[Op.getImmTy()] = i; 6752 } 6753 6754 assert(SrcIdx == 4); 6755 6756 bool Compr = false; 6757 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) { 6758 Compr = true; 6759 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]); 6760 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister); 6761 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister); 6762 } 6763 6764 for (auto i = 0; i < SrcIdx; ++i) { 6765 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) { 6766 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i); 6767 } 6768 } 6769 6770 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM); 6771 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr); 6772 6773 Inst.addOperand(MCOperand::createImm(EnMask)); 6774 } 6775 6776 //===----------------------------------------------------------------------===// 6777 // s_waitcnt 6778 //===----------------------------------------------------------------------===// 6779 6780 static bool 6781 encodeCnt( 6782 const AMDGPU::IsaVersion ISA, 6783 int64_t &IntVal, 6784 int64_t CntVal, 6785 bool Saturate, 6786 unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned), 6787 unsigned (*decode)(const IsaVersion &Version, unsigned)) 6788 { 6789 bool Failed = false; 6790 6791 IntVal = encode(ISA, IntVal, CntVal); 6792 if (CntVal != decode(ISA, IntVal)) { 6793 if (Saturate) { 6794 IntVal = encode(ISA, IntVal, -1); 6795 } else { 6796 Failed = true; 6797 } 6798 } 6799 return Failed; 6800 } 6801 6802 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 6803 6804 SMLoc CntLoc = getLoc(); 6805 StringRef CntName = getTokenStr(); 6806 6807 if (!skipToken(AsmToken::Identifier, "expected a counter name") || 6808 !skipToken(AsmToken::LParen, "expected a left parenthesis")) 6809 return false; 6810 6811 int64_t CntVal; 6812 SMLoc ValLoc = getLoc(); 6813 if (!parseExpr(CntVal)) 6814 return false; 6815 6816 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 6817 6818 bool Failed = true; 6819 bool Sat = CntName.ends_with("_sat"); 6820 6821 if (CntName == "vmcnt" || CntName == "vmcnt_sat") { 6822 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt); 6823 } else if (CntName == "expcnt" || CntName == "expcnt_sat") { 6824 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt); 6825 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") { 6826 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt); 6827 } else { 6828 Error(CntLoc, "invalid counter name " + CntName); 6829 return false; 6830 } 6831 6832 if (Failed) { 6833 Error(ValLoc, "too large value for " + CntName); 6834 return false; 6835 } 6836 6837 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis")) 6838 return false; 6839 6840 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) { 6841 if (isToken(AsmToken::EndOfStatement)) { 6842 Error(getLoc(), "expected a counter name"); 6843 return false; 6844 } 6845 } 6846 6847 return true; 6848 } 6849 6850 ParseStatus AMDGPUAsmParser::parseSWaitCnt(OperandVector &Operands) { 6851 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 6852 int64_t Waitcnt = getWaitcntBitMask(ISA); 6853 SMLoc S = getLoc(); 6854 6855 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) { 6856 while (!isToken(AsmToken::EndOfStatement)) { 6857 if (!parseCnt(Waitcnt)) 6858 return ParseStatus::Failure; 6859 } 6860 } else { 6861 if (!parseExpr(Waitcnt)) 6862 return ParseStatus::Failure; 6863 } 6864 6865 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S)); 6866 return ParseStatus::Success; 6867 } 6868 6869 bool AMDGPUAsmParser::parseDelay(int64_t &Delay) { 6870 SMLoc FieldLoc = getLoc(); 6871 StringRef FieldName = getTokenStr(); 6872 if (!skipToken(AsmToken::Identifier, "expected a field name") || 6873 !skipToken(AsmToken::LParen, "expected a left parenthesis")) 6874 return false; 6875 6876 SMLoc ValueLoc = getLoc(); 6877 StringRef ValueName = getTokenStr(); 6878 if (!skipToken(AsmToken::Identifier, "expected a value name") || 6879 !skipToken(AsmToken::RParen, "expected a right parenthesis")) 6880 return false; 6881 6882 unsigned Shift; 6883 if (FieldName == "instid0") { 6884 Shift = 0; 6885 } else if (FieldName == "instskip") { 6886 Shift = 4; 6887 } else if (FieldName == "instid1") { 6888 Shift = 7; 6889 } else { 6890 Error(FieldLoc, "invalid field name " + FieldName); 6891 return false; 6892 } 6893 6894 int Value; 6895 if (Shift == 4) { 6896 // Parse values for instskip. 6897 Value = StringSwitch<int>(ValueName) 6898 .Case("SAME", 0) 6899 .Case("NEXT", 1) 6900 .Case("SKIP_1", 2) 6901 .Case("SKIP_2", 3) 6902 .Case("SKIP_3", 4) 6903 .Case("SKIP_4", 5) 6904 .Default(-1); 6905 } else { 6906 // Parse values for instid0 and instid1. 6907 Value = StringSwitch<int>(ValueName) 6908 .Case("NO_DEP", 0) 6909 .Case("VALU_DEP_1", 1) 6910 .Case("VALU_DEP_2", 2) 6911 .Case("VALU_DEP_3", 3) 6912 .Case("VALU_DEP_4", 4) 6913 .Case("TRANS32_DEP_1", 5) 6914 .Case("TRANS32_DEP_2", 6) 6915 .Case("TRANS32_DEP_3", 7) 6916 .Case("FMA_ACCUM_CYCLE_1", 8) 6917 .Case("SALU_CYCLE_1", 9) 6918 .Case("SALU_CYCLE_2", 10) 6919 .Case("SALU_CYCLE_3", 11) 6920 .Default(-1); 6921 } 6922 if (Value < 0) { 6923 Error(ValueLoc, "invalid value name " + ValueName); 6924 return false; 6925 } 6926 6927 Delay |= Value << Shift; 6928 return true; 6929 } 6930 6931 ParseStatus AMDGPUAsmParser::parseSDelayALU(OperandVector &Operands) { 6932 int64_t Delay = 0; 6933 SMLoc S = getLoc(); 6934 6935 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) { 6936 do { 6937 if (!parseDelay(Delay)) 6938 return ParseStatus::Failure; 6939 } while (trySkipToken(AsmToken::Pipe)); 6940 } else { 6941 if (!parseExpr(Delay)) 6942 return ParseStatus::Failure; 6943 } 6944 6945 Operands.push_back(AMDGPUOperand::CreateImm(this, Delay, S)); 6946 return ParseStatus::Success; 6947 } 6948 6949 bool 6950 AMDGPUOperand::isSWaitCnt() const { 6951 return isImm(); 6952 } 6953 6954 bool AMDGPUOperand::isSDelayALU() const { return isImm(); } 6955 6956 //===----------------------------------------------------------------------===// 6957 // DepCtr 6958 //===----------------------------------------------------------------------===// 6959 6960 void AMDGPUAsmParser::depCtrError(SMLoc Loc, int ErrorId, 6961 StringRef DepCtrName) { 6962 switch (ErrorId) { 6963 case OPR_ID_UNKNOWN: 6964 Error(Loc, Twine("invalid counter name ", DepCtrName)); 6965 return; 6966 case OPR_ID_UNSUPPORTED: 6967 Error(Loc, Twine(DepCtrName, " is not supported on this GPU")); 6968 return; 6969 case OPR_ID_DUPLICATE: 6970 Error(Loc, Twine("duplicate counter name ", DepCtrName)); 6971 return; 6972 case OPR_VAL_INVALID: 6973 Error(Loc, Twine("invalid value for ", DepCtrName)); 6974 return; 6975 default: 6976 assert(false); 6977 } 6978 } 6979 6980 bool AMDGPUAsmParser::parseDepCtr(int64_t &DepCtr, unsigned &UsedOprMask) { 6981 6982 using namespace llvm::AMDGPU::DepCtr; 6983 6984 SMLoc DepCtrLoc = getLoc(); 6985 StringRef DepCtrName = getTokenStr(); 6986 6987 if (!skipToken(AsmToken::Identifier, "expected a counter name") || 6988 !skipToken(AsmToken::LParen, "expected a left parenthesis")) 6989 return false; 6990 6991 int64_t ExprVal; 6992 if (!parseExpr(ExprVal)) 6993 return false; 6994 6995 unsigned PrevOprMask = UsedOprMask; 6996 int CntVal = encodeDepCtr(DepCtrName, ExprVal, UsedOprMask, getSTI()); 6997 6998 if (CntVal < 0) { 6999 depCtrError(DepCtrLoc, CntVal, DepCtrName); 7000 return false; 7001 } 7002 7003 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis")) 7004 return false; 7005 7006 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) { 7007 if (isToken(AsmToken::EndOfStatement)) { 7008 Error(getLoc(), "expected a counter name"); 7009 return false; 7010 } 7011 } 7012 7013 unsigned CntValMask = PrevOprMask ^ UsedOprMask; 7014 DepCtr = (DepCtr & ~CntValMask) | CntVal; 7015 return true; 7016 } 7017 7018 ParseStatus AMDGPUAsmParser::parseDepCtr(OperandVector &Operands) { 7019 using namespace llvm::AMDGPU::DepCtr; 7020 7021 int64_t DepCtr = getDefaultDepCtrEncoding(getSTI()); 7022 SMLoc Loc = getLoc(); 7023 7024 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) { 7025 unsigned UsedOprMask = 0; 7026 while (!isToken(AsmToken::EndOfStatement)) { 7027 if (!parseDepCtr(DepCtr, UsedOprMask)) 7028 return ParseStatus::Failure; 7029 } 7030 } else { 7031 if (!parseExpr(DepCtr)) 7032 return ParseStatus::Failure; 7033 } 7034 7035 Operands.push_back(AMDGPUOperand::CreateImm(this, DepCtr, Loc)); 7036 return ParseStatus::Success; 7037 } 7038 7039 bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); } 7040 7041 //===----------------------------------------------------------------------===// 7042 // hwreg 7043 //===----------------------------------------------------------------------===// 7044 7045 bool 7046 AMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg, 7047 OperandInfoTy &Offset, 7048 OperandInfoTy &Width) { 7049 using namespace llvm::AMDGPU::Hwreg; 7050 7051 // The register may be specified by name or using a numeric code 7052 HwReg.Loc = getLoc(); 7053 if (isToken(AsmToken::Identifier) && 7054 (HwReg.Id = getHwregId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) { 7055 HwReg.IsSymbolic = true; 7056 lex(); // skip register name 7057 } else if (!parseExpr(HwReg.Id, "a register name")) { 7058 return false; 7059 } 7060 7061 if (trySkipToken(AsmToken::RParen)) 7062 return true; 7063 7064 // parse optional params 7065 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis")) 7066 return false; 7067 7068 Offset.Loc = getLoc(); 7069 if (!parseExpr(Offset.Id)) 7070 return false; 7071 7072 if (!skipToken(AsmToken::Comma, "expected a comma")) 7073 return false; 7074 7075 Width.Loc = getLoc(); 7076 return parseExpr(Width.Id) && 7077 skipToken(AsmToken::RParen, "expected a closing parenthesis"); 7078 } 7079 7080 bool 7081 AMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg, 7082 const OperandInfoTy &Offset, 7083 const OperandInfoTy &Width) { 7084 7085 using namespace llvm::AMDGPU::Hwreg; 7086 7087 if (HwReg.IsSymbolic) { 7088 if (HwReg.Id == OPR_ID_UNSUPPORTED) { 7089 Error(HwReg.Loc, 7090 "specified hardware register is not supported on this GPU"); 7091 return false; 7092 } 7093 } else { 7094 if (!isValidHwreg(HwReg.Id)) { 7095 Error(HwReg.Loc, 7096 "invalid code of hardware register: only 6-bit values are legal"); 7097 return false; 7098 } 7099 } 7100 if (!isValidHwregOffset(Offset.Id)) { 7101 Error(Offset.Loc, "invalid bit offset: only 5-bit values are legal"); 7102 return false; 7103 } 7104 if (!isValidHwregWidth(Width.Id)) { 7105 Error(Width.Loc, 7106 "invalid bitfield width: only values from 1 to 32 are legal"); 7107 return false; 7108 } 7109 return true; 7110 } 7111 7112 ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) { 7113 using namespace llvm::AMDGPU::Hwreg; 7114 7115 int64_t ImmVal = 0; 7116 SMLoc Loc = getLoc(); 7117 7118 if (trySkipId("hwreg", AsmToken::LParen)) { 7119 OperandInfoTy HwReg(OPR_ID_UNKNOWN); 7120 OperandInfoTy Offset(OFFSET_DEFAULT_); 7121 OperandInfoTy Width(WIDTH_DEFAULT_); 7122 if (parseHwregBody(HwReg, Offset, Width) && 7123 validateHwreg(HwReg, Offset, Width)) { 7124 ImmVal = encodeHwreg(HwReg.Id, Offset.Id, Width.Id); 7125 } else { 7126 return ParseStatus::Failure; 7127 } 7128 } else if (parseExpr(ImmVal, "a hwreg macro")) { 7129 if (ImmVal < 0 || !isUInt<16>(ImmVal)) 7130 return Error(Loc, "invalid immediate: only 16-bit values are legal"); 7131 } else { 7132 return ParseStatus::Failure; 7133 } 7134 7135 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg)); 7136 return ParseStatus::Success; 7137 } 7138 7139 bool AMDGPUOperand::isHwreg() const { 7140 return isImmTy(ImmTyHwreg); 7141 } 7142 7143 //===----------------------------------------------------------------------===// 7144 // sendmsg 7145 //===----------------------------------------------------------------------===// 7146 7147 bool 7148 AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, 7149 OperandInfoTy &Op, 7150 OperandInfoTy &Stream) { 7151 using namespace llvm::AMDGPU::SendMsg; 7152 7153 Msg.Loc = getLoc(); 7154 if (isToken(AsmToken::Identifier) && 7155 (Msg.Id = getMsgId(getTokenStr(), getSTI())) != OPR_ID_UNKNOWN) { 7156 Msg.IsSymbolic = true; 7157 lex(); // skip message name 7158 } else if (!parseExpr(Msg.Id, "a message name")) { 7159 return false; 7160 } 7161 7162 if (trySkipToken(AsmToken::Comma)) { 7163 Op.IsDefined = true; 7164 Op.Loc = getLoc(); 7165 if (isToken(AsmToken::Identifier) && 7166 (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) { 7167 lex(); // skip operation name 7168 } else if (!parseExpr(Op.Id, "an operation name")) { 7169 return false; 7170 } 7171 7172 if (trySkipToken(AsmToken::Comma)) { 7173 Stream.IsDefined = true; 7174 Stream.Loc = getLoc(); 7175 if (!parseExpr(Stream.Id)) 7176 return false; 7177 } 7178 } 7179 7180 return skipToken(AsmToken::RParen, "expected a closing parenthesis"); 7181 } 7182 7183 bool 7184 AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg, 7185 const OperandInfoTy &Op, 7186 const OperandInfoTy &Stream) { 7187 using namespace llvm::AMDGPU::SendMsg; 7188 7189 // Validation strictness depends on whether message is specified 7190 // in a symbolic or in a numeric form. In the latter case 7191 // only encoding possibility is checked. 7192 bool Strict = Msg.IsSymbolic; 7193 7194 if (Strict) { 7195 if (Msg.Id == OPR_ID_UNSUPPORTED) { 7196 Error(Msg.Loc, "specified message id is not supported on this GPU"); 7197 return false; 7198 } 7199 } else { 7200 if (!isValidMsgId(Msg.Id, getSTI())) { 7201 Error(Msg.Loc, "invalid message id"); 7202 return false; 7203 } 7204 } 7205 if (Strict && (msgRequiresOp(Msg.Id, getSTI()) != Op.IsDefined)) { 7206 if (Op.IsDefined) { 7207 Error(Op.Loc, "message does not support operations"); 7208 } else { 7209 Error(Msg.Loc, "missing message operation"); 7210 } 7211 return false; 7212 } 7213 if (!isValidMsgOp(Msg.Id, Op.Id, getSTI(), Strict)) { 7214 Error(Op.Loc, "invalid operation id"); 7215 return false; 7216 } 7217 if (Strict && !msgSupportsStream(Msg.Id, Op.Id, getSTI()) && 7218 Stream.IsDefined) { 7219 Error(Stream.Loc, "message operation does not support streams"); 7220 return false; 7221 } 7222 if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, getSTI(), Strict)) { 7223 Error(Stream.Loc, "invalid message stream id"); 7224 return false; 7225 } 7226 return true; 7227 } 7228 7229 ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) { 7230 using namespace llvm::AMDGPU::SendMsg; 7231 7232 int64_t ImmVal = 0; 7233 SMLoc Loc = getLoc(); 7234 7235 if (trySkipId("sendmsg", AsmToken::LParen)) { 7236 OperandInfoTy Msg(OPR_ID_UNKNOWN); 7237 OperandInfoTy Op(OP_NONE_); 7238 OperandInfoTy Stream(STREAM_ID_NONE_); 7239 if (parseSendMsgBody(Msg, Op, Stream) && 7240 validateSendMsg(Msg, Op, Stream)) { 7241 ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id); 7242 } else { 7243 return ParseStatus::Failure; 7244 } 7245 } else if (parseExpr(ImmVal, "a sendmsg macro")) { 7246 if (ImmVal < 0 || !isUInt<16>(ImmVal)) 7247 return Error(Loc, "invalid immediate: only 16-bit values are legal"); 7248 } else { 7249 return ParseStatus::Failure; 7250 } 7251 7252 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg)); 7253 return ParseStatus::Success; 7254 } 7255 7256 bool AMDGPUOperand::isSendMsg() const { 7257 return isImmTy(ImmTySendMsg); 7258 } 7259 7260 //===----------------------------------------------------------------------===// 7261 // v_interp 7262 //===----------------------------------------------------------------------===// 7263 7264 ParseStatus AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) { 7265 StringRef Str; 7266 SMLoc S = getLoc(); 7267 7268 if (!parseId(Str)) 7269 return ParseStatus::NoMatch; 7270 7271 int Slot = StringSwitch<int>(Str) 7272 .Case("p10", 0) 7273 .Case("p20", 1) 7274 .Case("p0", 2) 7275 .Default(-1); 7276 7277 if (Slot == -1) 7278 return Error(S, "invalid interpolation slot"); 7279 7280 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S, 7281 AMDGPUOperand::ImmTyInterpSlot)); 7282 return ParseStatus::Success; 7283 } 7284 7285 ParseStatus AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) { 7286 StringRef Str; 7287 SMLoc S = getLoc(); 7288 7289 if (!parseId(Str)) 7290 return ParseStatus::NoMatch; 7291 7292 if (!Str.starts_with("attr")) 7293 return Error(S, "invalid interpolation attribute"); 7294 7295 StringRef Chan = Str.take_back(2); 7296 int AttrChan = StringSwitch<int>(Chan) 7297 .Case(".x", 0) 7298 .Case(".y", 1) 7299 .Case(".z", 2) 7300 .Case(".w", 3) 7301 .Default(-1); 7302 if (AttrChan == -1) 7303 return Error(S, "invalid or missing interpolation attribute channel"); 7304 7305 Str = Str.drop_back(2).drop_front(4); 7306 7307 uint8_t Attr; 7308 if (Str.getAsInteger(10, Attr)) 7309 return Error(S, "invalid or missing interpolation attribute number"); 7310 7311 if (Attr > 32) 7312 return Error(S, "out of bounds interpolation attribute number"); 7313 7314 SMLoc SChan = SMLoc::getFromPointer(Chan.data()); 7315 7316 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S, 7317 AMDGPUOperand::ImmTyInterpAttr)); 7318 Operands.push_back(AMDGPUOperand::CreateImm( 7319 this, AttrChan, SChan, AMDGPUOperand::ImmTyInterpAttrChan)); 7320 return ParseStatus::Success; 7321 } 7322 7323 //===----------------------------------------------------------------------===// 7324 // exp 7325 //===----------------------------------------------------------------------===// 7326 7327 ParseStatus AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) { 7328 using namespace llvm::AMDGPU::Exp; 7329 7330 StringRef Str; 7331 SMLoc S = getLoc(); 7332 7333 if (!parseId(Str)) 7334 return ParseStatus::NoMatch; 7335 7336 unsigned Id = getTgtId(Str); 7337 if (Id == ET_INVALID || !isSupportedTgtId(Id, getSTI())) 7338 return Error(S, (Id == ET_INVALID) 7339 ? "invalid exp target" 7340 : "exp target is not supported on this GPU"); 7341 7342 Operands.push_back(AMDGPUOperand::CreateImm(this, Id, S, 7343 AMDGPUOperand::ImmTyExpTgt)); 7344 return ParseStatus::Success; 7345 } 7346 7347 //===----------------------------------------------------------------------===// 7348 // parser helpers 7349 //===----------------------------------------------------------------------===// 7350 7351 bool 7352 AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const { 7353 return Token.is(AsmToken::Identifier) && Token.getString() == Id; 7354 } 7355 7356 bool 7357 AMDGPUAsmParser::isId(const StringRef Id) const { 7358 return isId(getToken(), Id); 7359 } 7360 7361 bool 7362 AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const { 7363 return getTokenKind() == Kind; 7364 } 7365 7366 StringRef AMDGPUAsmParser::getId() const { 7367 return isToken(AsmToken::Identifier) ? getTokenStr() : StringRef(); 7368 } 7369 7370 bool 7371 AMDGPUAsmParser::trySkipId(const StringRef Id) { 7372 if (isId(Id)) { 7373 lex(); 7374 return true; 7375 } 7376 return false; 7377 } 7378 7379 bool 7380 AMDGPUAsmParser::trySkipId(const StringRef Pref, const StringRef Id) { 7381 if (isToken(AsmToken::Identifier)) { 7382 StringRef Tok = getTokenStr(); 7383 if (Tok.starts_with(Pref) && Tok.drop_front(Pref.size()) == Id) { 7384 lex(); 7385 return true; 7386 } 7387 } 7388 return false; 7389 } 7390 7391 bool 7392 AMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) { 7393 if (isId(Id) && peekToken().is(Kind)) { 7394 lex(); 7395 lex(); 7396 return true; 7397 } 7398 return false; 7399 } 7400 7401 bool 7402 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) { 7403 if (isToken(Kind)) { 7404 lex(); 7405 return true; 7406 } 7407 return false; 7408 } 7409 7410 bool 7411 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind, 7412 const StringRef ErrMsg) { 7413 if (!trySkipToken(Kind)) { 7414 Error(getLoc(), ErrMsg); 7415 return false; 7416 } 7417 return true; 7418 } 7419 7420 bool 7421 AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) { 7422 SMLoc S = getLoc(); 7423 7424 const MCExpr *Expr; 7425 if (Parser.parseExpression(Expr)) 7426 return false; 7427 7428 if (Expr->evaluateAsAbsolute(Imm)) 7429 return true; 7430 7431 if (Expected.empty()) { 7432 Error(S, "expected absolute expression"); 7433 } else { 7434 Error(S, Twine("expected ", Expected) + 7435 Twine(" or an absolute expression")); 7436 } 7437 return false; 7438 } 7439 7440 bool 7441 AMDGPUAsmParser::parseExpr(OperandVector &Operands) { 7442 SMLoc S = getLoc(); 7443 7444 const MCExpr *Expr; 7445 if (Parser.parseExpression(Expr)) 7446 return false; 7447 7448 int64_t IntVal; 7449 if (Expr->evaluateAsAbsolute(IntVal)) { 7450 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 7451 } else { 7452 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 7453 } 7454 return true; 7455 } 7456 7457 bool 7458 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) { 7459 if (isToken(AsmToken::String)) { 7460 Val = getToken().getStringContents(); 7461 lex(); 7462 return true; 7463 } else { 7464 Error(getLoc(), ErrMsg); 7465 return false; 7466 } 7467 } 7468 7469 bool 7470 AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) { 7471 if (isToken(AsmToken::Identifier)) { 7472 Val = getTokenStr(); 7473 lex(); 7474 return true; 7475 } else { 7476 if (!ErrMsg.empty()) 7477 Error(getLoc(), ErrMsg); 7478 return false; 7479 } 7480 } 7481 7482 AsmToken 7483 AMDGPUAsmParser::getToken() const { 7484 return Parser.getTok(); 7485 } 7486 7487 AsmToken AMDGPUAsmParser::peekToken(bool ShouldSkipSpace) { 7488 return isToken(AsmToken::EndOfStatement) 7489 ? getToken() 7490 : getLexer().peekTok(ShouldSkipSpace); 7491 } 7492 7493 void 7494 AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) { 7495 auto TokCount = getLexer().peekTokens(Tokens); 7496 7497 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx) 7498 Tokens[Idx] = AsmToken(AsmToken::Error, ""); 7499 } 7500 7501 AsmToken::TokenKind 7502 AMDGPUAsmParser::getTokenKind() const { 7503 return getLexer().getKind(); 7504 } 7505 7506 SMLoc 7507 AMDGPUAsmParser::getLoc() const { 7508 return getToken().getLoc(); 7509 } 7510 7511 StringRef 7512 AMDGPUAsmParser::getTokenStr() const { 7513 return getToken().getString(); 7514 } 7515 7516 void 7517 AMDGPUAsmParser::lex() { 7518 Parser.Lex(); 7519 } 7520 7521 SMLoc AMDGPUAsmParser::getInstLoc(const OperandVector &Operands) const { 7522 return ((AMDGPUOperand &)*Operands[0]).getStartLoc(); 7523 } 7524 7525 SMLoc 7526 AMDGPUAsmParser::getOperandLoc(std::function<bool(const AMDGPUOperand&)> Test, 7527 const OperandVector &Operands) const { 7528 for (unsigned i = Operands.size() - 1; i > 0; --i) { 7529 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 7530 if (Test(Op)) 7531 return Op.getStartLoc(); 7532 } 7533 return getInstLoc(Operands); 7534 } 7535 7536 SMLoc 7537 AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type, 7538 const OperandVector &Operands) const { 7539 auto Test = [=](const AMDGPUOperand& Op) { return Op.isImmTy(Type); }; 7540 return getOperandLoc(Test, Operands); 7541 } 7542 7543 SMLoc 7544 AMDGPUAsmParser::getRegLoc(unsigned Reg, 7545 const OperandVector &Operands) const { 7546 auto Test = [=](const AMDGPUOperand& Op) { 7547 return Op.isRegKind() && Op.getReg() == Reg; 7548 }; 7549 return getOperandLoc(Test, Operands); 7550 } 7551 7552 SMLoc AMDGPUAsmParser::getLitLoc(const OperandVector &Operands, 7553 bool SearchMandatoryLiterals) const { 7554 auto Test = [](const AMDGPUOperand& Op) { 7555 return Op.IsImmKindLiteral() || Op.isExpr(); 7556 }; 7557 SMLoc Loc = getOperandLoc(Test, Operands); 7558 if (SearchMandatoryLiterals && Loc == getInstLoc(Operands)) 7559 Loc = getMandatoryLitLoc(Operands); 7560 return Loc; 7561 } 7562 7563 SMLoc AMDGPUAsmParser::getMandatoryLitLoc(const OperandVector &Operands) const { 7564 auto Test = [](const AMDGPUOperand &Op) { 7565 return Op.IsImmKindMandatoryLiteral(); 7566 }; 7567 return getOperandLoc(Test, Operands); 7568 } 7569 7570 SMLoc 7571 AMDGPUAsmParser::getConstLoc(const OperandVector &Operands) const { 7572 auto Test = [](const AMDGPUOperand& Op) { 7573 return Op.isImmKindConst(); 7574 }; 7575 return getOperandLoc(Test, Operands); 7576 } 7577 7578 //===----------------------------------------------------------------------===// 7579 // swizzle 7580 //===----------------------------------------------------------------------===// 7581 7582 LLVM_READNONE 7583 static unsigned 7584 encodeBitmaskPerm(const unsigned AndMask, 7585 const unsigned OrMask, 7586 const unsigned XorMask) { 7587 using namespace llvm::AMDGPU::Swizzle; 7588 7589 return BITMASK_PERM_ENC | 7590 (AndMask << BITMASK_AND_SHIFT) | 7591 (OrMask << BITMASK_OR_SHIFT) | 7592 (XorMask << BITMASK_XOR_SHIFT); 7593 } 7594 7595 bool 7596 AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, 7597 const unsigned MinVal, 7598 const unsigned MaxVal, 7599 const StringRef ErrMsg, 7600 SMLoc &Loc) { 7601 if (!skipToken(AsmToken::Comma, "expected a comma")) { 7602 return false; 7603 } 7604 Loc = getLoc(); 7605 if (!parseExpr(Op)) { 7606 return false; 7607 } 7608 if (Op < MinVal || Op > MaxVal) { 7609 Error(Loc, ErrMsg); 7610 return false; 7611 } 7612 7613 return true; 7614 } 7615 7616 bool 7617 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 7618 const unsigned MinVal, 7619 const unsigned MaxVal, 7620 const StringRef ErrMsg) { 7621 SMLoc Loc; 7622 for (unsigned i = 0; i < OpNum; ++i) { 7623 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc)) 7624 return false; 7625 } 7626 7627 return true; 7628 } 7629 7630 bool 7631 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) { 7632 using namespace llvm::AMDGPU::Swizzle; 7633 7634 int64_t Lane[LANE_NUM]; 7635 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX, 7636 "expected a 2-bit lane id")) { 7637 Imm = QUAD_PERM_ENC; 7638 for (unsigned I = 0; I < LANE_NUM; ++I) { 7639 Imm |= Lane[I] << (LANE_SHIFT * I); 7640 } 7641 return true; 7642 } 7643 return false; 7644 } 7645 7646 bool 7647 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) { 7648 using namespace llvm::AMDGPU::Swizzle; 7649 7650 SMLoc Loc; 7651 int64_t GroupSize; 7652 int64_t LaneIdx; 7653 7654 if (!parseSwizzleOperand(GroupSize, 7655 2, 32, 7656 "group size must be in the interval [2,32]", 7657 Loc)) { 7658 return false; 7659 } 7660 if (!isPowerOf2_64(GroupSize)) { 7661 Error(Loc, "group size must be a power of two"); 7662 return false; 7663 } 7664 if (parseSwizzleOperand(LaneIdx, 7665 0, GroupSize - 1, 7666 "lane id must be in the interval [0,group size - 1]", 7667 Loc)) { 7668 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0); 7669 return true; 7670 } 7671 return false; 7672 } 7673 7674 bool 7675 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) { 7676 using namespace llvm::AMDGPU::Swizzle; 7677 7678 SMLoc Loc; 7679 int64_t GroupSize; 7680 7681 if (!parseSwizzleOperand(GroupSize, 7682 2, 32, 7683 "group size must be in the interval [2,32]", 7684 Loc)) { 7685 return false; 7686 } 7687 if (!isPowerOf2_64(GroupSize)) { 7688 Error(Loc, "group size must be a power of two"); 7689 return false; 7690 } 7691 7692 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1); 7693 return true; 7694 } 7695 7696 bool 7697 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) { 7698 using namespace llvm::AMDGPU::Swizzle; 7699 7700 SMLoc Loc; 7701 int64_t GroupSize; 7702 7703 if (!parseSwizzleOperand(GroupSize, 7704 1, 16, 7705 "group size must be in the interval [1,16]", 7706 Loc)) { 7707 return false; 7708 } 7709 if (!isPowerOf2_64(GroupSize)) { 7710 Error(Loc, "group size must be a power of two"); 7711 return false; 7712 } 7713 7714 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize); 7715 return true; 7716 } 7717 7718 bool 7719 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) { 7720 using namespace llvm::AMDGPU::Swizzle; 7721 7722 if (!skipToken(AsmToken::Comma, "expected a comma")) { 7723 return false; 7724 } 7725 7726 StringRef Ctl; 7727 SMLoc StrLoc = getLoc(); 7728 if (!parseString(Ctl)) { 7729 return false; 7730 } 7731 if (Ctl.size() != BITMASK_WIDTH) { 7732 Error(StrLoc, "expected a 5-character mask"); 7733 return false; 7734 } 7735 7736 unsigned AndMask = 0; 7737 unsigned OrMask = 0; 7738 unsigned XorMask = 0; 7739 7740 for (size_t i = 0; i < Ctl.size(); ++i) { 7741 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i); 7742 switch(Ctl[i]) { 7743 default: 7744 Error(StrLoc, "invalid mask"); 7745 return false; 7746 case '0': 7747 break; 7748 case '1': 7749 OrMask |= Mask; 7750 break; 7751 case 'p': 7752 AndMask |= Mask; 7753 break; 7754 case 'i': 7755 AndMask |= Mask; 7756 XorMask |= Mask; 7757 break; 7758 } 7759 } 7760 7761 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask); 7762 return true; 7763 } 7764 7765 bool 7766 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) { 7767 7768 SMLoc OffsetLoc = getLoc(); 7769 7770 if (!parseExpr(Imm, "a swizzle macro")) { 7771 return false; 7772 } 7773 if (!isUInt<16>(Imm)) { 7774 Error(OffsetLoc, "expected a 16-bit offset"); 7775 return false; 7776 } 7777 return true; 7778 } 7779 7780 bool 7781 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) { 7782 using namespace llvm::AMDGPU::Swizzle; 7783 7784 if (skipToken(AsmToken::LParen, "expected a left parentheses")) { 7785 7786 SMLoc ModeLoc = getLoc(); 7787 bool Ok = false; 7788 7789 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) { 7790 Ok = parseSwizzleQuadPerm(Imm); 7791 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) { 7792 Ok = parseSwizzleBitmaskPerm(Imm); 7793 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) { 7794 Ok = parseSwizzleBroadcast(Imm); 7795 } else if (trySkipId(IdSymbolic[ID_SWAP])) { 7796 Ok = parseSwizzleSwap(Imm); 7797 } else if (trySkipId(IdSymbolic[ID_REVERSE])) { 7798 Ok = parseSwizzleReverse(Imm); 7799 } else { 7800 Error(ModeLoc, "expected a swizzle mode"); 7801 } 7802 7803 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses"); 7804 } 7805 7806 return false; 7807 } 7808 7809 ParseStatus AMDGPUAsmParser::parseSwizzle(OperandVector &Operands) { 7810 SMLoc S = getLoc(); 7811 int64_t Imm = 0; 7812 7813 if (trySkipId("offset")) { 7814 7815 bool Ok = false; 7816 if (skipToken(AsmToken::Colon, "expected a colon")) { 7817 if (trySkipId("swizzle")) { 7818 Ok = parseSwizzleMacro(Imm); 7819 } else { 7820 Ok = parseSwizzleOffset(Imm); 7821 } 7822 } 7823 7824 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle)); 7825 7826 return Ok ? ParseStatus::Success : ParseStatus::Failure; 7827 } 7828 return ParseStatus::NoMatch; 7829 } 7830 7831 bool 7832 AMDGPUOperand::isSwizzle() const { 7833 return isImmTy(ImmTySwizzle); 7834 } 7835 7836 //===----------------------------------------------------------------------===// 7837 // VGPR Index Mode 7838 //===----------------------------------------------------------------------===// 7839 7840 int64_t AMDGPUAsmParser::parseGPRIdxMacro() { 7841 7842 using namespace llvm::AMDGPU::VGPRIndexMode; 7843 7844 if (trySkipToken(AsmToken::RParen)) { 7845 return OFF; 7846 } 7847 7848 int64_t Imm = 0; 7849 7850 while (true) { 7851 unsigned Mode = 0; 7852 SMLoc S = getLoc(); 7853 7854 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) { 7855 if (trySkipId(IdSymbolic[ModeId])) { 7856 Mode = 1 << ModeId; 7857 break; 7858 } 7859 } 7860 7861 if (Mode == 0) { 7862 Error(S, (Imm == 0)? 7863 "expected a VGPR index mode or a closing parenthesis" : 7864 "expected a VGPR index mode"); 7865 return UNDEF; 7866 } 7867 7868 if (Imm & Mode) { 7869 Error(S, "duplicate VGPR index mode"); 7870 return UNDEF; 7871 } 7872 Imm |= Mode; 7873 7874 if (trySkipToken(AsmToken::RParen)) 7875 break; 7876 if (!skipToken(AsmToken::Comma, 7877 "expected a comma or a closing parenthesis")) 7878 return UNDEF; 7879 } 7880 7881 return Imm; 7882 } 7883 7884 ParseStatus AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) { 7885 7886 using namespace llvm::AMDGPU::VGPRIndexMode; 7887 7888 int64_t Imm = 0; 7889 SMLoc S = getLoc(); 7890 7891 if (trySkipId("gpr_idx", AsmToken::LParen)) { 7892 Imm = parseGPRIdxMacro(); 7893 if (Imm == UNDEF) 7894 return ParseStatus::Failure; 7895 } else { 7896 if (getParser().parseAbsoluteExpression(Imm)) 7897 return ParseStatus::Failure; 7898 if (Imm < 0 || !isUInt<4>(Imm)) 7899 return Error(S, "invalid immediate: only 4-bit values are legal"); 7900 } 7901 7902 Operands.push_back( 7903 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode)); 7904 return ParseStatus::Success; 7905 } 7906 7907 bool AMDGPUOperand::isGPRIdxMode() const { 7908 return isImmTy(ImmTyGprIdxMode); 7909 } 7910 7911 //===----------------------------------------------------------------------===// 7912 // sopp branch targets 7913 //===----------------------------------------------------------------------===// 7914 7915 ParseStatus AMDGPUAsmParser::parseSOPPBrTarget(OperandVector &Operands) { 7916 7917 // Make sure we are not parsing something 7918 // that looks like a label or an expression but is not. 7919 // This will improve error messages. 7920 if (isRegister() || isModifier()) 7921 return ParseStatus::NoMatch; 7922 7923 if (!parseExpr(Operands)) 7924 return ParseStatus::Failure; 7925 7926 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]); 7927 assert(Opr.isImm() || Opr.isExpr()); 7928 SMLoc Loc = Opr.getStartLoc(); 7929 7930 // Currently we do not support arbitrary expressions as branch targets. 7931 // Only labels and absolute expressions are accepted. 7932 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) { 7933 Error(Loc, "expected an absolute expression or a label"); 7934 } else if (Opr.isImm() && !Opr.isS16Imm()) { 7935 Error(Loc, "expected a 16-bit signed jump offset"); 7936 } 7937 7938 return ParseStatus::Success; 7939 } 7940 7941 //===----------------------------------------------------------------------===// 7942 // Boolean holding registers 7943 //===----------------------------------------------------------------------===// 7944 7945 ParseStatus AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) { 7946 return parseReg(Operands); 7947 } 7948 7949 //===----------------------------------------------------------------------===// 7950 // mubuf 7951 //===----------------------------------------------------------------------===// 7952 7953 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, 7954 const OperandVector &Operands, 7955 bool IsAtomic) { 7956 OptionalImmIndexMap OptionalIdx; 7957 unsigned FirstOperandIdx = 1; 7958 bool IsAtomicReturn = false; 7959 7960 if (IsAtomic) { 7961 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) { 7962 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 7963 if (!Op.isCPol()) 7964 continue; 7965 IsAtomicReturn = Op.getImm() & AMDGPU::CPol::GLC; 7966 break; 7967 } 7968 7969 if (!IsAtomicReturn) { 7970 int NewOpc = AMDGPU::getAtomicNoRetOp(Inst.getOpcode()); 7971 if (NewOpc != -1) 7972 Inst.setOpcode(NewOpc); 7973 } 7974 7975 IsAtomicReturn = MII.get(Inst.getOpcode()).TSFlags & 7976 SIInstrFlags::IsAtomicRet; 7977 } 7978 7979 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) { 7980 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 7981 7982 // Add the register arguments 7983 if (Op.isReg()) { 7984 Op.addRegOperands(Inst, 1); 7985 // Insert a tied src for atomic return dst. 7986 // This cannot be postponed as subsequent calls to 7987 // addImmOperands rely on correct number of MC operands. 7988 if (IsAtomicReturn && i == FirstOperandIdx) 7989 Op.addRegOperands(Inst, 1); 7990 continue; 7991 } 7992 7993 // Handle the case where soffset is an immediate 7994 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 7995 Op.addImmOperands(Inst, 1); 7996 continue; 7997 } 7998 7999 // Handle tokens like 'offen' which are sometimes hard-coded into the 8000 // asm string. There are no MCInst operands for these. 8001 if (Op.isToken()) { 8002 continue; 8003 } 8004 assert(Op.isImm()); 8005 8006 // Handle optional arguments 8007 OptionalIdx[Op.getImmTy()] = i; 8008 } 8009 8010 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 8011 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyCPol, 0); 8012 } 8013 8014 //===----------------------------------------------------------------------===// 8015 // smrd 8016 //===----------------------------------------------------------------------===// 8017 8018 bool AMDGPUOperand::isSMRDOffset8() const { 8019 return isImmLiteral() && isUInt<8>(getImm()); 8020 } 8021 8022 bool AMDGPUOperand::isSMEMOffset() const { 8023 // Offset range is checked later by validator. 8024 return isImmLiteral(); 8025 } 8026 8027 bool AMDGPUOperand::isSMRDLiteralOffset() const { 8028 // 32-bit literals are only supported on CI and we only want to use them 8029 // when the offset is > 8-bits. 8030 return isImmLiteral() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 8031 } 8032 8033 //===----------------------------------------------------------------------===// 8034 // vop3 8035 //===----------------------------------------------------------------------===// 8036 8037 static bool ConvertOmodMul(int64_t &Mul) { 8038 if (Mul != 1 && Mul != 2 && Mul != 4) 8039 return false; 8040 8041 Mul >>= 1; 8042 return true; 8043 } 8044 8045 static bool ConvertOmodDiv(int64_t &Div) { 8046 if (Div == 1) { 8047 Div = 0; 8048 return true; 8049 } 8050 8051 if (Div == 2) { 8052 Div = 3; 8053 return true; 8054 } 8055 8056 return false; 8057 } 8058 8059 // For pre-gfx11 targets, both bound_ctrl:0 and bound_ctrl:1 are encoded as 1. 8060 // This is intentional and ensures compatibility with sp3. 8061 // See bug 35397 for details. 8062 bool AMDGPUAsmParser::convertDppBoundCtrl(int64_t &BoundCtrl) { 8063 if (BoundCtrl == 0 || BoundCtrl == 1) { 8064 if (!isGFX11Plus()) 8065 BoundCtrl = 1; 8066 return true; 8067 } 8068 return false; 8069 } 8070 8071 void AMDGPUAsmParser::onBeginOfFile() { 8072 if (!getParser().getStreamer().getTargetStreamer() || 8073 getSTI().getTargetTriple().getArch() == Triple::r600) 8074 return; 8075 8076 if (!getTargetStreamer().getTargetID()) 8077 getTargetStreamer().initializeTargetID(getSTI(), 8078 getSTI().getFeatureString()); 8079 8080 if (isHsaAbi(getSTI())) 8081 getTargetStreamer().EmitDirectiveAMDGCNTarget(); 8082 } 8083 8084 ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) { 8085 StringRef Name = getTokenStr(); 8086 if (Name == "mul") { 8087 return parseIntWithPrefix("mul", Operands, 8088 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul); 8089 } 8090 8091 if (Name == "div") { 8092 return parseIntWithPrefix("div", Operands, 8093 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv); 8094 } 8095 8096 return ParseStatus::NoMatch; 8097 } 8098 8099 // Determines which bit DST_OP_SEL occupies in the op_sel operand according to 8100 // the number of src operands present, then copies that bit into src0_modifiers. 8101 void cvtVOP3DstOpSelOnly(MCInst &Inst) { 8102 int Opc = Inst.getOpcode(); 8103 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 8104 if (OpSelIdx == -1) 8105 return; 8106 8107 int SrcNum; 8108 const int Ops[] = { AMDGPU::OpName::src0, 8109 AMDGPU::OpName::src1, 8110 AMDGPU::OpName::src2 }; 8111 for (SrcNum = 0; SrcNum < 3 && AMDGPU::hasNamedOperand(Opc, Ops[SrcNum]); 8112 ++SrcNum) 8113 ; 8114 assert(SrcNum > 0); 8115 8116 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 8117 8118 if ((OpSel & (1 << SrcNum)) != 0) { 8119 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers); 8120 uint32_t ModVal = Inst.getOperand(ModIdx).getImm(); 8121 Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL); 8122 } 8123 } 8124 8125 void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, 8126 const OperandVector &Operands) { 8127 cvtVOP3P(Inst, Operands); 8128 cvtVOP3DstOpSelOnly(Inst); 8129 } 8130 8131 void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands, 8132 OptionalImmIndexMap &OptionalIdx) { 8133 cvtVOP3P(Inst, Operands, OptionalIdx); 8134 cvtVOP3DstOpSelOnly(Inst); 8135 } 8136 8137 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) { 8138 return 8139 // 1. This operand is input modifiers 8140 Desc.operands()[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS 8141 // 2. This is not last operand 8142 && Desc.NumOperands > (OpNum + 1) 8143 // 3. Next operand is register class 8144 && Desc.operands()[OpNum + 1].RegClass != -1 8145 // 4. Next register is not tied to any other operand 8146 && Desc.getOperandConstraint(OpNum + 1, 8147 MCOI::OperandConstraint::TIED_TO) == -1; 8148 } 8149 8150 void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands) 8151 { 8152 OptionalImmIndexMap OptionalIdx; 8153 unsigned Opc = Inst.getOpcode(); 8154 8155 unsigned I = 1; 8156 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8157 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8158 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8159 } 8160 8161 for (unsigned E = Operands.size(); I != E; ++I) { 8162 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8163 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8164 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 8165 } else if (Op.isInterpSlot() || Op.isInterpAttr() || 8166 Op.isInterpAttrChan()) { 8167 Inst.addOperand(MCOperand::createImm(Op.getImm())); 8168 } else if (Op.isImmModifier()) { 8169 OptionalIdx[Op.getImmTy()] = I; 8170 } else { 8171 llvm_unreachable("unhandled operand type"); 8172 } 8173 } 8174 8175 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::high)) 8176 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8177 AMDGPUOperand::ImmTyHigh); 8178 8179 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp)) 8180 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8181 AMDGPUOperand::ImmTyClampSI); 8182 8183 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod)) 8184 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8185 AMDGPUOperand::ImmTyOModSI); 8186 } 8187 8188 void AMDGPUAsmParser::cvtVINTERP(MCInst &Inst, const OperandVector &Operands) 8189 { 8190 OptionalImmIndexMap OptionalIdx; 8191 unsigned Opc = Inst.getOpcode(); 8192 8193 unsigned I = 1; 8194 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8195 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8196 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8197 } 8198 8199 for (unsigned E = Operands.size(); I != E; ++I) { 8200 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8201 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8202 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 8203 } else if (Op.isImmModifier()) { 8204 OptionalIdx[Op.getImmTy()] = I; 8205 } else { 8206 llvm_unreachable("unhandled operand type"); 8207 } 8208 } 8209 8210 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 8211 8212 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 8213 if (OpSelIdx != -1) 8214 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOpSel); 8215 8216 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyWaitEXP); 8217 8218 if (OpSelIdx == -1) 8219 return; 8220 8221 const int Ops[] = { AMDGPU::OpName::src0, 8222 AMDGPU::OpName::src1, 8223 AMDGPU::OpName::src2 }; 8224 const int ModOps[] = { AMDGPU::OpName::src0_modifiers, 8225 AMDGPU::OpName::src1_modifiers, 8226 AMDGPU::OpName::src2_modifiers }; 8227 8228 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 8229 8230 for (int J = 0; J < 3; ++J) { 8231 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]); 8232 if (OpIdx == -1) 8233 break; 8234 8235 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); 8236 uint32_t ModVal = Inst.getOperand(ModIdx).getImm(); 8237 8238 if ((OpSel & (1 << J)) != 0) 8239 ModVal |= SISrcMods::OP_SEL_0; 8240 if (ModOps[J] == AMDGPU::OpName::src0_modifiers && 8241 (OpSel & (1 << 3)) != 0) 8242 ModVal |= SISrcMods::DST_OP_SEL; 8243 8244 Inst.getOperand(ModIdx).setImm(ModVal); 8245 } 8246 } 8247 8248 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands, 8249 OptionalImmIndexMap &OptionalIdx) { 8250 unsigned Opc = Inst.getOpcode(); 8251 8252 unsigned I = 1; 8253 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8254 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8255 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8256 } 8257 8258 for (unsigned E = Operands.size(); I != E; ++I) { 8259 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8260 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8261 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 8262 } else if (Op.isImmModifier()) { 8263 OptionalIdx[Op.getImmTy()] = I; 8264 } else if (Op.isRegOrImm()) { 8265 Op.addRegOrImmOperands(Inst, 1); 8266 } else { 8267 llvm_unreachable("unhandled operand type"); 8268 } 8269 } 8270 8271 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp)) 8272 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8273 AMDGPUOperand::ImmTyClampSI); 8274 8275 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod)) 8276 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8277 AMDGPUOperand::ImmTyOModSI); 8278 8279 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+): 8280 // it has src2 register operand that is tied to dst operand 8281 // we don't allow modifiers for this operand in assembler so src2_modifiers 8282 // should be 0. 8283 if (isMAC(Opc)) { 8284 auto it = Inst.begin(); 8285 std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers)); 8286 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2 8287 ++it; 8288 // Copy the operand to ensure it's not invalidated when Inst grows. 8289 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst 8290 } 8291 } 8292 8293 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 8294 OptionalImmIndexMap OptionalIdx; 8295 cvtVOP3(Inst, Operands, OptionalIdx); 8296 } 8297 8298 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands, 8299 OptionalImmIndexMap &OptIdx) { 8300 const int Opc = Inst.getOpcode(); 8301 const MCInstrDesc &Desc = MII.get(Opc); 8302 8303 const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0; 8304 8305 if (Opc == AMDGPU::V_CVT_SR_BF8_F32_vi || 8306 Opc == AMDGPU::V_CVT_SR_FP8_F32_vi) { 8307 Inst.addOperand(MCOperand::createImm(0)); // Placeholder for src2_mods 8308 Inst.addOperand(Inst.getOperand(0)); 8309 } 8310 8311 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in)) { 8312 assert(!IsPacked); 8313 Inst.addOperand(Inst.getOperand(0)); 8314 } 8315 8316 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3 8317 // instruction, and then figure out where to actually put the modifiers 8318 8319 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 8320 if (OpSelIdx != -1) { 8321 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel); 8322 } 8323 8324 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi); 8325 if (OpSelHiIdx != -1) { 8326 int DefaultVal = IsPacked ? -1 : 0; 8327 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, 8328 DefaultVal); 8329 } 8330 8331 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo); 8332 if (NegLoIdx != -1) { 8333 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo); 8334 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi); 8335 } 8336 8337 const int Ops[] = { AMDGPU::OpName::src0, 8338 AMDGPU::OpName::src1, 8339 AMDGPU::OpName::src2 }; 8340 const int ModOps[] = { AMDGPU::OpName::src0_modifiers, 8341 AMDGPU::OpName::src1_modifiers, 8342 AMDGPU::OpName::src2_modifiers }; 8343 8344 unsigned OpSel = 0; 8345 unsigned OpSelHi = 0; 8346 unsigned NegLo = 0; 8347 unsigned NegHi = 0; 8348 8349 if (OpSelIdx != -1) 8350 OpSel = Inst.getOperand(OpSelIdx).getImm(); 8351 8352 if (OpSelHiIdx != -1) 8353 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm(); 8354 8355 if (NegLoIdx != -1) { 8356 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi); 8357 NegLo = Inst.getOperand(NegLoIdx).getImm(); 8358 NegHi = Inst.getOperand(NegHiIdx).getImm(); 8359 } 8360 8361 for (int J = 0; J < 3; ++J) { 8362 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]); 8363 if (OpIdx == -1) 8364 break; 8365 8366 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); 8367 8368 if (ModIdx == -1) 8369 continue; 8370 8371 uint32_t ModVal = 0; 8372 8373 if ((OpSel & (1 << J)) != 0) 8374 ModVal |= SISrcMods::OP_SEL_0; 8375 8376 if ((OpSelHi & (1 << J)) != 0) 8377 ModVal |= SISrcMods::OP_SEL_1; 8378 8379 if ((NegLo & (1 << J)) != 0) 8380 ModVal |= SISrcMods::NEG; 8381 8382 if ((NegHi & (1 << J)) != 0) 8383 ModVal |= SISrcMods::NEG_HI; 8384 8385 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal); 8386 } 8387 } 8388 8389 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) { 8390 OptionalImmIndexMap OptIdx; 8391 cvtVOP3(Inst, Operands, OptIdx); 8392 cvtVOP3P(Inst, Operands, OptIdx); 8393 } 8394 8395 //===----------------------------------------------------------------------===// 8396 // VOPD 8397 //===----------------------------------------------------------------------===// 8398 8399 ParseStatus AMDGPUAsmParser::parseVOPD(OperandVector &Operands) { 8400 if (!hasVOPD(getSTI())) 8401 return ParseStatus::NoMatch; 8402 8403 if (isToken(AsmToken::Colon) && peekToken(false).is(AsmToken::Colon)) { 8404 SMLoc S = getLoc(); 8405 lex(); 8406 lex(); 8407 Operands.push_back(AMDGPUOperand::CreateToken(this, "::", S)); 8408 SMLoc OpYLoc = getLoc(); 8409 StringRef OpYName; 8410 if (isToken(AsmToken::Identifier) && !Parser.parseIdentifier(OpYName)) { 8411 Operands.push_back(AMDGPUOperand::CreateToken(this, OpYName, OpYLoc)); 8412 return ParseStatus::Success; 8413 } 8414 return Error(OpYLoc, "expected a VOPDY instruction after ::"); 8415 } 8416 return ParseStatus::NoMatch; 8417 } 8418 8419 // Create VOPD MCInst operands using parsed assembler operands. 8420 void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) { 8421 auto addOp = [&](uint16_t ParsedOprIdx) { // NOLINT:function pointer 8422 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[ParsedOprIdx]); 8423 if (Op.isReg()) { 8424 Op.addRegOperands(Inst, 1); 8425 return; 8426 } 8427 if (Op.isImm()) { 8428 Op.addImmOperands(Inst, 1); 8429 return; 8430 } 8431 llvm_unreachable("Unhandled operand type in cvtVOPD"); 8432 }; 8433 8434 const auto &InstInfo = getVOPDInstInfo(Inst.getOpcode(), &MII); 8435 8436 // MCInst operands are ordered as follows: 8437 // dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands] 8438 8439 for (auto CompIdx : VOPD::COMPONENTS) { 8440 addOp(InstInfo[CompIdx].getIndexOfDstInParsedOperands()); 8441 } 8442 8443 for (auto CompIdx : VOPD::COMPONENTS) { 8444 const auto &CInfo = InstInfo[CompIdx]; 8445 auto CompSrcOperandsNum = InstInfo[CompIdx].getCompParsedSrcOperandsNum(); 8446 for (unsigned CompSrcIdx = 0; CompSrcIdx < CompSrcOperandsNum; ++CompSrcIdx) 8447 addOp(CInfo.getIndexOfSrcInParsedOperands(CompSrcIdx)); 8448 if (CInfo.hasSrc2Acc()) 8449 addOp(CInfo.getIndexOfDstInParsedOperands()); 8450 } 8451 } 8452 8453 //===----------------------------------------------------------------------===// 8454 // dpp 8455 //===----------------------------------------------------------------------===// 8456 8457 bool AMDGPUOperand::isDPP8() const { 8458 return isImmTy(ImmTyDPP8); 8459 } 8460 8461 bool AMDGPUOperand::isDPPCtrl() const { 8462 using namespace AMDGPU::DPP; 8463 8464 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 8465 if (result) { 8466 int64_t Imm = getImm(); 8467 return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) || 8468 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) || 8469 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) || 8470 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) || 8471 (Imm == DppCtrl::WAVE_SHL1) || 8472 (Imm == DppCtrl::WAVE_ROL1) || 8473 (Imm == DppCtrl::WAVE_SHR1) || 8474 (Imm == DppCtrl::WAVE_ROR1) || 8475 (Imm == DppCtrl::ROW_MIRROR) || 8476 (Imm == DppCtrl::ROW_HALF_MIRROR) || 8477 (Imm == DppCtrl::BCAST15) || 8478 (Imm == DppCtrl::BCAST31) || 8479 (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) || 8480 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST); 8481 } 8482 return false; 8483 } 8484 8485 //===----------------------------------------------------------------------===// 8486 // mAI 8487 //===----------------------------------------------------------------------===// 8488 8489 bool AMDGPUOperand::isBLGP() const { 8490 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm()); 8491 } 8492 8493 bool AMDGPUOperand::isCBSZ() const { 8494 return isImm() && getImmTy() == ImmTyCBSZ && isUInt<3>(getImm()); 8495 } 8496 8497 bool AMDGPUOperand::isABID() const { 8498 return isImm() && getImmTy() == ImmTyABID && isUInt<4>(getImm()); 8499 } 8500 8501 bool AMDGPUOperand::isS16Imm() const { 8502 return isImmLiteral() && (isInt<16>(getImm()) || isUInt<16>(getImm())); 8503 } 8504 8505 bool AMDGPUOperand::isU16Imm() const { 8506 return isImmLiteral() && isUInt<16>(getImm()); 8507 } 8508 8509 //===----------------------------------------------------------------------===// 8510 // dim 8511 //===----------------------------------------------------------------------===// 8512 8513 bool AMDGPUAsmParser::parseDimId(unsigned &Encoding) { 8514 // We want to allow "dim:1D" etc., 8515 // but the initial 1 is tokenized as an integer. 8516 std::string Token; 8517 if (isToken(AsmToken::Integer)) { 8518 SMLoc Loc = getToken().getEndLoc(); 8519 Token = std::string(getTokenStr()); 8520 lex(); 8521 if (getLoc() != Loc) 8522 return false; 8523 } 8524 8525 StringRef Suffix; 8526 if (!parseId(Suffix)) 8527 return false; 8528 Token += Suffix; 8529 8530 StringRef DimId = Token; 8531 if (DimId.starts_with("SQ_RSRC_IMG_")) 8532 DimId = DimId.drop_front(12); 8533 8534 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId); 8535 if (!DimInfo) 8536 return false; 8537 8538 Encoding = DimInfo->Encoding; 8539 return true; 8540 } 8541 8542 ParseStatus AMDGPUAsmParser::parseDim(OperandVector &Operands) { 8543 if (!isGFX10Plus()) 8544 return ParseStatus::NoMatch; 8545 8546 SMLoc S = getLoc(); 8547 8548 if (!trySkipId("dim", AsmToken::Colon)) 8549 return ParseStatus::NoMatch; 8550 8551 unsigned Encoding; 8552 SMLoc Loc = getLoc(); 8553 if (!parseDimId(Encoding)) 8554 return Error(Loc, "invalid dim value"); 8555 8556 Operands.push_back(AMDGPUOperand::CreateImm(this, Encoding, S, 8557 AMDGPUOperand::ImmTyDim)); 8558 return ParseStatus::Success; 8559 } 8560 8561 //===----------------------------------------------------------------------===// 8562 // dpp 8563 //===----------------------------------------------------------------------===// 8564 8565 ParseStatus AMDGPUAsmParser::parseDPP8(OperandVector &Operands) { 8566 SMLoc S = getLoc(); 8567 8568 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon)) 8569 return ParseStatus::NoMatch; 8570 8571 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d] 8572 8573 int64_t Sels[8]; 8574 8575 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket")) 8576 return ParseStatus::Failure; 8577 8578 for (size_t i = 0; i < 8; ++i) { 8579 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma")) 8580 return ParseStatus::Failure; 8581 8582 SMLoc Loc = getLoc(); 8583 if (getParser().parseAbsoluteExpression(Sels[i])) 8584 return ParseStatus::Failure; 8585 if (0 > Sels[i] || 7 < Sels[i]) 8586 return Error(Loc, "expected a 3-bit value"); 8587 } 8588 8589 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 8590 return ParseStatus::Failure; 8591 8592 unsigned DPP8 = 0; 8593 for (size_t i = 0; i < 8; ++i) 8594 DPP8 |= (Sels[i] << (i * 3)); 8595 8596 Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8)); 8597 return ParseStatus::Success; 8598 } 8599 8600 bool 8601 AMDGPUAsmParser::isSupportedDPPCtrl(StringRef Ctrl, 8602 const OperandVector &Operands) { 8603 if (Ctrl == "row_newbcast") 8604 return isGFX90A(); 8605 8606 if (Ctrl == "row_share" || 8607 Ctrl == "row_xmask") 8608 return isGFX10Plus(); 8609 8610 if (Ctrl == "wave_shl" || 8611 Ctrl == "wave_shr" || 8612 Ctrl == "wave_rol" || 8613 Ctrl == "wave_ror" || 8614 Ctrl == "row_bcast") 8615 return isVI() || isGFX9(); 8616 8617 return Ctrl == "row_mirror" || 8618 Ctrl == "row_half_mirror" || 8619 Ctrl == "quad_perm" || 8620 Ctrl == "row_shl" || 8621 Ctrl == "row_shr" || 8622 Ctrl == "row_ror"; 8623 } 8624 8625 int64_t 8626 AMDGPUAsmParser::parseDPPCtrlPerm() { 8627 // quad_perm:[%d,%d,%d,%d] 8628 8629 if (!skipToken(AsmToken::LBrac, "expected an opening square bracket")) 8630 return -1; 8631 8632 int64_t Val = 0; 8633 for (int i = 0; i < 4; ++i) { 8634 if (i > 0 && !skipToken(AsmToken::Comma, "expected a comma")) 8635 return -1; 8636 8637 int64_t Temp; 8638 SMLoc Loc = getLoc(); 8639 if (getParser().parseAbsoluteExpression(Temp)) 8640 return -1; 8641 if (Temp < 0 || Temp > 3) { 8642 Error(Loc, "expected a 2-bit value"); 8643 return -1; 8644 } 8645 8646 Val += (Temp << i * 2); 8647 } 8648 8649 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 8650 return -1; 8651 8652 return Val; 8653 } 8654 8655 int64_t 8656 AMDGPUAsmParser::parseDPPCtrlSel(StringRef Ctrl) { 8657 using namespace AMDGPU::DPP; 8658 8659 // sel:%d 8660 8661 int64_t Val; 8662 SMLoc Loc = getLoc(); 8663 8664 if (getParser().parseAbsoluteExpression(Val)) 8665 return -1; 8666 8667 struct DppCtrlCheck { 8668 int64_t Ctrl; 8669 int Lo; 8670 int Hi; 8671 }; 8672 8673 DppCtrlCheck Check = StringSwitch<DppCtrlCheck>(Ctrl) 8674 .Case("wave_shl", {DppCtrl::WAVE_SHL1, 1, 1}) 8675 .Case("wave_rol", {DppCtrl::WAVE_ROL1, 1, 1}) 8676 .Case("wave_shr", {DppCtrl::WAVE_SHR1, 1, 1}) 8677 .Case("wave_ror", {DppCtrl::WAVE_ROR1, 1, 1}) 8678 .Case("row_shl", {DppCtrl::ROW_SHL0, 1, 15}) 8679 .Case("row_shr", {DppCtrl::ROW_SHR0, 1, 15}) 8680 .Case("row_ror", {DppCtrl::ROW_ROR0, 1, 15}) 8681 .Case("row_share", {DppCtrl::ROW_SHARE_FIRST, 0, 15}) 8682 .Case("row_xmask", {DppCtrl::ROW_XMASK_FIRST, 0, 15}) 8683 .Case("row_newbcast", {DppCtrl::ROW_NEWBCAST_FIRST, 0, 15}) 8684 .Default({-1, 0, 0}); 8685 8686 bool Valid; 8687 if (Check.Ctrl == -1) { 8688 Valid = (Ctrl == "row_bcast" && (Val == 15 || Val == 31)); 8689 Val = (Val == 15)? DppCtrl::BCAST15 : DppCtrl::BCAST31; 8690 } else { 8691 Valid = Check.Lo <= Val && Val <= Check.Hi; 8692 Val = (Check.Lo == Check.Hi) ? Check.Ctrl : (Check.Ctrl | Val); 8693 } 8694 8695 if (!Valid) { 8696 Error(Loc, Twine("invalid ", Ctrl) + Twine(" value")); 8697 return -1; 8698 } 8699 8700 return Val; 8701 } 8702 8703 ParseStatus AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { 8704 using namespace AMDGPU::DPP; 8705 8706 if (!isToken(AsmToken::Identifier) || 8707 !isSupportedDPPCtrl(getTokenStr(), Operands)) 8708 return ParseStatus::NoMatch; 8709 8710 SMLoc S = getLoc(); 8711 int64_t Val = -1; 8712 StringRef Ctrl; 8713 8714 parseId(Ctrl); 8715 8716 if (Ctrl == "row_mirror") { 8717 Val = DppCtrl::ROW_MIRROR; 8718 } else if (Ctrl == "row_half_mirror") { 8719 Val = DppCtrl::ROW_HALF_MIRROR; 8720 } else { 8721 if (skipToken(AsmToken::Colon, "expected a colon")) { 8722 if (Ctrl == "quad_perm") { 8723 Val = parseDPPCtrlPerm(); 8724 } else { 8725 Val = parseDPPCtrlSel(Ctrl); 8726 } 8727 } 8728 } 8729 8730 if (Val == -1) 8731 return ParseStatus::Failure; 8732 8733 Operands.push_back( 8734 AMDGPUOperand::CreateImm(this, Val, S, AMDGPUOperand::ImmTyDppCtrl)); 8735 return ParseStatus::Success; 8736 } 8737 8738 void AMDGPUAsmParser::cvtVOP3DPP(MCInst &Inst, const OperandVector &Operands, 8739 bool IsDPP8) { 8740 OptionalImmIndexMap OptionalIdx; 8741 unsigned Opc = Inst.getOpcode(); 8742 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8743 8744 // MAC instructions are special because they have 'old' 8745 // operand which is not tied to dst (but assumed to be). 8746 // They also have dummy unused src2_modifiers. 8747 int OldIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old); 8748 int Src2ModIdx = 8749 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers); 8750 bool IsMAC = OldIdx != -1 && Src2ModIdx != -1 && 8751 Desc.getOperandConstraint(OldIdx, MCOI::TIED_TO) == -1; 8752 8753 unsigned I = 1; 8754 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8755 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8756 } 8757 8758 int Fi = 0; 8759 for (unsigned E = Operands.size(); I != E; ++I) { 8760 8761 if (IsMAC) { 8762 int NumOperands = Inst.getNumOperands(); 8763 if (OldIdx == NumOperands) { 8764 // Handle old operand 8765 constexpr int DST_IDX = 0; 8766 Inst.addOperand(Inst.getOperand(DST_IDX)); 8767 } else if (Src2ModIdx == NumOperands) { 8768 // Add unused dummy src2_modifiers 8769 Inst.addOperand(MCOperand::createImm(0)); 8770 } 8771 } 8772 8773 auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(), 8774 MCOI::TIED_TO); 8775 if (TiedTo != -1) { 8776 assert((unsigned)TiedTo < Inst.getNumOperands()); 8777 // handle tied old or src2 for MAC instructions 8778 Inst.addOperand(Inst.getOperand(TiedTo)); 8779 } 8780 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8781 // Add the register arguments 8782 if (IsDPP8 && Op.isDppFI()) { 8783 Fi = Op.getImm(); 8784 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8785 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 8786 } else if (Op.isReg()) { 8787 Op.addRegOperands(Inst, 1); 8788 } else if (Op.isImm() && 8789 Desc.operands()[Inst.getNumOperands()].RegClass != -1) { 8790 assert(!Op.IsImmKindLiteral() && "Cannot use literal with DPP"); 8791 Op.addImmOperands(Inst, 1); 8792 } else if (Op.isImm()) { 8793 OptionalIdx[Op.getImmTy()] = I; 8794 } else { 8795 llvm_unreachable("unhandled operand type"); 8796 } 8797 } 8798 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp)) 8799 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 8800 8801 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod)) 8802 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 8803 8804 if (Desc.TSFlags & SIInstrFlags::VOP3P) 8805 cvtVOP3P(Inst, Operands, OptionalIdx); 8806 else if (Desc.TSFlags & SIInstrFlags::VOP3) 8807 cvtVOP3OpSel(Inst, Operands, OptionalIdx); 8808 else if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) { 8809 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOpSel); 8810 } 8811 8812 if (IsDPP8) { 8813 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDPP8); 8814 using namespace llvm::AMDGPU::DPP; 8815 Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0)); 8816 } else { 8817 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppCtrl, 0xe4); 8818 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 8819 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 8820 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 8821 8822 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) 8823 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8824 AMDGPUOperand::ImmTyDppFI); 8825 } 8826 } 8827 8828 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) { 8829 OptionalImmIndexMap OptionalIdx; 8830 8831 unsigned I = 1; 8832 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8833 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8834 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8835 } 8836 8837 int Fi = 0; 8838 for (unsigned E = Operands.size(); I != E; ++I) { 8839 auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(), 8840 MCOI::TIED_TO); 8841 if (TiedTo != -1) { 8842 assert((unsigned)TiedTo < Inst.getNumOperands()); 8843 // handle tied old or src2 for MAC instructions 8844 Inst.addOperand(Inst.getOperand(TiedTo)); 8845 } 8846 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8847 // Add the register arguments 8848 if (Op.isReg() && validateVccOperand(Op.getReg())) { 8849 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token. 8850 // Skip it. 8851 continue; 8852 } 8853 8854 if (IsDPP8) { 8855 if (Op.isDPP8()) { 8856 Op.addImmOperands(Inst, 1); 8857 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8858 Op.addRegWithFPInputModsOperands(Inst, 2); 8859 } else if (Op.isDppFI()) { 8860 Fi = Op.getImm(); 8861 } else if (Op.isReg()) { 8862 Op.addRegOperands(Inst, 1); 8863 } else { 8864 llvm_unreachable("Invalid operand type"); 8865 } 8866 } else { 8867 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 8868 Op.addRegWithFPInputModsOperands(Inst, 2); 8869 } else if (Op.isReg()) { 8870 Op.addRegOperands(Inst, 1); 8871 } else if (Op.isDPPCtrl()) { 8872 Op.addImmOperands(Inst, 1); 8873 } else if (Op.isImm()) { 8874 // Handle optional arguments 8875 OptionalIdx[Op.getImmTy()] = I; 8876 } else { 8877 llvm_unreachable("Invalid operand type"); 8878 } 8879 } 8880 } 8881 8882 if (IsDPP8) { 8883 using namespace llvm::AMDGPU::DPP; 8884 Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0)); 8885 } else { 8886 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 8887 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 8888 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 8889 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::fi)) { 8890 addOptionalImmOperand(Inst, Operands, OptionalIdx, 8891 AMDGPUOperand::ImmTyDppFI); 8892 } 8893 } 8894 } 8895 8896 //===----------------------------------------------------------------------===// 8897 // sdwa 8898 //===----------------------------------------------------------------------===// 8899 8900 ParseStatus AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, 8901 StringRef Prefix, 8902 AMDGPUOperand::ImmTy Type) { 8903 using namespace llvm::AMDGPU::SDWA; 8904 8905 SMLoc S = getLoc(); 8906 StringRef Value; 8907 8908 SMLoc StringLoc; 8909 ParseStatus Res = parseStringWithPrefix(Prefix, Value, StringLoc); 8910 if (!Res.isSuccess()) 8911 return Res; 8912 8913 int64_t Int; 8914 Int = StringSwitch<int64_t>(Value) 8915 .Case("BYTE_0", SdwaSel::BYTE_0) 8916 .Case("BYTE_1", SdwaSel::BYTE_1) 8917 .Case("BYTE_2", SdwaSel::BYTE_2) 8918 .Case("BYTE_3", SdwaSel::BYTE_3) 8919 .Case("WORD_0", SdwaSel::WORD_0) 8920 .Case("WORD_1", SdwaSel::WORD_1) 8921 .Case("DWORD", SdwaSel::DWORD) 8922 .Default(0xffffffff); 8923 8924 if (Int == 0xffffffff) 8925 return Error(StringLoc, "invalid " + Twine(Prefix) + " value"); 8926 8927 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type)); 8928 return ParseStatus::Success; 8929 } 8930 8931 ParseStatus AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 8932 using namespace llvm::AMDGPU::SDWA; 8933 8934 SMLoc S = getLoc(); 8935 StringRef Value; 8936 8937 SMLoc StringLoc; 8938 ParseStatus Res = parseStringWithPrefix("dst_unused", Value, StringLoc); 8939 if (!Res.isSuccess()) 8940 return Res; 8941 8942 int64_t Int; 8943 Int = StringSwitch<int64_t>(Value) 8944 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD) 8945 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT) 8946 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE) 8947 .Default(0xffffffff); 8948 8949 if (Int == 0xffffffff) 8950 return Error(StringLoc, "invalid dst_unused value"); 8951 8952 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySDWADstUnused)); 8953 return ParseStatus::Success; 8954 } 8955 8956 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { 8957 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); 8958 } 8959 8960 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { 8961 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); 8962 } 8963 8964 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) { 8965 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true, true); 8966 } 8967 8968 void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands) { 8969 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, false, true); 8970 } 8971 8972 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { 8973 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI()); 8974 } 8975 8976 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, 8977 uint64_t BasicInstType, 8978 bool SkipDstVcc, 8979 bool SkipSrcVcc) { 8980 using namespace llvm::AMDGPU::SDWA; 8981 8982 OptionalImmIndexMap OptionalIdx; 8983 bool SkipVcc = SkipDstVcc || SkipSrcVcc; 8984 bool SkippedVcc = false; 8985 8986 unsigned I = 1; 8987 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 8988 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 8989 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 8990 } 8991 8992 for (unsigned E = Operands.size(); I != E; ++I) { 8993 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 8994 if (SkipVcc && !SkippedVcc && Op.isReg() && 8995 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) { 8996 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. 8997 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3) 8998 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand. 8999 // Skip VCC only if we didn't skip it on previous iteration. 9000 // Note that src0 and src1 occupy 2 slots each because of modifiers. 9001 if (BasicInstType == SIInstrFlags::VOP2 && 9002 ((SkipDstVcc && Inst.getNumOperands() == 1) || 9003 (SkipSrcVcc && Inst.getNumOperands() == 5))) { 9004 SkippedVcc = true; 9005 continue; 9006 } else if (BasicInstType == SIInstrFlags::VOPC && 9007 Inst.getNumOperands() == 0) { 9008 SkippedVcc = true; 9009 continue; 9010 } 9011 } 9012 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 9013 Op.addRegOrImmWithInputModsOperands(Inst, 2); 9014 } else if (Op.isImm()) { 9015 // Handle optional arguments 9016 OptionalIdx[Op.getImmTy()] = I; 9017 } else { 9018 llvm_unreachable("Invalid operand type"); 9019 } 9020 SkippedVcc = false; 9021 } 9022 9023 const unsigned Opc = Inst.getOpcode(); 9024 if (Opc != AMDGPU::V_NOP_sdwa_gfx10 && Opc != AMDGPU::V_NOP_sdwa_gfx9 && 9025 Opc != AMDGPU::V_NOP_sdwa_vi) { 9026 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments 9027 switch (BasicInstType) { 9028 case SIInstrFlags::VOP1: 9029 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::clamp)) 9030 addOptionalImmOperand(Inst, Operands, OptionalIdx, 9031 AMDGPUOperand::ImmTyClampSI, 0); 9032 9033 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::omod)) 9034 addOptionalImmOperand(Inst, Operands, OptionalIdx, 9035 AMDGPUOperand::ImmTyOModSI, 0); 9036 9037 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_sel)) 9038 addOptionalImmOperand(Inst, Operands, OptionalIdx, 9039 AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD); 9040 9041 if (AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::dst_unused)) 9042 addOptionalImmOperand(Inst, Operands, OptionalIdx, 9043 AMDGPUOperand::ImmTySDWADstUnused, 9044 DstUnused::UNUSED_PRESERVE); 9045 9046 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD); 9047 break; 9048 9049 case SIInstrFlags::VOP2: 9050 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 9051 9052 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::omod)) 9053 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); 9054 9055 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWADstSel, SdwaSel::DWORD); 9056 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWADstUnused, DstUnused::UNUSED_PRESERVE); 9057 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD); 9058 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD); 9059 break; 9060 9061 case SIInstrFlags::VOPC: 9062 if (AMDGPU::hasNamedOperand(Inst.getOpcode(), AMDGPU::OpName::clamp)) 9063 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 9064 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWASrc0Sel, SdwaSel::DWORD); 9065 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySDWASrc1Sel, SdwaSel::DWORD); 9066 break; 9067 9068 default: 9069 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); 9070 } 9071 } 9072 9073 // special case v_mac_{f16, f32}: 9074 // it has src2 register operand that is tied to dst operand 9075 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 9076 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 9077 auto it = Inst.begin(); 9078 std::advance( 9079 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); 9080 Inst.insert(it, Inst.getOperand(0)); // src2 = dst 9081 } 9082 } 9083 9084 /// Force static initialization. 9085 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() { 9086 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheR600Target()); 9087 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); 9088 } 9089 9090 #define GET_REGISTER_MATCHER 9091 #define GET_MATCHER_IMPLEMENTATION 9092 #define GET_MNEMONIC_SPELL_CHECKER 9093 #define GET_MNEMONIC_CHECKER 9094 #include "AMDGPUGenAsmMatcher.inc" 9095 9096 ParseStatus AMDGPUAsmParser::parseCustomOperand(OperandVector &Operands, 9097 unsigned MCK) { 9098 switch (MCK) { 9099 case MCK_addr64: 9100 return parseTokenOp("addr64", Operands); 9101 case MCK_done: 9102 return parseTokenOp("done", Operands); 9103 case MCK_idxen: 9104 return parseTokenOp("idxen", Operands); 9105 case MCK_lds: 9106 return parseTokenOp("lds", Operands); 9107 case MCK_offen: 9108 return parseTokenOp("offen", Operands); 9109 case MCK_off: 9110 return parseTokenOp("off", Operands); 9111 case MCK_row_95_en: 9112 return parseTokenOp("row_en", Operands); 9113 case MCK_gds: 9114 return parseNamedBit("gds", Operands, AMDGPUOperand::ImmTyGDS); 9115 case MCK_tfe: 9116 return parseNamedBit("tfe", Operands, AMDGPUOperand::ImmTyTFE); 9117 } 9118 return tryCustomParseOperand(Operands, MCK); 9119 } 9120 9121 // This function should be defined after auto-generated include so that we have 9122 // MatchClassKind enum defined 9123 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 9124 unsigned Kind) { 9125 // Tokens like "glc" would be parsed as immediate operands in ParseOperand(). 9126 // But MatchInstructionImpl() expects to meet token and fails to validate 9127 // operand. This method checks if we are given immediate operand but expect to 9128 // get corresponding token. 9129 AMDGPUOperand &Operand = (AMDGPUOperand&)Op; 9130 switch (Kind) { 9131 case MCK_addr64: 9132 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand; 9133 case MCK_gds: 9134 return Operand.isGDS() ? Match_Success : Match_InvalidOperand; 9135 case MCK_lds: 9136 return Operand.isLDS() ? Match_Success : Match_InvalidOperand; 9137 case MCK_idxen: 9138 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand; 9139 case MCK_offen: 9140 return Operand.isOffen() ? Match_Success : Match_InvalidOperand; 9141 case MCK_tfe: 9142 return Operand.isTFE() ? Match_Success : Match_InvalidOperand; 9143 case MCK_SSrcB32: 9144 // When operands have expression values, they will return true for isToken, 9145 // because it is not possible to distinguish between a token and an 9146 // expression at parse time. MatchInstructionImpl() will always try to 9147 // match an operand as a token, when isToken returns true, and when the 9148 // name of the expression is not a valid token, the match will fail, 9149 // so we need to handle it here. 9150 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand; 9151 case MCK_SSrcF32: 9152 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand; 9153 case MCK_SOPPBrTarget: 9154 return Operand.isSOPPBrTarget() ? Match_Success : Match_InvalidOperand; 9155 case MCK_VReg32OrOff: 9156 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand; 9157 case MCK_InterpSlot: 9158 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand; 9159 case MCK_InterpAttr: 9160 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand; 9161 case MCK_InterpAttrChan: 9162 return Operand.isInterpAttrChan() ? Match_Success : Match_InvalidOperand; 9163 case MCK_SReg_64: 9164 case MCK_SReg_64_XEXEC: 9165 // Null is defined as a 32-bit register but 9166 // it should also be enabled with 64-bit operands. 9167 // The following code enables it for SReg_64 operands 9168 // used as source and destination. Remaining source 9169 // operands are handled in isInlinableImm. 9170 return Operand.isNull() ? Match_Success : Match_InvalidOperand; 9171 default: 9172 return Match_InvalidOperand; 9173 } 9174 } 9175 9176 //===----------------------------------------------------------------------===// 9177 // endpgm 9178 //===----------------------------------------------------------------------===// 9179 9180 ParseStatus AMDGPUAsmParser::parseEndpgm(OperandVector &Operands) { 9181 SMLoc S = getLoc(); 9182 int64_t Imm = 0; 9183 9184 if (!parseExpr(Imm)) { 9185 // The operand is optional, if not present default to 0 9186 Imm = 0; 9187 } 9188 9189 if (!isUInt<16>(Imm)) 9190 return Error(S, "expected a 16-bit value"); 9191 9192 Operands.push_back( 9193 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm)); 9194 return ParseStatus::Success; 9195 } 9196 9197 bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); } 9198 9199 //===----------------------------------------------------------------------===// 9200 // LDSDIR 9201 //===----------------------------------------------------------------------===// 9202 9203 bool AMDGPUOperand::isWaitVDST() const { 9204 return isImmTy(ImmTyWaitVDST) && isUInt<4>(getImm()); 9205 } 9206 9207 bool AMDGPUOperand::isWaitVAVDst() const { 9208 return isImmTy(ImmTyWaitVAVDst) && isUInt<4>(getImm()); 9209 } 9210 9211 bool AMDGPUOperand::isWaitVMVSrc() const { 9212 return isImmTy(ImmTyWaitVMVSrc) && isUInt<1>(getImm()); 9213 } 9214 9215 //===----------------------------------------------------------------------===// 9216 // VINTERP 9217 //===----------------------------------------------------------------------===// 9218 9219 bool AMDGPUOperand::isWaitEXP() const { 9220 return isImmTy(ImmTyWaitEXP) && isUInt<3>(getImm()); 9221 } 9222 9223 //===----------------------------------------------------------------------===// 9224 // Split Barrier 9225 //===----------------------------------------------------------------------===// 9226 9227 bool AMDGPUOperand::isSplitBarrier() const { return isInlinableImm(MVT::i32); } 9228