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