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