1//===-- VOPInstructions.td - Vector Instruction Definitions ---------------===// 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// dummies for outer let 10class LetDummies { 11 bit TRANS; 12 bit ReadsModeReg; 13 bit mayRaiseFPException; 14 bit isCommutable; 15 bit isConvertibleToThreeAddress; 16 bit isMoveImm; 17 bit isReMaterializable; 18 bit isAsCheapAsAMove; 19 bit VOPAsmPrefer32Bit; 20 bit FPDPRounding; 21 Predicate SubtargetPredicate; 22 string Constraints; 23 string DisableEncoding; 24 list<SchedReadWrite> SchedRW; 25 list<Register> Uses; 26 list<Register> Defs; 27 list<Predicate> OtherPredicates; 28 Predicate AssemblerPredicate; 29 string DecoderNamespace; 30} 31 32//===----------------------------------------------------------------------===// 33// VOP Subtarget info 34//===----------------------------------------------------------------------===// 35 36class GFXGen<Predicate pred, string dn, string suffix, int sub> { 37 Predicate AssemblerPredicate = pred; 38 string DecoderNamespace = dn; 39 string Suffix = suffix; 40 int Subtarget = sub; 41} 42 43def GFX12Gen : GFXGen<isGFX12Only, "GFX12", "_gfx12", SIEncodingFamily.GFX12>; 44def GFX11Gen : GFXGen<isGFX11Only, "GFX11", "_gfx11", SIEncodingFamily.GFX11>; 45 46//===----------------------------------------------------------------------===// 47 48class VOP <string opName> { 49 string OpName = opName; 50} 51 52// First 13 insts from VOPDY are also VOPDX. DOT2ACC_F32_BF16 is omitted 53defvar VOPDX_Max_Index = 12; 54 55class VOPD_Component<bits<5> OpIn, string vOPDName> { 56 Instruction BaseVOP = !cast<Instruction>(NAME); 57 string VOPDName = "v_dual_" # !substr(vOPDName, 2); 58 bits<5> VOPDOp = OpIn; 59 bit CanBeVOPDX = !le(VOPDOp, VOPDX_Max_Index); 60} 61 62class VOPAnyCommon <dag outs, dag ins, string asm, list<dag> pattern> : 63 InstSI <outs, ins, asm, pattern> { 64 65 let mayLoad = 0; 66 let mayStore = 0; 67 let hasSideEffects = 0; 68 let UseNamedOperandTable = 1; 69 let VALU = 1; 70 let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]); 71} 72 73class VOP_Pseudo <string opName, string suffix, VOPProfile P, dag outs, dag ins, 74 string asm, list<dag> pattern> : 75 InstSI <outs, ins, asm, pattern>, 76 VOP <opName>, 77 SIMCInstr <opName#suffix, SIEncodingFamily.NONE> { 78 let isPseudo = 1; 79 let isCodeGenOnly = 1; 80 let UseNamedOperandTable = 1; 81 82 string Mnemonic = opName; 83 Instruction Opcode = !cast<Instruction>(NAME); 84 bit IsTrue16 = P.IsTrue16; 85 VOPProfile Pfl = P; 86 87 string AsmOperands; 88} 89 90class VOP3Common <dag outs, dag ins, string asm = "", 91 list<dag> pattern = [], bit HasMods = 0> : 92 VOPAnyCommon <outs, ins, asm, pattern> { 93 94 // Using complex patterns gives VOP3 patterns a very high complexity rating, 95 // but standalone patterns are almost always preferred, so we need to adjust the 96 // priority lower. The goal is to use a high number to reduce complexity to 97 // zero (or less than zero). 98 let AddedComplexity = -1000; 99 100 let VOP3 = 1; 101 102 let AsmVariantName = AMDGPUAsmVariants.VOP3; 103 let AsmMatchConverter = !if(HasMods, "cvtVOP3", ""); 104 105 let isCodeGenOnly = 0; 106 107 int Size = 8; 108 109 // Because SGPRs may be allowed if there are multiple operands, we 110 // need a post-isel hook to insert copies in order to avoid 111 // violating constant bus requirements. 112 let hasPostISelHook = 1; 113} 114 115class VOP3_Pseudo <string opName, VOPProfile P, list<dag> pattern = [], 116 bit isVOP3P = 0, bit isVop3OpSel = 0> : 117 VOP_Pseudo <opName, "_e64", P, P.Outs64, 118 !if(isVop3OpSel, 119 P.InsVOP3OpSel, 120 !if(!and(isVOP3P, P.IsPacked), P.InsVOP3P, P.Ins64)), 121 "", pattern> { 122 123 let VOP3_OPSEL = isVop3OpSel; 124 let IsPacked = P.IsPacked; 125 let IsMAI = P.IsMAI; 126 let IsWMMA = P.IsWMMA; 127 let IsSWMMAC = P.IsSWMMAC; 128 129 let AsmOperands = !if(isVop3OpSel, 130 P.AsmVOP3OpSel, 131 !if(!and(isVOP3P, P.IsPacked), P.AsmVOP3P, P.Asm64)); 132 133 let Size = 8; 134 let mayLoad = 0; 135 let mayStore = 0; 136 let hasSideEffects = 0; 137 138 // Because SGPRs may be allowed if there are multiple operands, we 139 // need a post-isel hook to insert copies in order to avoid 140 // violating constant bus requirements. 141 let hasPostISelHook = 1; 142 143 // Using complex patterns gives VOP3 patterns a very high complexity rating, 144 // but standalone patterns are almost always preferred, so we need to adjust the 145 // priority lower. The goal is to use a high number to reduce complexity to 146 // zero (or less than zero). 147 let AddedComplexity = -1000; 148 149 let VOP3 = 1; 150 let VALU = 1; 151 let FPClamp = P.HasFPClamp; 152 let IntClamp = P.HasIntClamp; 153 let ClampLo = P.HasClampLo; 154 let ClampHi = P.HasClampHi; 155 156 let ReadsModeReg = !or(P.DstVT.isFP, P.Src0VT.isFP); 157 158 let mayRaiseFPException = ReadsModeReg; 159 let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]); 160 161 let AsmVariantName = AMDGPUAsmVariants.VOP3; 162 let AsmMatchConverter = 163 !if(isVOP3P, 164 "cvtVOP3P", 165 !if(!or(P.HasModifiers, P.HasOMod, P.HasIntClamp), 166 "cvtVOP3", 167 "")); 168} 169 170class VOP3P_Pseudo <string opName, VOPProfile P, list<dag> pattern = []> : 171 VOP3_Pseudo<opName, P, pattern, 1> { 172 let VOP3P = 1; 173 let IsDOT = P.IsDOT; 174} 175 176class VOP_Real<VOP_Pseudo ps> { 177 Instruction Opcode = !cast<Instruction>(NAME); 178 bit IsSingle = ps.Pfl.IsSingle; 179} 180 181class VOP3_Real <VOP_Pseudo ps, int EncodingFamily, string asm_name = ps.Mnemonic> : 182 VOP_Real <ps>, 183 InstSI <ps.OutOperandList, ps.InOperandList, asm_name # ps.AsmOperands, []>, 184 SIMCInstr <ps.PseudoInstr, EncodingFamily> { 185 186 let VALU = 1; 187 let VOP3 = 1; 188 let isPseudo = 0; 189 let isCodeGenOnly = 0; 190 let UseNamedOperandTable = 1; 191 192 // copy relevant pseudo op flags 193 let SubtargetPredicate = ps.SubtargetPredicate; 194 let OtherPredicates = ps.OtherPredicates; 195 let AsmMatchConverter = ps.AsmMatchConverter; 196 let AsmVariantName = ps.AsmVariantName; 197 let Constraints = ps.Constraints; 198 let DisableEncoding = ps.DisableEncoding; 199 let TSFlags = ps.TSFlags; 200 let UseNamedOperandTable = ps.UseNamedOperandTable; 201 let Uses = ps.Uses; 202 let Defs = ps.Defs; 203 let SchedRW = ps.SchedRW; 204 let mayLoad = ps.mayLoad; 205 let mayStore = ps.mayStore; 206 let TRANS = ps.TRANS; 207 208 VOPProfile Pfl = ps.Pfl; 209} 210 211class VOP3_Real_Gen <VOP_Pseudo ps, GFXGen Gen, string asm_name = ps.Mnemonic> : 212 VOP3_Real <ps, Gen.Subtarget, asm_name> { 213 let AssemblerPredicate = Gen.AssemblerPredicate; 214 let OtherPredicates = !if(ps.Pfl.IsRealTrue16, [UseRealTrue16Insts], []); 215 let DecoderNamespace = Gen.DecoderNamespace# 216 !if(ps.Pfl.IsRealTrue16, "", "_FAKE16"); 217} 218 219// XXX - Is there any reason to distinguish this from regular VOP3 220// here? 221class VOP3P_Real<VOP_Pseudo ps, int EncodingFamily, string asm_name = ps.Mnemonic> : 222 VOP3_Real<ps, EncodingFamily, asm_name> { 223 224 // The v_wmma pseudos have extra constraints that we do not want to impose on the real instruction. 225 let Constraints = !if(!eq(!substr(ps.Mnemonic,0,6), "v_wmma"), "", ps.Constraints); 226} 227 228class VOP3P_Real_Gen<VOP_Pseudo ps, GFXGen Gen, string asm_name = ps.Mnemonic> : 229 VOP3P_Real<ps, Gen.Subtarget, asm_name> { 230 let AssemblerPredicate = Gen.AssemblerPredicate; 231 let DecoderNamespace = Gen.DecoderNamespace; 232} 233 234class VOP3a<VOPProfile P> : Enc64 { 235 bits<4> src0_modifiers; 236 bits<9> src0; 237 bits<3> src1_modifiers; 238 bits<9> src1; 239 bits<3> src2_modifiers; 240 bits<9> src2; 241 bits<1> clamp; 242 bits<2> omod; 243 244 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); 245 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); 246 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); 247 248 let Inst{31-26} = 0x34; //encoding 249 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 250 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 251 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 252 let Inst{60-59} = !if(P.HasOMod, omod, 0); 253 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 254 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); 255 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); 256} 257 258class VOP3a_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3a<p> { 259 let Inst{11} = !if(p.HasClamp, clamp{0}, 0); 260 let Inst{25-17} = op; 261} 262 263class VOP3a_gfx10<bits<10> op, VOPProfile p> : VOP3a<p> { 264 let Inst{15} = !if(p.HasClamp, clamp{0}, 0); 265 let Inst{25-16} = op; 266 let Inst{31-26} = 0x35; 267} 268 269class VOP3a_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3a_gfx10<op, p>; 270 271class VOP3a_vi <bits<10> op, VOPProfile P> : VOP3a<P> { 272 let Inst{25-16} = op; 273 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 274} 275 276class VOP3e_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3a_gfx6_gfx7<op, p> { 277 bits<8> vdst; 278 let Inst{7-0} = !if(p.EmitDst, vdst{7-0}, 0); 279} 280 281class VOP3e_gfx10<bits<10> op, VOPProfile p> : VOP3a_gfx10<op, p> { 282 bits<8> vdst; 283 let Inst{7-0} = !if(p.EmitDst, vdst{7-0}, 0); 284} 285 286class VOP3e_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p>; 287 288class VOP3e_vi <bits<10> op, VOPProfile P> : VOP3a_vi <op, P> { 289 bits<8> vdst; 290 let Inst{7-0} = !if(P.EmitDst, vdst{7-0}, 0); 291} 292 293class VOP3OpSel_gfx9 <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> { 294 let Inst{11} = !if(P.HasSrc0, src0_modifiers{2}, 0); 295 let Inst{12} = !if(P.HasSrc1, src1_modifiers{2}, 0); 296 let Inst{13} = !if(P.HasSrc2, src2_modifiers{2}, 0); 297 let Inst{14} = !if(P.HasDst, src0_modifiers{3}, 0); 298} 299 300class VOP3OpSel_gfx10<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p> { 301 let Inst{11} = !if(p.HasSrc0, src0_modifiers{2}, 0); 302 let Inst{12} = !if(p.HasSrc1, src1_modifiers{2}, 0); 303 let Inst{13} = !if(p.HasSrc2, src2_modifiers{2}, 0); 304 let Inst{14} = !if(p.HasDst, src0_modifiers{3}, 0); 305} 306 307class VOP3OpSel_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3OpSel_gfx10<op, p>; 308 309class VOP3FP8OpSel_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p> { 310 let Inst{11} = !if(p.HasSrc0, src0_modifiers{2}, 0); 311 let Inst{12} = !if(p.HasSrc0, src0_modifiers{3}, 0); 312} 313 314class VOP3DotOpSel_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3OpSel_gfx11_gfx12<op, p>{ 315 let Inst{11} = ?; 316 let Inst{12} = ?; 317} 318 319// NB: For V_INTERP* opcodes, src0 is encoded as src1 and vice versa 320class VOP3Interp_vi <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> { 321 bits<2> attrchan; 322 bits<6> attr; 323 bits<1> high; 324 325 let Inst{8} = 0; // No modifiers for src0 326 let Inst{61} = 0; 327 328 let Inst{9} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); 329 let Inst{62} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 330 331 let Inst{37-32} = attr; 332 let Inst{39-38} = attrchan; 333 let Inst{40} = !if(P.HasHigh, high, 0); 334 335 let Inst{49-41} = src0; 336} 337 338class VOP3Interp_gfx10<bits<10> op, VOPProfile p> : VOP3e_gfx10<op, p> { 339 bits<6> attr; 340 bits<2> attrchan; 341 bits<1> high; 342 343 let Inst{8} = 0; 344 let Inst{9} = !if(p.HasSrc0Mods, src0_modifiers{1}, 0); 345 let Inst{37-32} = attr; 346 let Inst{39-38} = attrchan; 347 let Inst{40} = !if(p.HasHigh, high, 0); 348 let Inst{49-41} = src0; 349 let Inst{61} = 0; 350 let Inst{62} = !if(p.HasSrc0Mods, src0_modifiers{0}, 0); 351} 352 353class VOP3Interp_gfx11<bits<10> op, VOPProfile p> : VOP3Interp_gfx10<op, p>; 354 355class VOP3be <VOPProfile P> : Enc64 { 356 bits<8> vdst; 357 bits<2> src0_modifiers; 358 bits<9> src0; 359 bits<2> src1_modifiers; 360 bits<9> src1; 361 bits<2> src2_modifiers; 362 bits<9> src2; 363 bits<7> sdst; 364 bits<2> omod; 365 366 let Inst{7-0} = vdst; 367 let Inst{14-8} = sdst; 368 let Inst{31-26} = 0x34; //encoding 369 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 370 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 371 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 372 let Inst{60-59} = !if(P.HasOMod, omod, 0); 373 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 374 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); 375 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); 376} 377 378class VOP3Pe <bits<7> op, VOPProfile P> : Enc64 { 379 bits<8> vdst; 380 bits<4> src0_modifiers; 381 bits<9> src0; 382 bits<4> src1_modifiers; 383 bits<9> src1; 384 bits<4> src2_modifiers; 385 bits<9> src2; 386 bits<1> clamp; 387 bits<2> index_key_8bit; 388 bits<1> index_key_16bit; 389 390 let Inst{7-0} = vdst; 391 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // neg_hi src0 392 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // neg_hi src1 393 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); // neg_hi src2 394 395 let Inst{11} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{2}, 0); // op_sel(0) 396 let Inst{12} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{2}, 0); // op_sel(1) 397 let Inst{13} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{2}, 0); // op_sel(2) 398 399 let Inst{14} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(2) 400 401 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 402 403 let Inst{22-16} = op; 404 let Inst{31-23} = 0x1a7; //encoding 405 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 406 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 407 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 408 let Inst{59} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(0) 409 let Inst{60} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(1) 410 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // neg (lo) 411 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // neg (lo) 412 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); // neg (lo) 413} 414 415class VOP3Pe_MAI <bits<7> op, VOPProfile P, bit acc_cd = 0> : Enc64 { 416 bits<8> vdst; 417 bits<10> src0; 418 bits<10> src1; 419 bits<9> src2; 420 bits<3> blgp; 421 bits<3> cbsz; 422 bits<4> abid; 423 424 let Inst{7-0} = vdst; 425 426 let Inst{10-8} = !if(P.HasSrc1, cbsz, 0); 427 let Inst{14-11} = !if(P.HasSrc1, abid, 0); 428 429 let Inst{15} = acc_cd; 430 431 let Inst{22-16} = op; 432 let Inst{31-23} = 0x1a7; //encoding 433 let Inst{40-32} = !if(P.HasSrc0, src0{8-0}, 0); 434 let Inst{49-41} = !if(P.HasSrc1, src1{8-0}, 0); 435 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 436 437 let Inst{59} = !if(P.HasSrc0, src0{9}, 0); // acc(0) 438 let Inst{60} = !if(P.HasSrc1, src1{9}, 0); // acc(1) 439 440 let Inst{63-61} = !if(P.HasSrc1, blgp, 0); 441} 442 443class VOP3Pe_SMFMAC <bits<7> op> : Enc64 { 444 bits<10> vdst; // VGPR or AGPR, but not SGPR. vdst{8} is not encoded in the instruction. 445 bits<10> src0; 446 bits<10> src1; 447 bits<9> idx; 448 bits<3> blgp; 449 bits<3> cbsz; 450 bits<4> abid; 451 452 let blgp = 0; 453 454 let Inst{7-0} = vdst{7-0}; 455 456 let Inst{10-8} = cbsz; 457 let Inst{14-11} = abid; 458 459 let Inst{15} = vdst{9}; // acc(vdst) 460 461 let Inst{22-16} = op; 462 let Inst{31-23} = 0x1a7; // encoding 463 let Inst{40-32} = src0{8-0}; 464 let Inst{49-41} = src1{8-0}; 465 let Inst{58-50} = idx; 466 467 let Inst{59} = src0{9}; // acc(0) 468 let Inst{60} = src1{9}; // acc(1) 469 470 let Inst{63-61} = blgp; 471} 472 473class VOP3Pe_gfx10 <bits<7> op, VOPProfile P> : VOP3Pe<op, P> { 474 let Inst{31-23} = 0x198; //encoding 475} 476 477class VOP3Pe_gfx11_gfx12<bits<7> op, VOPProfile P> : VOP3Pe_gfx10<op, P>; 478 479class VOP3be_gfx6_gfx7<bits<9> op, VOPProfile p> : VOP3be<p> { 480 let Inst{25-17} = op; 481} 482 483class VOP3be_gfx10<bits<10> op, VOPProfile p> : VOP3be<p> { 484 bits<1> clamp; 485 let Inst{15} = !if(p.HasClamp, clamp{0}, 0); 486 let Inst{25-16} = op; 487 let Inst{31-26} = 0x35; 488} 489 490class VOP3be_gfx11_gfx12<bits<10> op, VOPProfile p> : VOP3be_gfx10<op, p>; 491 492class VOP3be_vi <bits<10> op, VOPProfile P> : VOP3be<P> { 493 bits<1> clamp; 494 let Inst{25-16} = op; 495 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 496} 497 498def SDWA { 499 // sdwa_sel 500 int BYTE_0 = 0; 501 int BYTE_1 = 1; 502 int BYTE_2 = 2; 503 int BYTE_3 = 3; 504 int WORD_0 = 4; 505 int WORD_1 = 5; 506 int DWORD = 6; 507 508 // dst_unused 509 int UNUSED_PAD = 0; 510 int UNUSED_SEXT = 1; 511 int UNUSED_PRESERVE = 2; 512} 513 514class VOP_SDWAe<VOPProfile P> : Enc64 { 515 bits<8> src0; 516 bits<3> src0_sel; 517 bits<2> src0_modifiers; // float: {abs,neg}, int {sext} 518 bits<3> src1_sel; 519 bits<2> src1_modifiers; 520 bits<3> dst_sel; 521 bits<2> dst_unused; 522 bits<1> clamp; 523 524 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 525 let Inst{42-40} = !if(P.EmitDstSel, dst_sel{2-0}, ?); 526 let Inst{44-43} = !if(P.EmitDstSel, dst_unused{1-0}, ?); 527 let Inst{45} = !if(P.HasSDWAClamp, clamp{0}, 0); 528 let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0); 529 let Inst{51} = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0); 530 let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0); 531 let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0); 532 let Inst{59} = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0); 533 let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0); 534} 535 536// GFX9 adds two features to SDWA: 537// 1. Add 3 fields to the SDWA microcode word: S0, S1 and OMOD. 538// a. S0 and S1 indicate that source 0 and 1 respectively are SGPRs rather 539// than VGPRs (at most 1 can be an SGPR); 540// b. OMOD is the standard output modifier (result *2, *4, /2) 541// 2. Add a new version of the SDWA microcode word for VOPC: SDWAB. This 542// replaces OMOD and the dest fields with SD and SDST (SGPR destination) 543// field. 544// a. When SD=1, the SDST is used as the destination for the compare result; 545// b. When SD=0, VCC is used. 546// 547// In GFX9, V_MAC_F16, V_MAC_F32 opcodes cannot be used with SDWA 548 549// gfx9 SDWA basic encoding 550class VOP_SDWA9e<VOPProfile P> : Enc64 { 551 bits<9> src0; // {src0_sgpr{0}, src0{7-0}} 552 bits<3> src0_sel; 553 bits<2> src0_modifiers; // float: {abs,neg}, int {sext} 554 bits<3> src1_sel; 555 bits<2> src1_modifiers; 556 bits<1> src1_sgpr; 557 558 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 559 let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0); 560 let Inst{51} = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0); 561 let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0); 562 let Inst{55} = !if(P.HasSrc0, src0{8}, 0); 563 let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0); 564 let Inst{59} = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0); 565 let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0); 566 let Inst{63} = 0; // src1_sgpr - should be specified in subclass 567} 568 569// gfx9 SDWA-A 570class VOP_SDWA9Ae<VOPProfile P> : VOP_SDWA9e<P> { 571 bits<3> dst_sel; 572 bits<2> dst_unused; 573 bits<1> clamp; 574 bits<2> omod; 575 576 let Inst{42-40} = !if(P.EmitDstSel, dst_sel{2-0}, ?); 577 let Inst{44-43} = !if(P.EmitDstSel, dst_unused{1-0}, ?); 578 let Inst{45} = !if(P.HasSDWAClamp, clamp{0}, 0); 579 let Inst{47-46} = !if(P.HasSDWAOMod, omod{1-0}, 0); 580} 581 582// gfx9 SDWA-B 583class VOP_SDWA9Be<VOPProfile P> : VOP_SDWA9e<P> { 584 bits<8> sdst; // {vcc_sdst{0}, sdst{6-0}} 585 586 let Inst{46-40} = !if(P.EmitDst, sdst{6-0}, ?); 587 let Inst{47} = !if(P.EmitDst, sdst{7}, 0); 588} 589 590class VOP_SDWA_Pseudo <string opName, VOPProfile P, list<dag> pattern=[]> : 591 InstSI <P.OutsSDWA, P.InsSDWA, "", pattern>, 592 VOP <opName>, 593 SIMCInstr <opName#"_sdwa", SIEncodingFamily.NONE> { 594 595 let isPseudo = 1; 596 let isCodeGenOnly = 1; 597 let UseNamedOperandTable = 1; 598 599 string Mnemonic = opName; 600 string AsmOperands = P.AsmSDWA; 601 string AsmOperands9 = P.AsmSDWA9; 602 603 let Size = 8; 604 let mayLoad = 0; 605 let mayStore = 0; 606 let hasSideEffects = 0; 607 608 let VALU = 1; 609 let SDWA = 1; 610 611 let ReadsModeReg = !or(P.DstVT.isFP, P.Src0VT.isFP); 612 613 let mayRaiseFPException = ReadsModeReg; 614 let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]); 615 616 let SubtargetPredicate = HasSDWA; 617 let AssemblerPredicate = HasSDWA; 618 let AsmVariantName = !if(P.HasExtSDWA, AMDGPUAsmVariants.SDWA, 619 AMDGPUAsmVariants.Disable); 620 let DecoderNamespace = "SDWA"; 621 622 VOPProfile Pfl = P; 623} 624 625class VOP_SDWA_Real <VOP_SDWA_Pseudo ps> : 626 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>, 627 SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA> { 628 629 let VALU = 1; 630 let SDWA = 1; 631 let isPseudo = 0; 632 let isCodeGenOnly = 0; 633 634 let Defs = ps.Defs; 635 let Uses = ps.Uses; 636 let hasSideEffects = ps.hasSideEffects; 637 638 let Constraints = ps.Constraints; 639 let DisableEncoding = ps.DisableEncoding; 640 641 // Copy relevant pseudo op flags 642 let SubtargetPredicate = ps.SubtargetPredicate; 643 let AssemblerPredicate = ps.AssemblerPredicate; 644 let AsmMatchConverter = ps.AsmMatchConverter; 645 let AsmVariantName = ps.AsmVariantName; 646 let UseNamedOperandTable = ps.UseNamedOperandTable; 647 let DecoderNamespace = ps.DecoderNamespace; 648 let Constraints = ps.Constraints; 649 let DisableEncoding = ps.DisableEncoding; 650 let TSFlags = ps.TSFlags; 651 let SchedRW = ps.SchedRW; 652 let mayLoad = ps.mayLoad; 653 let mayStore = ps.mayStore; 654 let TRANS = ps.TRANS; 655} 656 657class Base_VOP_SDWA9_Real <VOP_SDWA_Pseudo ps> : 658 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands9, []> { 659 660 let VALU = 1; 661 let SDWA = 1; 662 let isPseudo = 0; 663 let isCodeGenOnly = 0; 664 665 let Defs = ps.Defs; 666 let Uses = ps.Uses; 667 let hasSideEffects = ps.hasSideEffects; 668 669 let Constraints = ps.Constraints; 670 let DisableEncoding = ps.DisableEncoding; 671 672 let SubtargetPredicate = HasSDWA9; 673 let AssemblerPredicate = HasSDWA9; 674 let AsmVariantName = !if(ps.Pfl.HasExtSDWA9, AMDGPUAsmVariants.SDWA9, 675 AMDGPUAsmVariants.Disable); 676 let DecoderNamespace = "SDWA9"; 677 678 // Copy relevant pseudo op flags 679 let AsmMatchConverter = ps.AsmMatchConverter; 680 let UseNamedOperandTable = ps.UseNamedOperandTable; 681 let Constraints = ps.Constraints; 682 let DisableEncoding = ps.DisableEncoding; 683 let TSFlags = ps.TSFlags; 684 let SchedRW = ps.SchedRW; 685 let mayLoad = ps.mayLoad; 686 let mayStore = ps.mayStore; 687 let TRANS = ps.TRANS; 688} 689 690class VOP_SDWA9_Real <VOP_SDWA_Pseudo ps> : 691 Base_VOP_SDWA9_Real <ps >, 692 SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA9>; 693 694class Base_VOP_SDWA10_Real<VOP_SDWA_Pseudo ps> : Base_VOP_SDWA9_Real<ps> { 695 let SubtargetPredicate = HasSDWA10; 696 let AssemblerPredicate = HasSDWA10; 697 let DecoderNamespace = "SDWA10"; 698} 699 700class VOP_SDWA10_Real<VOP_SDWA_Pseudo ps> : 701 Base_VOP_SDWA10_Real<ps>, SIMCInstr<ps.PseudoInstr, SIEncodingFamily.SDWA10>; 702 703class VOP_DPPe<VOPProfile P, bit IsDPP16=0> : Enc64 { 704 bits<2> src0_modifiers; 705 bits<8> src0; 706 bits<2> src1_modifiers; 707 bits<9> dpp_ctrl; 708 bits<1> bound_ctrl; 709 bits<4> bank_mask; 710 bits<4> row_mask; 711 bit fi; 712 713 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 714 let Inst{48-40} = dpp_ctrl; 715 let Inst{50} = !if(IsDPP16, fi, ?); 716 let Inst{51} = bound_ctrl; 717 let Inst{52} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // src0_neg 718 let Inst{53} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // src0_abs 719 let Inst{54} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // src1_neg 720 let Inst{55} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // src1_abs 721 let Inst{59-56} = bank_mask; 722 let Inst{63-60} = row_mask; 723} 724 725class VOP3_DPPe_Fields_Base { 726 bits<9> dpp_ctrl; 727 bits<1> bound_ctrl; 728 bits<4> bank_mask; 729 bits<4> row_mask; 730 bit fi; 731} 732class VOP3_DPPe_Fields : VOP3_DPPe_Fields_Base { 733 bits<8> src0; 734} 735 736// Common refers to common between DPP and DPP8 737class VOP3_DPPe_Common_Base<bits<10> op, VOPProfile P> : Enc96 { 738 bits<4> src0_modifiers; 739 bits<3> src1_modifiers; 740 bits<3> src2_modifiers; 741 bits<1> clamp; 742 bits<2> omod; 743 744 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); 745 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); 746 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); 747 // OPSEL must be set such that the low result only uses low inputs, and the high result only uses high inputs. 748 let Inst{11} = !if(P.HasOpSel,!if(P.HasSrc0Mods, src0_modifiers{2}, 0),?); 749 let Inst{12} = !if(P.HasOpSel,!if(P.HasSrc1Mods, src1_modifiers{2}, !if((P.IsFP8), src0_modifiers{3}, 0)), ?); 750 let Inst{13} = !if(P.HasOpSel,!if(P.HasSrc2Mods, src2_modifiers{2}, 0),?); 751 let Inst{14} = !if(P.HasOpSel,!if(P.HasSrc0Mods, src0_modifiers{3}, 0),?); 752 let Inst{15} = !if(P.HasClamp, clamp, 0); 753 let Inst{25-16} = op; 754 let Inst{31-26} = 0x35; 755 756 let Inst{60-59} = !if(P.HasOMod, omod, 0); 757 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 758 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); 759 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); 760} 761 762class VOP3_DPPe_Common<bits<10> op, VOPProfile P> : VOP3_DPPe_Common_Base<op, P> { 763 bits<8> vdst; 764 bits<9> src1; 765 bits<9> src2; 766 767 let Inst{7-0} = !if(P.EmitDst, vdst{7-0}, 0); 768 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 769 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 770} 771 772class VOP3P_DPPe_Common_Base<bits<7> op, VOPProfile P> : Enc96 { 773 bits<4> src0_modifiers; 774 bits<4> src1_modifiers; 775 bits<4> src2_modifiers; 776 bits<1> clamp; 777 778 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // neg_hi src0 779 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // neg_hi src1 780 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); // neg_hi src2 781 let Inst{11} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{2}, 0); // op_sel(0) 782 let Inst{12} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{2}, 0); // op_sel(1) 783 let Inst{13} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{2}, 0); // op_sel(2) 784 let Inst{14} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(2) 785 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 786 let Inst{22-16} = op; 787 let Inst{31-23} = 0x198; // encoding 788 let Inst{59} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(0) 789 let Inst{60} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{3}, !if(P.IsDOT, 1, ?)); // op_sel_hi(1) 790 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // neg (lo) 791 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // neg (lo) 792 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); // neg (lo) 793} 794 795class VOP3P_DPPe_Common<bits<7> op, VOPProfile P> : VOP3P_DPPe_Common_Base<op, P> { 796 bits<8> vdst; 797 bits<9> src1; 798 bits<9> src2; 799 800 let Inst{7-0} = vdst; 801 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 802 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 803} 804 805class VOP_DPP_Pseudo <string OpName, VOPProfile P, list<dag> pattern=[], 806 dag Ins = P.InsDPP, string asmOps = P.AsmDPP> : 807 InstSI <P.OutsDPP, Ins, OpName#asmOps, pattern>, 808 VOP <OpName>, 809 SIMCInstr <OpName#"_dpp", SIEncodingFamily.NONE> { 810 811 let isPseudo = 1; 812 let isCodeGenOnly = 1; 813 814 let mayLoad = 0; 815 let mayStore = 0; 816 let hasSideEffects = 0; 817 let UseNamedOperandTable = 1; 818 819 let VALU = 1; 820 let DPP = 1; 821 let Size = 8; 822 823 let ReadsModeReg = !or(P.DstVT.isFP, P.Src0VT.isFP); 824 825 let mayRaiseFPException = ReadsModeReg; 826 let Uses = !if(ReadsModeReg, [MODE, EXEC], [EXEC]); 827 let isConvergent = 1; 828 829 string Mnemonic = OpName; 830 string AsmOperands = asmOps; 831 832 let AsmMatchConverter = !if(P.HasModifiers, "cvtDPP", ""); 833 let SubtargetPredicate = !if(P.HasExt64BitDPP, HasDPALU_DPP, HasDPP); 834 let AssemblerPredicate = !if(P.HasExt64BitDPP, HasDPALU_DPP, HasDPP); 835 let AsmVariantName = !if(P.HasExtDPP, AMDGPUAsmVariants.DPP, 836 AMDGPUAsmVariants.Disable); 837 let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", ""); 838 let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, ""); 839 let DecoderNamespace = "DPP"; 840 841 VOPProfile Pfl = P; 842} 843 844class VOP3_DPP_Pseudo <string OpName, VOPProfile P> : 845 VOP_DPP_Pseudo <OpName, P, [], P.InsVOP3DPP, P.AsmVOP3DPP> { 846 let PseudoInstr = OpName#"_e64"#"_dpp"; 847 let OutOperandList = P.OutsVOP3DPP; 848 let Size = 12; 849 let VOP3 = 1; 850 let AsmMatchConverter = "cvtVOP3DPP"; 851 let AsmVariantName = !if(P.HasExtVOP3DPP, AMDGPUAsmVariants.VOP3_DPP, 852 AMDGPUAsmVariants.Disable); 853} 854 855class VOP_DPP_Real <VOP_DPP_Pseudo ps, int EncodingFamily> : 856 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>, 857 SIMCInstr <ps.PseudoInstr, EncodingFamily> { 858 859 let VALU = 1; 860 let DPP = 1; 861 let isPseudo = 0; 862 let isCodeGenOnly = 0; 863 864 let Defs = ps.Defs; 865 let Uses = ps.Uses; 866 let hasSideEffects = ps.hasSideEffects; 867 868 let Constraints = ps.Constraints; 869 let DisableEncoding = ps.DisableEncoding; 870 871 // Copy relevant pseudo op flags 872 let isConvergent = ps.isConvergent; 873 let SubtargetPredicate = ps.SubtargetPredicate; 874 let AssemblerPredicate = ps.AssemblerPredicate; 875 let OtherPredicates = ps.OtherPredicates; 876 let AsmMatchConverter = ps.AsmMatchConverter; 877 let AsmVariantName = ps.AsmVariantName; 878 let UseNamedOperandTable = ps.UseNamedOperandTable; 879 let DecoderNamespace = ps.DecoderNamespace; 880 let Constraints = ps.Constraints; 881 let DisableEncoding = ps.DisableEncoding; 882 let TSFlags = ps.TSFlags; 883 let SchedRW = ps.SchedRW; 884 let mayLoad = ps.mayLoad; 885 let mayStore = ps.mayStore; 886 let TRANS = ps.TRANS; 887} 888 889class VOP_DPP_Base <string OpName, VOPProfile P, 890 dag InsDPP, 891 string AsmDPP > : 892 InstSI <P.OutsDPP, InsDPP, OpName#AsmDPP, []> { 893 894 let mayLoad = 0; 895 let mayStore = 0; 896 let hasSideEffects = 0; 897 let UseNamedOperandTable = 1; 898 899 let VALU = 1; 900 let DPP = 1; 901 let Size = 8; 902 903 let AsmMatchConverter = !if(P.HasModifiers, "cvtDPP", ""); 904 let SubtargetPredicate = !if(P.HasExt64BitDPP, HasDPALU_DPP, HasDPP); 905 let AssemblerPredicate = !if(P.HasExt64BitDPP, HasDPALU_DPP, HasDPP); 906 let AsmVariantName = !if(P.HasExtDPP, AMDGPUAsmVariants.DPP, 907 AMDGPUAsmVariants.Disable); 908 let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", ""); 909 let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, ""); 910 let DecoderNamespace = "DPP"; 911} 912 913class VOP_DPP <string OpName, VOPProfile P, bit IsDPP16, 914 dag InsDPP = !if(IsDPP16, P.InsDPP16, P.InsDPP), 915 string AsmDPP = !if(IsDPP16, P.AsmDPP16, P.AsmDPP)> : 916 VOP_DPP_Base<OpName, P, InsDPP, AsmDPP>, VOP_DPPe<P, IsDPP16>; 917 918class VOP3_DPP_Base <string OpName, VOPProfile P, bit IsDPP16, 919 dag InsDPP = !if(IsDPP16, P.InsVOP3DPP16, P.InsVOP3DPP), 920 string AsmDPP = !if(IsDPP16, P.AsmVOP3DPP16, P.AsmVOP3DPP)> : 921 VOP_DPP_Base<OpName, P, InsDPP, AsmDPP> { 922 let OutOperandList = P.OutsVOP3DPP; 923 let AsmMatchConverter = "cvtVOP3DPP"; 924 let VOP3 = 1; 925 let AsmVariantName = !if(P.HasExtVOP3DPP, AMDGPUAsmVariants.VOP3_DPP, 926 AMDGPUAsmVariants.Disable); 927 let Size = 12; 928} 929 930class VOP3_DPP <bits<10> op, string OpName, VOPProfile P, bit IsDPP16, 931 dag InsDPP = !if(IsDPP16, P.InsVOP3DPP16, P.InsVOP3DPP), 932 string AsmDPP = !if(IsDPP16, P.AsmVOP3DPP16, P.AsmVOP3DPP)> : 933 VOP3_DPP_Base<OpName, P, IsDPP16, InsDPP, AsmDPP>, VOP3_DPPe_Common<op, P>, 934 VOP3_DPPe_Fields { 935 936 let Inst{40-32} = 0xfa; 937 let Inst{71-64} = !if(P.HasSrc0, src0{7-0}, 0); 938 let Inst{80-72} = dpp_ctrl; 939 let Inst{82} = !if(IsDPP16, fi, ?); 940 let Inst{83} = bound_ctrl; 941 942 // Inst{87-84} ignored by hw 943 let Inst{91-88} = bank_mask; 944 let Inst{95-92} = row_mask; 945} 946 947class VOP3P_DPP <bits<7> op, string OpName, VOPProfile P, bit IsDPP16, 948 dag InsDPP = !if(IsDPP16, P.InsVOP3DPP16, P.InsVOP3DPP), 949 string AsmDPP = !if(IsDPP16, P.AsmVOP3DPP16, P.AsmVOP3DPP)> : 950 VOP3_DPP_Base<OpName, P, IsDPP16, InsDPP, AsmDPP>, VOP3P_DPPe_Common<op, P>, 951 VOP3_DPPe_Fields { 952 953 let VOP3P = 1; 954 955 let Inst{40-32} = 0xfa; 956 let Inst{71-64} = !if(P.HasSrc0, src0{7-0}, 0); 957 let Inst{80-72} = dpp_ctrl; 958 let Inst{82} = !if(IsDPP16, fi, ?); 959 let Inst{83} = bound_ctrl; 960 961 // Inst{87-84} ignored by hw 962 let Inst{91-88} = bank_mask; 963 let Inst{95-92} = row_mask; 964} 965 966class VOP_DPP8e<VOPProfile P> : Enc64 { 967 bits<8> src0; 968 bits<24> dpp8; 969 bits<9> fi; 970 971 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 972 let Inst{63-40} = dpp8{23-0}; 973} 974 975class VOP3_DPP8e_Fields { 976 bits<8> src0; 977 bits<24> dpp8; 978 bits<9> fi; 979} 980 981class VOP_DPP8_Base<string OpName, VOPProfile P, dag InsDPP8 = P.InsDPP8, string AsmDPP8 = P.AsmDPP8> : 982 InstSI<P.OutsDPP8, InsDPP8, OpName#AsmDPP8, []> { 983 984 let mayLoad = 0; 985 let mayStore = 0; 986 let hasSideEffects = 0; 987 let UseNamedOperandTable = 1; 988 989 let VALU = 1; 990 let DPP = 1; 991 let Size = 8; 992 993 let AsmMatchConverter = "cvtDPP8"; 994 let SubtargetPredicate = HasDPP8; 995 let AssemblerPredicate = HasDPP8; 996 let AsmVariantName = AMDGPUAsmVariants.DPP; 997 let Constraints = !if(P.NumSrcArgs, P.TieRegDPP # " = $vdst", ""); 998 let DisableEncoding = !if(P.NumSrcArgs, P.TieRegDPP, ""); 999} 1000 1001class VOP_DPP8<string OpName, VOPProfile P> : 1002 VOP_DPP8_Base<OpName, P>, VOP_DPP8e<P>; 1003 1004class VOP3_DPP8_Base<string OpName, VOPProfile P> : 1005 VOP_DPP8_Base<OpName, P, P.InsVOP3DPP8, P.AsmVOP3DPP8> { 1006 let OutOperandList = P.OutsVOP3DPP8; 1007 let AsmMatchConverter = "cvtVOP3DPP8"; 1008 let AsmVariantName = !if(P.HasExtVOP3DPP, AMDGPUAsmVariants.VOP3_DPP, 1009 AMDGPUAsmVariants.Disable); 1010 let VOP3 = 1; 1011 let Size = 12; 1012} 1013 1014 1015class VOP3_DPP8<bits<10> op, string OpName, VOPProfile P> : 1016 VOP3_DPP8_Base<OpName, P>, VOP3_DPPe_Common<op, P>, 1017 VOP3_DPP8e_Fields { 1018 1019 let Inst{40-32} = fi; 1020 let Inst{71-64} = !if(P.HasSrc0, src0{7-0}, 0); 1021 let Inst{95-72} = dpp8{23-0}; 1022} 1023 1024class VOP3P_DPP8<bits<7> op, string OpName, VOPProfile P> : 1025 VOP3_DPP8_Base<OpName, P>, VOP3P_DPPe_Common<op, P>, 1026 VOP3_DPP8e_Fields { 1027 1028 let VOP3P = 1; 1029 let Inst{40-32} = fi; 1030 let Inst{71-64} = !if(P.HasSrc0, src0{7-0}, 0); 1031 let Inst{95-72} = dpp8{23-0}; 1032} 1033 1034def DPP8Mode { 1035 int FI_0 = 0xE9; 1036 int FI_1 = 0xEA; 1037} 1038 1039class getNumNodeArgs<SDPatternOperator Op> { 1040 SDNode N = !cast<SDNode>(Op); 1041 SDTypeProfile TP = N.TypeProfile; 1042 int ret = TP.NumOperands; 1043} 1044 1045class getDivergentFrag<SDPatternOperator Op> { 1046 assert !or(!isa<SDNode>(Op), !isa<PatFrags>(Op)), "Expected SDNode or PatFrags"; 1047 1048 int NumSrcArgs = !if(!isa<SDNode>(Op), getNumNodeArgs<Op>.ret, 1049 !size(!cast<PatFrags>(Op).Operands)); 1050 PatFrag ret = PatFrag < 1051 !if(!eq(NumSrcArgs, 1), 1052 (ops node:$src0), 1053 !if(!eq(NumSrcArgs, 2), 1054 (ops node:$src0, node:$src1), 1055 (ops node:$src0, node:$src1, node:$src2))), 1056 !if(!eq(NumSrcArgs, 1), 1057 (Op $src0), 1058 !if(!eq(NumSrcArgs, 2), 1059 (Op $src0, $src1), 1060 (Op $src0, $src1, $src2))), 1061 [{ return N->isDivergent(); }] 1062 >; 1063} 1064 1065class VOPPatGen<SDPatternOperator Op, VOPProfile P> { 1066 PatFrag Operator = getDivergentFrag < Op >.ret; 1067 1068 dag Ins = !foreach(tmp, P.Ins32, !subst(ins, Operator, 1069 !subst(P.Src0RC32, P.Src0VT, 1070 !subst(P.Src1RC32, P.Src1VT, tmp)))); 1071 1072 dag Outs = !foreach(tmp, P.Outs32, !subst(outs, set, 1073 !subst(P.DstRC, P.DstVT, tmp))); 1074 1075 list<dag> ret = [!con(Outs, (set Ins))]; 1076} 1077 1078class DivergentUnaryFrag<SDPatternOperator Op> : PatFrag < 1079 (ops node:$src0), 1080 (Op $src0), 1081 [{ return N->isDivergent(); }]> { 1082 // This check is unnecessary as it's captured by the result register 1083 // bank constraint. 1084 // 1085 // FIXME: Should add a way for the emitter to recognize this is a 1086 // trivially true predicate to eliminate the check. 1087 let GISelPredicateCode = [{return true;}]; 1088} 1089 1090class VOPPatOrNull<SDPatternOperator Op, VOPProfile P> { 1091 list<dag> ret = !if(!ne(P.NeedPatGen,PatGenMode.NoPattern), VOPPatGen<Op, P>.ret, []); 1092} 1093 1094class DivergentFragOrOp<SDPatternOperator Op, VOPProfile P> { 1095 SDPatternOperator ret = !if(!eq(P.NeedPatGen,PatGenMode.Pattern), 1096 !if(!isa<SDNode>(Op), getDivergentFrag<Op>.ret, Op), Op); 1097} 1098 1099class getVSrcOp<ValueType vt> { 1100 RegisterOperand ret = !if(!eq(vt.Size, 32), VSrc_b32, VSrc_b16); 1101} 1102 1103// Class for binary integer operations with the clamp bit set for saturation 1104// TODO: Add sub with negated inline constant pattern. 1105class VOPBinOpClampPat<SDPatternOperator node, Instruction inst, ValueType vt> : 1106 GCNPat<(node vt:$src0, vt:$src1), 1107 (inst getVSrcOp<vt>.ret:$src0, getVSrcOp<vt>.ret:$src1, 1108 DSTCLAMP.ENABLE) 1109>; 1110 1111//===----------------------------------------------------------------------===// 1112// VOP3 Classes 1113//===----------------------------------------------------------------------===// 1114 1115class getVOP3ModPat<VOPProfile P, SDPatternOperator node> { 1116 dag src0 = !if(P.HasOMod, 1117 (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod), 1118 (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)); 1119 1120 list<dag> ret3 = [(set P.DstVT:$vdst, 1121 (DivergentFragOrOp<node, P>.ret (P.Src0VT src0), 1122 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)), 1123 (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers))))]; 1124 1125 list<dag> ret2 = [(set P.DstVT:$vdst, 1126 (DivergentFragOrOp<node, P>.ret (P.Src0VT src0), 1127 (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))]; 1128 1129 list<dag> ret1 = [(set P.DstVT:$vdst, 1130 (DivergentFragOrOp<node, P>.ret (P.Src0VT src0)))]; 1131 1132 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1133 !if(!eq(P.NumSrcArgs, 2), ret2, 1134 ret1)); 1135} 1136 1137class getVOP3PModPat<VOPProfile P, SDPatternOperator node, bit HasExplicitClamp, 1138 bit IsDOT = 0, 1139 ComplexPattern SrcPat = !if(IsDOT, VOP3PModsDOT, VOP3PMods)> { 1140 dag src0_dag = (P.Src0VT (SrcPat P.Src0VT:$src0, i32:$src0_modifiers)); 1141 dag src1_dag = (P.Src1VT (SrcPat P.Src1VT:$src1, i32:$src1_modifiers)); 1142 dag src2_dag = (P.Src2VT (SrcPat P.Src2VT:$src2, i32:$src2_modifiers)); 1143 dag clamp_dag = (i1 timm:$clamp); 1144 1145 list<dag> ret3 = [(set P.DstVT:$vdst, 1146 !if(HasExplicitClamp, 1147 (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, src2_dag, clamp_dag), 1148 (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, src2_dag)))]; 1149 1150 list<dag> ret2 = [(set P.DstVT:$vdst, 1151 !if(HasExplicitClamp, 1152 (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag, clamp_dag), 1153 (DivergentFragOrOp<node, P>.ret src0_dag, src1_dag)))]; 1154 1155 list<dag> ret1 = [(set P.DstVT:$vdst, 1156 !if(HasExplicitClamp, 1157 (DivergentFragOrOp<node, P>.ret src0_dag, clamp_dag), 1158 (DivergentFragOrOp<node, P>.ret src0_dag)))]; 1159 1160 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1161 !if(!eq(P.NumSrcArgs, 2), ret2, 1162 ret1)); 1163} 1164 1165class getVOP3OpSelPat<VOPProfile P, SDPatternOperator node> { 1166 list<dag> ret3 = [(set P.DstVT:$vdst, 1167 (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers)), 1168 (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers)), 1169 (P.Src2VT (VOP3OpSel P.Src2VT:$src2, i32:$src2_modifiers))))]; 1170 1171 list<dag> ret2 = [(set P.DstVT:$vdst, 1172 (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers)), 1173 (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers))))]; 1174 1175 list<dag> ret1 = [(set P.DstVT:$vdst, 1176 (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))))]; 1177 1178 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1179 !if(!eq(P.NumSrcArgs, 2), ret2, 1180 ret1)); 1181} 1182 1183class getVOP3OpSelModPat<VOPProfile P, SDPatternOperator node> { 1184 list<dag> ret3 = [(set P.DstVT:$vdst, 1185 (DivergentFragOrOp<node, P>.ret (P.Src0VT !if(P.HasClamp, (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers), 1186 (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))), 1187 (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers)), 1188 (P.Src2VT (VOP3OpSelMods P.Src2VT:$src2, i32:$src2_modifiers))))]; 1189 1190 list<dag> ret2 = [(set P.DstVT:$vdst, 1191 (DivergentFragOrOp<node, P>.ret !if(P.HasClamp, (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers)), 1192 (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))), 1193 (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers))))]; 1194 1195 list<dag> ret1 = [(set P.DstVT:$vdst, 1196 (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))))]; 1197 1198 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1199 !if(!eq(P.NumSrcArgs, 2), ret2, 1200 ret1)); 1201} 1202 1203class getVOP3FromVOP2Pat<VOPProfile P, SDPatternOperator node> { 1204 list<dag> ret = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1))]; 1205} 1206// In VOP1, we can have clamp and omod even if !HasModifiers 1207class getVOP3Pat<VOPProfile P, SDPatternOperator node> { 1208 dag src0 = 1209 !if(P.HasOMod, 1210 !if(P.HasClamp, 1211 (VOP3Mods0 P.Src0VT:$src0, i1:$clamp, i32:$omod), 1212 (VOP3Mods0 P.Src0VT:$src0, i32:$omod)), // impossible? 1213 !if(P.HasClamp, 1214 (VOP3Mods0 P.Src0VT:$src0, i1:$clamp), 1215 (VOP3Mods0 P.Src0VT:$src0)) 1216 ); 1217 list<dag> ret3 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret (P.Src0VT src0), P.Src1VT:$src1, P.Src2VT:$src2))]; 1218 1219 list<dag> ret2 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret (P.Src0VT src0), P.Src1VT:$src1))]; 1220 1221 list<dag> ret1 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret (P.Src0VT src0)))]; 1222 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1223 !if(!eq(P.NumSrcArgs, 2), ret2, 1224 ret1)); 1225} 1226 1227class getVOP3ClampPat<VOPProfile P, SDPatternOperator node> { 1228 list<dag> ret3 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i1:$clamp))]; 1229 list<dag> ret2 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, i1:$clamp))]; 1230 list<dag> ret1 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, i1:$clamp))]; 1231 list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3, 1232 !if(!eq(P.NumSrcArgs, 2), ret2, 1233 ret1)); 1234} 1235 1236class getVOP3MAIPat<VOPProfile P, SDPatternOperator node> { 1237 list<dag> ret = !if(!eq(P.Src0VT, P.Src1VT), 1238 // mfma 1239 [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, 1240 timm:$cbsz, timm:$abid, timm:$blgp))], 1241 // smfmac 1242 [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i32:$idx, 1243 timm:$cbsz, timm:$abid))]); 1244} 1245 1246class VOP3Features<bit Clamp, bit OpSel, bit Packed, bit MAI> { 1247 bit HasClamp = Clamp; 1248 bit HasOpSel = OpSel; 1249 bit IsPacked = Packed; 1250 bit IsMAI = MAI; 1251} 1252 1253def VOP3_REGULAR : VOP3Features<0, 0, 0, 0>; 1254def VOP3_CLAMP : VOP3Features<1, 0, 0, 0>; 1255def VOP3_OPSEL : VOP3Features<1, 1, 0, 0>; 1256def VOP3_PACKED : VOP3Features<1, 1, 1, 0>; 1257def VOP3_MAI : VOP3Features<0, 0, 0, 1>; 1258 1259class VOP3_Profile_Base<VOPProfile P, VOP3Features Features = VOP3_REGULAR> : VOPProfile<P.ArgVT> { 1260 1261 let HasClamp = !if(Features.HasClamp, 1, P.HasClamp); 1262 let HasOpSel = !if(Features.HasOpSel, 1, P.HasOpSel); 1263 let IsMAI = !if(Features.IsMAI, 1, P.IsMAI); 1264 let IsPacked = !if(Features.IsPacked, 1, P.IsPacked); 1265 1266 let HasModifiers = 1267 !if (Features.IsMAI, 0, 1268 !or(Features.IsPacked, Features.HasOpSel, P.HasModifiers)); 1269} 1270 1271class VOP3_Profile<VOPProfile P, VOP3Features Features = VOP3_REGULAR> : VOP3_Profile_Base<P, Features> { 1272 let IsSingle = 1; 1273 1274} 1275 1276// consistently gives instructions a _e64 suffix 1277multiclass VOP3Inst_Pseudo_Wrapper<string opName, VOPProfile P, list<dag> pattern = [], bit VOP3Only = 0> { 1278 def _e64 : VOP3_Pseudo<opName, P, pattern, VOP3Only>; 1279} 1280 1281class VOP3InstBase<string OpName, VOPProfile P, SDPatternOperator node = null_frag, bit IsVOP2 = 0> : 1282 VOP3_Pseudo<OpName, P, 1283 !if(P.HasOpSel, 1284 !if(P.HasModifiers, 1285 getVOP3OpSelModPat<P, node>.ret, 1286 getVOP3OpSelPat<P, node>.ret), 1287 !if(P.HasModifiers, 1288 getVOP3ModPat<P, node>.ret, 1289 !if(IsVOP2, 1290 getVOP3FromVOP2Pat<P, node>.ret, 1291 !if(P.HasIntClamp, 1292 getVOP3ClampPat<P, node>.ret, 1293 !if (P.IsMAI, 1294 getVOP3MAIPat<P, node>.ret, 1295 getVOP3Pat<P, node>.ret))))), 1296 0, P.HasOpSel> { 1297 1298 let IntClamp = P.HasIntClamp; 1299 let AsmMatchConverter = 1300 !if(P.HasOpSel, 1301 "cvtVOP3OpSel", 1302 !if(!or(P.HasModifiers, P.HasOMod, P.HasIntClamp), 1303 "cvtVOP3", 1304 "")); 1305} 1306 1307multiclass VOP3Inst<string OpName, VOPProfile P, SDPatternOperator node = null_frag> { 1308 def _e64 : VOP3InstBase<OpName, P, node>; 1309 let SubtargetPredicate = isGFX11Plus in { 1310 if P.HasExtVOP3DPP then 1311 def _e64_dpp : VOP3_DPP_Pseudo <OpName, P>; 1312 } // end SubtargetPredicate = isGFX11Plus 1313} 1314 1315class UniformUnaryFragOrOp<SDPatternOperator Op> { 1316 SDPatternOperator ret = !if(!or(!isa<SDNode>(Op), !isa<PatFrags>(Op)), 1317 UniformUnaryFrag<Op>, Op); 1318} 1319 1320multiclass VOP3PseudoScalarInst<string OpName, VOPProfile P, 1321 SDPatternOperator node = null_frag> { 1322 def _e64 : VOP3_Pseudo<OpName, P, [(set P.DstVT:$vdst, 1323 (UniformUnaryFragOrOp<node>.ret 1324 (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, 1325 i32:$omod))))]>; 1326} 1327 1328//===----------------------------------------------------------------------===// 1329// VOP3 DPP 1330//===----------------------------------------------------------------------===// 1331 1332class Base_VOP3_DPP16<bits<10> op, VOP_DPP_Pseudo ps, string opName = ps.OpName> 1333 : VOP3_DPP<op, opName, ps.Pfl, 1> { 1334 let VOP3_OPSEL = ps.Pfl.HasOpSel; 1335 let IsDOT = ps.IsDOT; 1336 let hasSideEffects = ps.hasSideEffects; 1337 let Defs = ps.Defs; 1338 let SchedRW = ps.SchedRW; 1339 let Uses = ps.Uses; 1340 let AssemblerPredicate = HasDPP16; 1341 let SubtargetPredicate = HasDPP16; 1342 let OtherPredicates = ps.OtherPredicates; 1343} 1344 1345class VOP3_DPP16<bits<10> op, VOP_DPP_Pseudo ps, int subtarget, 1346 string opName = ps.OpName> 1347 : Base_VOP3_DPP16<op, ps, opName>, SIMCInstr<ps.PseudoInstr, subtarget>; 1348 1349class VOP3_DPP16_Gen<bits<10> op, VOP_DPP_Pseudo ps, GFXGen Gen, 1350 string opName = ps.OpName> : 1351 VOP3_DPP16 <op, ps, Gen.Subtarget, opName> { 1352 let AssemblerPredicate = Gen.AssemblerPredicate; 1353 let OtherPredicates = !if(ps.Pfl.IsRealTrue16, [UseRealTrue16Insts], []); 1354 let DecoderNamespace = "DPP"#Gen.DecoderNamespace# 1355 !if(ps.Pfl.IsRealTrue16, "", "_FAKE16"); 1356} 1357 1358class Base_VOP3_DPP8<bits<10> op, VOP_Pseudo ps, string opName = ps.OpName> 1359 : VOP3_DPP8<op, opName, ps.Pfl> { 1360 let VOP3_OPSEL = ps.Pfl.HasOpSel; 1361 let IsDOT = ps.IsDOT; 1362 let hasSideEffects = ps.hasSideEffects; 1363 let Defs = ps.Defs; 1364 let SchedRW = ps.SchedRW; 1365 let Uses = ps.Uses; 1366 1367 let OtherPredicates = ps.OtherPredicates; 1368} 1369 1370class Base_VOP3b_DPP16<bits<10> op, VOP_DPP_Pseudo ps, 1371 string opName = ps.OpName> 1372 : Base_VOP3_DPP16<op, ps, opName> { 1373 bits<7> sdst; 1374 let Inst{14 - 8} = sdst; 1375} 1376 1377class VOP3b_DPP8_Base<bits<10> op, VOP_Pseudo ps, string opName = ps.OpName> 1378 : Base_VOP3_DPP8<op, ps, opName> { 1379 bits<7> sdst; 1380 let Inst{14 - 8} = sdst; 1381} 1382 1383//===----------------------------------------------------------------------===// 1384// VOP3 GFX11, GFX12 1385//===----------------------------------------------------------------------===// 1386 1387multiclass VOP3_Real_Base<GFXGen Gen, bits<10> op, string opName = NAME, 1388 bit isSingle = 0> { 1389 defvar ps = !cast<VOP_Pseudo>(opName#"_e64"); 1390 let IsSingle = !or(isSingle, ps.Pfl.IsSingle) in { 1391 if ps.Pfl.HasOpSel then 1392 def _e64#Gen.Suffix : 1393 VOP3_Real_Gen<ps, Gen>, 1394 VOP3OpSel_gfx11_gfx12<op, ps.Pfl>; 1395 if !not(ps.Pfl.HasOpSel) then 1396 def _e64#Gen.Suffix : 1397 VOP3_Real_Gen<ps, Gen>, 1398 VOP3e_gfx11_gfx12<op, ps.Pfl>; 1399 } 1400} 1401 1402multiclass VOP3Dot_Real_Base<GFXGen Gen, bits<10> op, string opName = NAME, 1403 bit isSingle = 0> { 1404 defvar ps = !cast<VOP_Pseudo>(opName#"_e64"); 1405 let IsSingle = !or(isSingle, ps.Pfl.IsSingle) in { 1406 def _e64#Gen.Suffix : 1407 VOP3_Real_Gen<ps, Gen>, 1408 VOP3DotOpSel_gfx11_gfx12<op, ps.Pfl>; 1409 } 1410} 1411 1412multiclass VOP3_Real_with_name<GFXGen Gen, bits<10> op, string opName, 1413 string asmName, bit isSingle = 0> { 1414 defvar ps = !cast<VOP_Pseudo>(opName#"_e64"); 1415 let AsmString = asmName # ps.AsmOperands, 1416 IsSingle = !or(isSingle, ps.Pfl.IsSingle) in { 1417 if ps.Pfl.IsFP8 then { 1418 def _e64#Gen.Suffix : 1419 VOP3_Real_Gen<ps, Gen>, 1420 VOP3FP8OpSel_gfx11_gfx12<op, ps.Pfl>; 1421 } else { 1422 if ps.Pfl.HasOpSel then 1423 def _e64#Gen.Suffix : 1424 VOP3_Real_Gen<ps, Gen>, 1425 VOP3OpSel_gfx11_gfx12<op, ps.Pfl>; 1426 if !not(ps.Pfl.HasOpSel) then 1427 def _e64#Gen.Suffix : 1428 VOP3_Real_Gen<ps, Gen>, 1429 VOP3e_gfx11_gfx12<op, ps.Pfl>; 1430 } 1431 } 1432 def Gen.Suffix#"_VOP3_alias" : MnemonicAlias<ps.Mnemonic, asmName>, Requires<[Gen.AssemblerPredicate]>, LetDummies; 1433} 1434 1435// for READLANE/WRITELANE 1436multiclass VOP3_Real_No_Suffix<GFXGen Gen, bits<10> op, string opName = NAME> { 1437 defvar ps = !cast<VOP_Pseudo>(opName); 1438 def _e64#Gen.Suffix : 1439 VOP3_Real_Gen<ps, Gen>, 1440 VOP3e_gfx11_gfx12<op, ps.Pfl>; 1441} 1442 1443multiclass VOP3_Real_dpp_Base<GFXGen Gen, bits<10> op, string opName = NAME> { 1444 def _e64_dpp#Gen.Suffix : 1445 VOP3_DPP16_Gen<op, !cast<VOP_DPP_Pseudo>(opName#"_e64"#"_dpp"), Gen>; 1446} 1447 1448multiclass VOP3Dot_Real_dpp_Base<GFXGen Gen, bits<10> op, string opName = NAME> { 1449 def _e64_dpp#Gen.Suffix : 1450 VOP3_DPP16_Gen<op, !cast<VOP_DPP_Pseudo>(opName#"_e64"#"_dpp"), Gen> { 1451 let Inst{11} = ?; 1452 let Inst{12} = ?; 1453 } 1454} 1455 1456multiclass VOP3_Real_dpp_with_name<GFXGen Gen, bits<10> op, string opName, 1457 string asmName> { 1458 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1459 let AsmString = asmName # ps.Pfl.AsmVOP3DPP16 in { 1460 defm NAME : VOP3_Real_dpp_Base<Gen, op, opName>; 1461 } 1462} 1463 1464multiclass VOP3_Real_dpp8_Base<GFXGen Gen, bits<10> op, string opName = NAME> { 1465 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1466 def _e64_dpp8#Gen.Suffix : Base_VOP3_DPP8<op, ps> { 1467 let DecoderNamespace = "DPP8"#Gen.DecoderNamespace; 1468 let AssemblerPredicate = Gen.AssemblerPredicate; 1469 } 1470} 1471 1472multiclass VOP3Dot_Real_dpp8_Base<GFXGen Gen, bits<10> op, string opName = NAME> { 1473 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1474 def _e64_dpp8#Gen.Suffix : Base_VOP3_DPP8<op, ps> { 1475 let Inst{11} = ?; 1476 let Inst{12} = ?; 1477 let DecoderNamespace = "DPP8"#Gen.DecoderNamespace; 1478 let AssemblerPredicate = Gen.AssemblerPredicate; 1479 } 1480} 1481 1482multiclass VOP3_Real_dpp8_with_name<GFXGen Gen, bits<10> op, string opName, 1483 string asmName> { 1484 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1485 let AsmString = asmName # ps.Pfl.AsmVOP3DPP8, 1486 DecoderNamespace = "DPP8"#Gen.DecoderNamespace# 1487 !if(ps.Pfl.IsRealTrue16, "", "_FAKE16"), 1488 OtherPredicates = !if(ps.Pfl.IsRealTrue16, [UseRealTrue16Insts], 1489 [TruePredicate]) in { 1490 defm NAME : VOP3_Real_dpp8_Base<Gen, op, opName>; 1491 } 1492} 1493 1494multiclass VOP3be_Real<GFXGen Gen, bits<10> op, string opName, string asmName, 1495 bit isSingle = 0> { 1496 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1497 let IsSingle = !or(isSingle, ps.Pfl.IsSingle) in 1498 def _e64#Gen.Suffix : 1499 VOP3_Real_Gen<ps, Gen, asmName>, 1500 VOP3be_gfx11_gfx12<op, ps.Pfl> ; 1501} 1502 1503multiclass VOP3be_Real_dpp<GFXGen Gen, bits<10> op, string opName, 1504 string asmName> { 1505 defvar ps = !cast<VOP3_Pseudo>(opName #"_e64"); 1506 defvar dpp_ps = !cast<VOP_DPP_Pseudo>(opName #"_e64" #"_dpp"); 1507 def _e64_dpp#Gen.Suffix : Base_VOP3b_DPP16<op, dpp_ps, asmName>, 1508 SIMCInstr<dpp_ps.PseudoInstr, Gen.Subtarget> { 1509 let DecoderNamespace = "DPP"#Gen.DecoderNamespace; 1510 let AssemblerPredicate = Gen.AssemblerPredicate; 1511 } 1512} 1513 1514multiclass VOP3be_Real_dpp8<GFXGen Gen, bits<10> op, string opName, 1515 string asmName> { 1516 defvar ps = !cast<VOP3_Pseudo>(opName #"_e64"); 1517 def _e64_dpp8#Gen.Suffix : VOP3b_DPP8_Base<op, ps, asmName> { 1518 let DecoderNamespace = "DPP8"#Gen.DecoderNamespace; 1519 let AssemblerPredicate = Gen.AssemblerPredicate; 1520 } 1521} 1522 1523// VOP1 and VOP2 depend on these triple defs 1524multiclass VOP3_Realtriple<GFXGen Gen, bits<10> op, bit isSingle = 0, 1525 string opName = NAME> : 1526 VOP3_Real_Base<Gen, op, opName, isSingle>, 1527 VOP3_Real_dpp_Base<Gen, op, opName>, 1528 VOP3_Real_dpp8_Base<Gen, op, opName>; 1529 1530multiclass VOP3Dot_Realtriple<GFXGen Gen, bits<10> op, bit isSingle = 0, 1531 string opName = NAME> : 1532 VOP3Dot_Real_Base<Gen, op, opName, isSingle>, 1533 VOP3Dot_Real_dpp_Base<Gen, op, opName>, 1534 VOP3Dot_Real_dpp8_Base<Gen, op, opName>; 1535 1536multiclass VOP3Only_Realtriple<GFXGen Gen, bits<10> op> : 1537 VOP3_Realtriple<Gen, op, 1>; 1538 1539multiclass VOP3_Realtriple_with_name<GFXGen Gen, bits<10> op, string opName, 1540 string asmName, bit isSingle = 0> : 1541 VOP3_Real_with_name<Gen, op, opName, asmName, isSingle>, 1542 VOP3_Real_dpp_with_name<Gen, op, opName, asmName>, 1543 VOP3_Real_dpp8_with_name<Gen, op, opName, asmName>; 1544 1545multiclass VOP3Only_Realtriple_with_name<GFXGen Gen, bits<10> op, string opName, 1546 string asmName> : 1547 VOP3_Realtriple_with_name<Gen, op, opName, asmName, 1>; 1548 1549multiclass VOP3Only_Realtriple_t16<GFXGen Gen, bits<10> op, string asmName, 1550 string opName = NAME> 1551 : VOP3Only_Realtriple_with_name<Gen, op, opName, asmName>; 1552 1553multiclass VOP3be_Realtriple< 1554 GFXGen Gen, bits<10> op, bit isSingle = 0, string opName = NAME, 1555 string asmName = !cast<VOP_Pseudo>(opName#"_e64").Mnemonic> : 1556 VOP3be_Real<Gen, op, opName, asmName, isSingle>, 1557 VOP3be_Real_dpp<Gen, op, opName, asmName>, 1558 VOP3be_Real_dpp8<Gen, op, opName, asmName>; 1559 1560multiclass VOP3beOnly_Realtriple<GFXGen Gen, bits<10> op> : 1561 VOP3be_Realtriple<Gen, op, 1>; 1562 1563//===----------------------------------------------------------------------===// 1564// VOP3 GFX11 1565//===----------------------------------------------------------------------===// 1566 1567multiclass VOP3be_Real_gfx11<bits<10> op, string opName, string asmName, 1568 bit isSingle = 0> : 1569 VOP3be_Real<GFX11Gen, op, opName, asmName, isSingle>; 1570 1571multiclass VOP3_Real_Base_gfx11<bits<10> op, string opName = NAME, 1572 bit isSingle = 0> : 1573 VOP3_Real_Base<GFX11Gen, op, opName, isSingle>; 1574 1575multiclass VOP3_Realtriple_gfx11<bits<10> op, bit isSingle = 0, 1576 string opName = NAME> : 1577 VOP3_Realtriple<GFX11Gen, op, isSingle, opName>; 1578 1579multiclass VOP3Only_Realtriple_t16_gfx11<bits<10> op, string asmName, 1580 string opName = NAME> 1581 : VOP3Only_Realtriple_with_name<GFX11Gen, op, opName, asmName>; 1582 1583//===----------------------------------------------------------------------===// 1584// VOP3 GFX12 1585//===----------------------------------------------------------------------===// 1586 1587multiclass VOP3Only_Realtriple_gfx12<bits<10> op, bit isSingle = 0> : 1588 VOP3_Realtriple<GFX12Gen, op, isSingle>; 1589 1590// IsSingle is captured from the vopprofile for these instructions, but the 1591// following alternative is more explicit 1592multiclass VOP3Only_Real_Base_gfx12<bits<10> op> : 1593 VOP3_Real_Base<GFX12Gen, op, NAME, 1/*IsSingle*/>; 1594 1595multiclass VOP3Only_Realtriple_t16_gfx12<bits<10> op> : 1596 VOP3Only_Realtriple<GFX12Gen, op>; 1597 1598multiclass VOP3be_Real_with_name_gfx12<bits<10> op, string opName, 1599 string asmName, bit isSingle = 0> { 1600 defvar ps = !cast<VOP3_Pseudo>(opName#"_e64"); 1601 let AsmString = asmName # ps.AsmOperands, 1602 IsSingle = !or(isSingle, ps.Pfl.IsSingle) in 1603 def _e64_gfx12 : 1604 VOP3_Real_Gen<ps, GFX12Gen, asmName>, 1605 VOP3be_gfx11_gfx12<op, ps.Pfl>, 1606 MnemonicAlias<ps.Mnemonic, asmName>, Requires<[isGFX12Only]>; 1607} 1608 1609multiclass VOP3_Realtriple_with_name_gfx12<bits<10> op, string opName, 1610 string asmName, bit isSingle = 0> : 1611 VOP3_Realtriple_with_name<GFX12Gen, op, opName, asmName, isSingle>; 1612 1613multiclass VOP3Only_Realtriple_with_name_gfx11_gfx12<bits<10> op, string opName, 1614 string asmName> : 1615 VOP3Only_Realtriple_with_name<GFX11Gen, op, opName, asmName>, 1616 VOP3Only_Realtriple_with_name<GFX12Gen, op, opName, asmName>; 1617 1618multiclass VOP3Only_Realtriple_with_name_t16_gfx12<bits<10> op, string asmName, 1619 string opName = NAME> 1620 : VOP3Only_Realtriple_with_name<GFX12Gen, op, opName, asmName>; 1621 1622//===----------------------------------------------------------------------===// 1623 1624include "VOPCInstructions.td" 1625include "VOP1Instructions.td" 1626include "VOP2Instructions.td" 1627include "VOP3Instructions.td" 1628include "VOP3PInstructions.td" 1629include "VOPDInstructions.td" 1630 1631class ClassPat<Instruction inst, ValueType vt> : GCNPat < 1632 (is_fpclass (vt (VOP3ModsNonCanonicalizing vt:$src0, i32:$src0_mods)), (i32 timm:$mask)), 1633 (inst i32:$src0_mods, vt:$src0, (V_MOV_B32_e32 timm:$mask)) 1634>; 1635 1636def : ClassPat<V_CMP_CLASS_F16_e64, f16> { 1637 let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts]; 1638} 1639 1640def : ClassPat<V_CMP_CLASS_F16_t16_e64, f16> { 1641 let OtherPredicates = [HasTrue16BitInsts]; 1642} 1643 1644def : ClassPat<V_CMP_CLASS_F32_e64, f32>; 1645def : ClassPat<V_CMP_CLASS_F64_e64, f64>; 1646 1647class VOPInfoTable <string Format> : GenericTable { 1648 let FilterClass = Format # "_Real"; 1649 let CppTypeName = "VOPInfo"; 1650 let Fields = ["Opcode", "IsSingle"]; 1651 1652 let PrimaryKey = ["Opcode"]; 1653 let PrimaryKeyName = "get" # Format # "OpcodeHelper"; 1654} 1655 1656def VOP1InfoTable : VOPInfoTable<"VOP1">; 1657def VOP2InfoTable : VOPInfoTable<"VOP2">; 1658def VOP3InfoTable : VOPInfoTable<"VOP3">; 1659 1660class VOPC64Table <string Format> : GenericTable { 1661 let FilterClass = "VOPC64_" # Format # "_Base"; 1662 let CppTypeName = "VOPC64DPPInfo"; 1663 let Fields = ["Opcode"]; 1664 1665 let PrimaryKey = ["Opcode"]; 1666 let PrimaryKeyName = "isVOPC64" # Format # "OpcodeHelper"; 1667} 1668 1669def VOPC64DPPTable : VOPC64Table<"DPP">; 1670def VOPC64DPP8Table : VOPC64Table<"DPP8">; 1671 1672def VOPTrue16Table : GenericTable { 1673 let FilterClass = "VOP_Pseudo"; 1674 let CppTypeName = "VOPTrue16Info"; 1675 let Fields = ["Opcode", "IsTrue16"]; 1676 1677 let PrimaryKey = ["Opcode"]; 1678 let PrimaryKeyName = "getTrue16OpcodeHelper"; 1679} 1680