llvm.org GIT mirror llvm / 9b4f7ea
[AMDGPU] Assembler: Custom converters for SDWA instructions. Support for _dpp and _sdwa suffixes in mnemonics. Summary: Added custom converters for SDWA instruction to support optional operands and modifiers. Support for _dpp and _sdwa suffixes that allows to force DPP or SDWA encoding for instructions. Reviewers: tstellarAMD, vpykhtin, artem.tamazov Subscribers: arsenm, kzhuravl Differential Revision: http://reviews.llvm.org/D20625 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271655 91177308-0d34-0410-b5e6-96231b3b80d8 Sam Kolton 4 years ago
3 changed file(s) with 179 addition(s) and 67 deletion(s). Raw diff Collapse all Expand all
8181 ImmTyDppRowMask,
8282 ImmTyDppBankMask,
8383 ImmTyDppBoundCtrl,
84 ImmTySdwaSel,
84 ImmTySdwaDstSel,
85 ImmTySdwaSrc0Sel,
86 ImmTySdwaSrc1Sel,
8587 ImmTySdwaDstUnused,
8688 ImmTyDMask,
8789 ImmTyUNorm,
273275 return isImmTy(ImmTyDppBoundCtrl);
274276 }
275277
276 bool isSDWASel() const {
277 return isImmTy(ImmTySdwaSel);
278 bool isSDWADstSel() const {
279 return isImmTy(ImmTySdwaDstSel);
280 }
281
282 bool isSDWASrc0Sel() const {
283 return isImmTy(ImmTySdwaSrc0Sel);
284 }
285
286 bool isSDWASrc1Sel() const {
287 return isImmTy(ImmTySdwaSrc1Sel);
278288 }
279289
280290 bool isSDWADstUnused() const {
384394 case ImmTyDppRowMask: OS << "DppRowMask"; break;
385395 case ImmTyDppBankMask: OS << "DppBankMask"; break;
386396 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
387 case ImmTySdwaSel: OS << "SdwaSel"; break;
397 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
398 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
399 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
388400 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
389401 case ImmTyDMask: OS << "DMask"; break;
390402 case ImmTyUNorm: OS << "UNorm"; break;
478490 MCAsmParser &Parser;
479491
480492 unsigned ForcedEncodingSize;
493 bool ForcedDPP;
494 bool ForcedSDWA;
481495
482496 bool isSI() const {
483497 return AMDGPU::isSI(getSTI());
530544 const MCInstrInfo &MII,
531545 const MCTargetOptions &Options)
532546 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
533 ForcedEncodingSize(0) {
547 ForcedEncodingSize(0),
548 ForcedDPP(false),
549 ForcedSDWA(false) {
534550 MCAsmParserExtension::Initialize(Parser);
535551
536552 if (getSTI().getFeatureBits().none()) {
545561 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
546562 return static_cast(TS);
547563 }
548
549 unsigned getForcedEncodingSize() const {
550 return ForcedEncodingSize;
551 }
552
553 void setForcedEncodingSize(unsigned Size) {
554 ForcedEncodingSize = Size;
555 }
556
557 bool isForcedVOP3() const {
558 return ForcedEncodingSize == 64;
559 }
564
565 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
566 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
567 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
568
569 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
570 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
571 bool isForcedDPP() const { return ForcedDPP; }
572 bool isForcedSDWA() const { return ForcedSDWA; }
560573
561574 std::unique_ptr parseRegister();
562575 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
569582 bool MatchingInlineAsm) override;
570583 bool ParseDirective(AsmToken DirectiveID) override;
571584 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
585 StringRef parseMnemonicSuffix(StringRef Name);
572586 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
573587 SMLoc NameLoc, OperandVector &Operands) override;
574588
579593 bool (*ConvertResult)(int64_t&) = 0);
580594 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands,
581595 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
582 OperandMatchResultTy parseStringWithPrefix(const char *Prefix, StringRef &Value);
596 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, StringRef &Value);
583597
584598 OperandMatchResultTy parseImm(OperandVector &Operands);
585599 OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
642656 AMDGPUOperand::Ptr defaultBoundCtrl() const;
643657 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
644658
645 OperandMatchResultTy parseSDWASel(OperandVector &Operands);
659 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
660 AMDGPUOperand::ImmTy Type);
646661 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
647 AMDGPUOperand::Ptr defaultSDWASel() const;
662 AMDGPUOperand::Ptr defaultSDWASel(AMDGPUOperand::ImmTy Type) const;
663 AMDGPUOperand::Ptr defaultSDWADstSel() const;
664 AMDGPUOperand::Ptr defaultSDWASrc0Sel() const;
665 AMDGPUOperand::Ptr defaultSDWASrc1Sel() const;
648666 AMDGPUOperand::Ptr defaultSDWADstUnused() const;
667 void cvtSdwaVop1_mod(MCInst &Inst, const OperandVector &Operands);
668 void cvtSdwaVop1_nomod(MCInst &Inst, const OperandVector &Operands);
669 void cvtSdwaVop2_mod(MCInst &Inst, const OperandVector &Operands);
670 void cvtSdwaVop2_nomod(MCInst &Inst, const OperandVector &Operands);
671 void cvtSDWA(MCInst &Inst, const OperandVector &Operands, bool HasMods,
672 bool IsVOP1);
649673 };
650674
651675 struct OptionalOperand {
9871011 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
9881012
9891013 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
990 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)))
1014 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1015 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1016 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
9911017 return Match_InvalidOperand;
9921018
9931019 if ((TSFlags & SIInstrFlags::VOP3) &&
13221348 return MatchOperand_NoMatch;
13231349 }
13241350
1351 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
1352 // Clear any forced encodings from the previous instruction.
1353 setForcedEncodingSize(0);
1354 setForcedDPP(false);
1355 setForcedSDWA(false);
1356
1357 if (Name.endswith("_e64")) {
1358 setForcedEncodingSize(64);
1359 return Name.substr(0, Name.size() - 4);
1360 } else if (Name.endswith("_e32")) {
1361 setForcedEncodingSize(32);
1362 return Name.substr(0, Name.size() - 4);
1363 } else if (Name.endswith("_dpp")) {
1364 setForcedDPP(true);
1365 return Name.substr(0, Name.size() - 4);
1366 } else if (Name.endswith("_sdwa")) {
1367 setForcedSDWA(true);
1368 return Name.substr(0, Name.size() - 5);
1369 }
1370 return Name;
1371 }
1372
13251373 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
13261374 StringRef Name,
13271375 SMLoc NameLoc, OperandVector &Operands) {
1328
1329 // Clear any forced encodings from the previous instruction.
1330 setForcedEncodingSize(0);
1331
1332 if (Name.endswith("_e64"))
1333 setForcedEncodingSize(64);
1334 else if (Name.endswith("_e32"))
1335 setForcedEncodingSize(32);
1336
13371376 // Add the instruction mnemonic
1377 Name = parseMnemonicSuffix(Name);
13381378 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
1339
1340
1341 if (Name.endswith("_e64")) { Name = Name.substr(0, Name.size() - 4); }
1342 if (Name.endswith("_e32")) { Name = Name.substr(0, Name.size() - 4); }
1343
1379
13441380 while (!getLexer().is(AsmToken::EndOfStatement)) {
13451381 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
13461382
14651501 }
14661502
14671503 AMDGPUAsmParser::OperandMatchResultTy
1468 AMDGPUAsmParser::parseStringWithPrefix(const char *Prefix, StringRef &Value) {
1504 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
14691505 if (getLexer().isNot(AsmToken::Identifier)) {
14701506 return MatchOperand_NoMatch;
14711507 }
21952231 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
21962232 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
21972233 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
2198 {"sdwa_sel", AMDGPUOperand::ImmTySdwaSel, false, nullptr},
2234 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
2235 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
2236 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
21992237 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
22002238 };
22012239
22072245 res = parseNamedBit(Op.Name, Operands, Op.Type);
22082246 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
22092247 res = parseOModOperand(Operands);
2210 } else if (Op.Type == AMDGPUOperand::ImmTySdwaSel) {
2211 res = parseSDWASel(Operands);
2248 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
2249 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
2250 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
2251 res = parseSDWASel(Operands, Op.Name, Op.Type);
22122252 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
22132253 res = parseSDWADstUnused(Operands);
22142254 } else {
24562496 }
24572497 }
24582498
2459 // ToDo: fix default values for row_mask and bank_mask
24602499 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
24612500 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
24622501 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
24672506 //===----------------------------------------------------------------------===//
24682507
24692508 AMDGPUAsmParser::OperandMatchResultTy
2470 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands) {
2509 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
2510 AMDGPUOperand::ImmTy Type) {
24712511 SMLoc S = Parser.getTok().getLoc();
24722512 StringRef Value;
24732513 AMDGPUAsmParser::OperandMatchResultTy res;
24742514
2475 res = parseStringWithPrefix("dst_sel", Value);
2476 if (res == MatchOperand_ParseFail) {
2477 return MatchOperand_ParseFail;
2478 } else if (res == MatchOperand_NoMatch) {
2479 res = parseStringWithPrefix("src0_sel", Value);
2480 if (res == MatchOperand_ParseFail) {
2481 return MatchOperand_ParseFail;
2482 } else if (res == MatchOperand_NoMatch) {
2483 res = parseStringWithPrefix("src1_sel", Value);
2484 if (res != MatchOperand_Success) {
2485 return res;
2486 }
2487 }
2515 res = parseStringWithPrefix(Prefix, Value);
2516 if (res != MatchOperand_Success) {
2517 return res;
24882518 }
24892519
24902520 int64_t Int;
25032533 return MatchOperand_ParseFail;
25042534 }
25052535
2506 Operands.push_back(AMDGPUOperand::CreateImm(Int, S,
2507 AMDGPUOperand::ImmTySdwaSel));
2536 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, Type));
25082537 return MatchOperand_Success;
25092538 }
25102539
25362565 return MatchOperand_Success;
25372566 }
25382567
2539 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWASel() const {
2540 return AMDGPUOperand::CreateImm(6, SMLoc(), AMDGPUOperand::ImmTySdwaSel);
2568 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWASel(AMDGPUOperand::ImmTy Type) const {
2569 return AMDGPUOperand::CreateImm(6, SMLoc(), Type);
2570 }
2571
2572 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWADstSel() const {
2573 return defaultSDWASel(AMDGPUOperand::ImmTySdwaDstSel);
2574 }
2575
2576 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWASrc0Sel() const {
2577 return defaultSDWASel(AMDGPUOperand::ImmTySdwaSrc0Sel);
2578 }
2579
2580 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWASrc1Sel() const {
2581 return defaultSDWASel(AMDGPUOperand::ImmTySdwaSrc1Sel);
25412582 }
25422583
25432584 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSDWADstUnused() const {
25442585 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTySdwaDstUnused);
25452586 }
25462587
2588 void AMDGPUAsmParser::cvtSdwaVop1_mod(MCInst &Inst, const OperandVector &Operands) {
2589 cvtSDWA(Inst, Operands, true, true);
2590 }
2591
2592 void AMDGPUAsmParser::cvtSdwaVop1_nomod(MCInst &Inst, const OperandVector &Operands) {
2593 cvtSDWA(Inst, Operands, false, true);
2594 }
2595
2596 void AMDGPUAsmParser::cvtSdwaVop2_mod(MCInst &Inst, const OperandVector &Operands) {
2597 cvtSDWA(Inst, Operands, true, false);
2598 }
2599
2600 void AMDGPUAsmParser::cvtSdwaVop2_nomod(MCInst &Inst, const OperandVector &Operands) {
2601 cvtSDWA(Inst, Operands, false, false);
2602 }
2603
2604 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
2605 bool HasMods, bool IsVOP1) {
2606 OptionalImmIndexMap OptionalIdx;
2607
2608 unsigned I = 1;
2609 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2610 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2611 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2612 }
2613
2614 for (unsigned E = Operands.size(); I != E; ++I) {
2615 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2616 // Add the register arguments
2617 if (!HasMods && Op.isReg()) {
2618 Op.addRegOperands(Inst, 1);
2619 } else if (HasMods && Op.isRegOrImmWithInputMods()) {
2620 Op.addRegOrImmWithInputModsOperands(Inst, 2);
2621 } else if (Op.isImm()) {
2622 // Handle optional arguments
2623 OptionalIdx[Op.getImmTy()] = I;
2624 } else {
2625 llvm_unreachable("Invalid operand type");
2626 }
2627 }
2628
2629 if (HasMods) {
2630 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
2631 }
2632 if (Inst.getOpcode() == AMDGPU::V_NOP_sdwa) {
2633 // V_NOP_sdwa has no optional sdwa arguments
2634 return;
2635 }
2636 if (IsVOP1) {
2637 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2638 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2639 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2640 } else { // VOP2
2641 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2642 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2643 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2644 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
2645 }
2646 }
25472647
25482648 /// Force static initialization.
25492649 extern "C" void LLVMInitializeAMDGPUAsmParser() {
488488 let ParserMethod = !if(Optional, "parseOptionalOperand", "parse"#CName);
489489 let RenderMethod = "addImmOperands";
490490 let IsOptional = Optional;
491 let DefaultMethod = "default"#CName;
492 }
493
494 def sdwa_sel : NamedMatchClass<"SDWASel">;
491 let DefaultMethod = !if(Optional, "default"#CName, ?);
492 }
495493
496494 class NamedOperandBit : Operand {
497495 let PrintMethod = "print"#Name;
546544 def bank_mask : NamedOperandU32<"BankMask", NamedMatchClass<"BankMask">>;
547545 def bound_ctrl : NamedOperandBit<"BoundCtrl", NamedMatchClass<"BoundCtrl">>;
548546
549 def dst_sel : NamedOperandU32<"SDWADstSel", sdwa_sel>;
550 def src0_sel : NamedOperandU32<"SDWASrc0Sel", sdwa_sel>;
551 def src1_sel : NamedOperandU32<"SDWASrc1Sel", sdwa_sel>;
547 def dst_sel : NamedOperandU32<"SDWADstSel", NamedMatchClass<"SDWADstSel">>;
548 def src0_sel : NamedOperandU32<"SDWASrc0Sel", NamedMatchClass<"SDWASrc0Sel">>;
549 def src1_sel : NamedOperandU32<"SDWASrc1Sel", NamedMatchClass<"SDWASrc1Sel">>;
552550 def dst_unused : NamedOperandU32<"SDWADstUnused", NamedMatchClass<"SDWADstUnused">>;
553551
554552 def hwreg : NamedOperandU16<"Hwreg", NamedMatchClass<"Hwreg", 0>>;
13361334 " $src1_modifiers,"));
13371335 string args = !if(!eq(HasModifiers, 0),
13381336 getAsm32<0, NumSrcArgs, DstVT>.ret,
1339 ", "#src0#src1#", $clamp");
1337 ", "#src0#src1#"$clamp");
13401338 string sdwa = !if(!eq(NumSrcArgs, 0),
13411339 "",
13421340 !if(!eq(NumSrcArgs, 1),
16781676 !if(!eq(p.NumSrcArgs, 1), 0,
16791677 !if(p.HasModifiers, ?, 0)));
16801678 bits<3> dst_sel = !if(p.HasDst, ?, 6);
1681 bits<2> dst_unused = !if(p.HasDst, ?, 0);
1679 bits<2> dst_unused = !if(p.HasDst, ?, 2);
16821680 bits<1> clamp = !if(p.HasModifiers, ?, 0);
16831681 }
16841682
16861684 VOP1_SDWAe ,
16871685 VOP_SDWA ,
16881686 SDWADisableFields

{

1687 let AsmMatchConverter = !if(!eq(p.HasModifiers,1), "cvtSdwaVop1_mod", "cvtSdwaVop1_nomod");
16891688 let AssemblerPredicates = !if(p.HasExt, [isVI], [DisableInst]);
16901689 let DecoderNamespace = "SDWA";
16911690 let DisableDecoder = DisableVIDecoder;
17591758 VOP2_SDWAe ,
17601759 VOP_SDWA ,
17611760 SDWADisableFields

{

1761 let AsmMatchConverter = !if(!eq(p.HasModifiers,1), "cvtSdwaVop2_mod", "cvtSdwaVop2_nomod");
17621762 let AssemblerPredicates = !if(p.HasExt, [isVI], [DisableInst]);
17631763 let DecoderNamespace = "SDWA";
17641764 let DisableDecoder = DisableVIDecoder;
3737 // NOSICI: error:
3838 // VI: v_min_u32_sdwa v1, v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD ; encoding: [0xf9,0x02,0x02,0x1c,0x01,0x06,0x00,0x06]
3939 v_min_u32 v1, v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
40
41 // NOSICI: error:
42 // VI: v_mov_b32_sdwa v0, v0 dst_sel:BYTE_0 dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x02,0x00,0x7e,0x00,0x10,0x06,0x06]
43 v_mov_b32 v0, v0 dst_sel:BYTE_0 src0_sel:DWORD
44
45 // NOSICI: error:
46 // VI: v_mov_b32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x02,0x00,0x7e,0x00,0x16,0x06,0x06]
47 v_mov_b32 v0, v0 src0_sel:DWORD
48
49 // NOSICI: error:
50 // VI: v_mov_b32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PRESERVE src0_sel:DWORD ; encoding: [0xf9,0x02,0x00,0x7e,0x00,0x16,0x06,0x06]
51 v_mov_b32_sdwa v0, v0