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