1//===-- VOPInstructions.td - Vector Instruction Defintions ----------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// dummies for outer let 11class LetDummies { 12 bit isCommutable; 13 bit isConvertibleToThreeAddress; 14 bit isMoveImm; 15 bit isReMaterializable; 16 bit isAsCheapAsAMove; 17 bit VOPAsmPrefer32Bit; 18 Predicate SubtargetPredicate; 19 string Constraints; 20 string DisableEncoding; 21 list<SchedReadWrite> SchedRW; 22 list<Register> Uses; 23 list<Register> Defs; 24} 25 26class VOP <string opName> { 27 string OpName = opName; 28} 29 30class VOPAnyCommon <dag outs, dag ins, string asm, list<dag> pattern> : 31 InstSI <outs, ins, asm, pattern> { 32 33 let mayLoad = 0; 34 let mayStore = 0; 35 let hasSideEffects = 0; 36 let UseNamedOperandTable = 1; 37 let VALU = 1; 38 let Uses = [EXEC]; 39} 40 41class VOP_Pseudo <string opName, string suffix, VOPProfile P, dag outs, dag ins, 42 string asm, list<dag> pattern> : 43 InstSI <outs, ins, asm, pattern>, 44 VOP <opName>, 45 SIMCInstr <opName#suffix, SIEncodingFamily.NONE>, 46 MnemonicAlias<opName#suffix, opName> { 47 48 let isPseudo = 1; 49 let isCodeGenOnly = 1; 50 let UseNamedOperandTable = 1; 51 52 string Mnemonic = opName; 53 VOPProfile Pfl = P; 54 55 string AsmOperands; 56} 57 58class VOP3Common <dag outs, dag ins, string asm = "", 59 list<dag> pattern = [], bit HasMods = 0, 60 bit VOP3Only = 0> : 61 VOPAnyCommon <outs, ins, asm, pattern> { 62 63 // Using complex patterns gives VOP3 patterns a very high complexity rating, 64 // but standalone patterns are almost always preferred, so we need to adjust the 65 // priority lower. The goal is to use a high number to reduce complexity to 66 // zero (or less than zero). 67 let AddedComplexity = -1000; 68 69 let VOP3 = 1; 70 71 let AsmVariantName = AMDGPUAsmVariants.VOP3; 72 let AsmMatchConverter = !if(!eq(HasMods,1), "cvtVOP3", ""); 73 74 let isCodeGenOnly = 0; 75 76 int Size = 8; 77 78 // Because SGPRs may be allowed if there are multiple operands, we 79 // need a post-isel hook to insert copies in order to avoid 80 // violating constant bus requirements. 81 let hasPostISelHook = 1; 82} 83 84class VOP3_Pseudo <string opName, VOPProfile P, list<dag> pattern = [], 85 bit VOP3Only = 0, bit isVOP3P = 0, bit isVop3OpSel = 0> : 86 VOP_Pseudo <opName, "_e64", P, P.Outs64, 87 !if(isVop3OpSel, 88 P.InsVOP3OpSel, 89 !if(!and(isVOP3P, P.IsPacked), P.InsVOP3P, P.Ins64)), 90 "", pattern> { 91 92 let VOP3_OPSEL = isVop3OpSel; 93 let IsPacked = P.IsPacked; 94 95 let AsmOperands = !if(isVop3OpSel, 96 P.AsmVOP3OpSel, 97 !if(!and(isVOP3P, P.IsPacked), P.AsmVOP3P, P.Asm64)); 98 99 let Size = 8; 100 let mayLoad = 0; 101 let mayStore = 0; 102 let hasSideEffects = 0; 103 let SubtargetPredicate = isGCN; 104 105 // Because SGPRs may be allowed if there are multiple operands, we 106 // need a post-isel hook to insert copies in order to avoid 107 // violating constant bus requirements. 108 let hasPostISelHook = 1; 109 110 // Using complex patterns gives VOP3 patterns a very high complexity rating, 111 // but standalone patterns are almost always preferred, so we need to adjust the 112 // priority lower. The goal is to use a high number to reduce complexity to 113 // zero (or less than zero). 114 let AddedComplexity = -1000; 115 116 let VOP3 = 1; 117 let VALU = 1; 118 let FPClamp = P.HasFPClamp; 119 let IntClamp = P.HasIntClamp; 120 let ClampLo = P.HasClampLo; 121 let ClampHi = P.HasClampHi; 122 123 let Uses = [EXEC]; 124 125 let AsmVariantName = AMDGPUAsmVariants.VOP3; 126 let AsmMatchConverter = 127 !if(isVOP3P, 128 "cvtVOP3P", 129 !if(!or(P.HasModifiers, !or(P.HasOMod, P.HasIntClamp)), 130 "cvtVOP3", 131 "")); 132} 133 134class VOP3P_Pseudo <string opName, VOPProfile P, list<dag> pattern = []> : 135 VOP3_Pseudo<opName, P, pattern, 1, 1> { 136 let VOP3P = 1; 137} 138 139class VOP3_Real <VOP_Pseudo ps, int EncodingFamily> : 140 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>, 141 SIMCInstr <ps.PseudoInstr, EncodingFamily> { 142 143 let isPseudo = 0; 144 let isCodeGenOnly = 0; 145 let UseNamedOperandTable = 1; 146 147 let Constraints = ps.Constraints; 148 let DisableEncoding = ps.DisableEncoding; 149 150 // copy relevant pseudo op flags 151 let SubtargetPredicate = ps.SubtargetPredicate; 152 let AsmMatchConverter = ps.AsmMatchConverter; 153 let AsmVariantName = ps.AsmVariantName; 154 let Constraints = ps.Constraints; 155 let DisableEncoding = ps.DisableEncoding; 156 let TSFlags = ps.TSFlags; 157 let UseNamedOperandTable = ps.UseNamedOperandTable; 158 let Uses = ps.Uses; 159 let Defs = ps.Defs; 160 161 VOPProfile Pfl = ps.Pfl; 162} 163 164// XXX - Is there any reason to distingusih this from regular VOP3 165// here? 166class VOP3P_Real<VOP_Pseudo ps, int EncodingFamily> : 167 VOP3_Real<ps, EncodingFamily>; 168 169class VOP3a<VOPProfile P> : Enc64 { 170 bits<4> src0_modifiers; 171 bits<9> src0; 172 bits<3> src1_modifiers; 173 bits<9> src1; 174 bits<3> src2_modifiers; 175 bits<9> src2; 176 bits<1> clamp; 177 bits<2> omod; 178 179 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); 180 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); 181 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); 182 183 let Inst{31-26} = 0x34; //encoding 184 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 185 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 186 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 187 let Inst{60-59} = !if(P.HasOMod, omod, 0); 188 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 189 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); 190 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); 191} 192 193class VOP3a_si <bits<9> op, VOPProfile P> : VOP3a<P> { 194 let Inst{25-17} = op; 195 let Inst{11} = !if(P.HasClamp, clamp{0}, 0); 196} 197 198class VOP3a_vi <bits<10> op, VOPProfile P> : VOP3a<P> { 199 let Inst{25-16} = op; 200 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 201} 202 203class VOP3e_si <bits<9> op, VOPProfile P> : VOP3a_si <op, P> { 204 bits<8> vdst; 205 let Inst{7-0} = !if(P.EmitDst, vdst{7-0}, 0); 206} 207 208class VOP3e_vi <bits<10> op, VOPProfile P> : VOP3a_vi <op, P> { 209 bits<8> vdst; 210 let Inst{7-0} = !if(P.EmitDst, vdst{7-0}, 0); 211} 212 213class VOP3OpSel_gfx9 <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> { 214 let Inst{11} = !if(P.HasSrc0, src0_modifiers{2}, 0); 215 let Inst{12} = !if(P.HasSrc1, src1_modifiers{2}, 0); 216 let Inst{13} = !if(P.HasSrc2, src2_modifiers{2}, 0); 217 let Inst{14} = !if(P.HasDst, src0_modifiers{3}, 0); 218} 219 220// NB: For V_INTERP* opcodes, src0 is encoded as src1 and vice versa 221class VOP3Interp_vi <bits<10> op, VOPProfile P> : VOP3e_vi <op, P> { 222 bits<2> attrchan; 223 bits<6> attr; 224 bits<1> high; 225 226 let Inst{8} = 0; // No modifiers for src0 227 let Inst{61} = 0; 228 229 let Inst{9} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); 230 let Inst{62} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 231 232 let Inst{37-32} = attr; 233 let Inst{39-38} = attrchan; 234 let Inst{40} = !if(P.HasHigh, high, 0); 235 236 let Inst{49-41} = src0; 237} 238 239class VOP3be <VOPProfile P> : Enc64 { 240 bits<8> vdst; 241 bits<2> src0_modifiers; 242 bits<9> src0; 243 bits<2> src1_modifiers; 244 bits<9> src1; 245 bits<2> src2_modifiers; 246 bits<9> src2; 247 bits<7> sdst; 248 bits<2> omod; 249 250 let Inst{7-0} = vdst; 251 let Inst{14-8} = sdst; 252 let Inst{31-26} = 0x34; //encoding 253 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 254 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 255 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 256 let Inst{60-59} = !if(P.HasOMod, omod, 0); 257 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); 258 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); 259 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); 260} 261 262class VOP3Pe <bits<10> op, VOPProfile P> : Enc64 { 263 bits<8> vdst; 264 // neg, neg_hi, op_sel put in srcN_modifiers 265 bits<4> src0_modifiers; 266 bits<9> src0; 267 bits<4> src1_modifiers; 268 bits<9> src1; 269 bits<4> src2_modifiers; 270 bits<9> src2; 271 bits<1> clamp; 272 273 let Inst{7-0} = vdst; 274 let Inst{8} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // neg_hi src0 275 let Inst{9} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // neg_hi src1 276 let Inst{10} = !if(P.HasSrc2Mods, src2_modifiers{1}, 0); // neg_hi src2 277 278 let Inst{11} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{2}, 0); // op_sel(0) 279 let Inst{12} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{2}, 0); // op_sel(1) 280 let Inst{13} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{2}, 0); // op_sel(2) 281 282 let Inst{14} = !if(!and(P.HasSrc2, P.HasOpSel), src2_modifiers{3}, 0); // op_sel_hi(2) 283 284 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 285 286 let Inst{25-16} = op; 287 let Inst{31-26} = 0x34; //encoding 288 let Inst{40-32} = !if(P.HasSrc0, src0, 0); 289 let Inst{49-41} = !if(P.HasSrc1, src1, 0); 290 let Inst{58-50} = !if(P.HasSrc2, src2, 0); 291 let Inst{59} = !if(!and(P.HasSrc0, P.HasOpSel), src0_modifiers{3}, 0); // op_sel_hi(0) 292 let Inst{60} = !if(!and(P.HasSrc1, P.HasOpSel), src1_modifiers{3}, 0); // op_sel_hi(1) 293 let Inst{61} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // neg (lo) 294 let Inst{62} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // neg (lo) 295 let Inst{63} = !if(P.HasSrc2Mods, src2_modifiers{0}, 0); // neg (lo) 296} 297 298class VOP3be_si <bits<9> op, VOPProfile P> : VOP3be<P> { 299 let Inst{25-17} = op; 300} 301 302class VOP3be_vi <bits<10> op, VOPProfile P> : VOP3be<P> { 303 bits<1> clamp; 304 let Inst{25-16} = op; 305 let Inst{15} = !if(P.HasClamp, clamp{0}, 0); 306} 307 308def SDWA { 309 // sdwa_sel 310 int BYTE_0 = 0; 311 int BYTE_1 = 1; 312 int BYTE_2 = 2; 313 int BYTE_3 = 3; 314 int WORD_0 = 4; 315 int WORD_1 = 5; 316 int DWORD = 6; 317 318 // dst_unused 319 int UNUSED_PAD = 0; 320 int UNUSED_SEXT = 1; 321 int UNUSED_PRESERVE = 2; 322} 323 324class VOP_SDWAe<VOPProfile P> : Enc64 { 325 bits<8> src0; 326 bits<3> src0_sel; 327 bits<2> src0_modifiers; // float: {abs,neg}, int {sext} 328 bits<3> src1_sel; 329 bits<2> src1_modifiers; 330 bits<3> dst_sel; 331 bits<2> dst_unused; 332 bits<1> clamp; 333 334 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 335 let Inst{42-40} = !if(P.EmitDst, dst_sel{2-0}, 0); 336 let Inst{44-43} = !if(P.EmitDst, dst_unused{1-0}, 0); 337 let Inst{45} = !if(P.HasSDWAClamp, clamp{0}, 0); 338 let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0); 339 let Inst{51} = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0); 340 let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0); 341 let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0); 342 let Inst{59} = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0); 343 let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0); 344} 345 346// GFX9 adds two features to SDWA: 347// 1. Add 3 fields to the SDWA microcode word: S0, S1 and OMOD. 348// a. S0 and S1 indicate that source 0 and 1 respectively are SGPRs rather 349// than VGPRs (at most 1 can be an SGPR); 350// b. OMOD is the standard output modifier (result *2, *4, /2) 351// 2. Add a new version of the SDWA microcode word for VOPC: SDWAB. This 352// replaces OMOD and the dest fields with SD and SDST (SGPR destination) 353// field. 354// a. When SD=1, the SDST is used as the destination for the compare result; 355// b. When SD=0, VCC is used. 356// 357// In GFX9, V_MAC_F16, V_MAC_F32 opcodes cannot be used with SDWA 358 359// gfx9 SDWA basic encoding 360class VOP_SDWA9e<VOPProfile P> : Enc64 { 361 bits<9> src0; // {src0_sgpr{0}, src0{7-0}} 362 bits<3> src0_sel; 363 bits<2> src0_modifiers; // float: {abs,neg}, int {sext} 364 bits<3> src1_sel; 365 bits<2> src1_modifiers; 366 bits<1> src1_sgpr; 367 368 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 369 let Inst{50-48} = !if(P.HasSrc0, src0_sel{2-0}, 0); 370 let Inst{51} = !if(P.HasSrc0IntMods, src0_modifiers{0}, 0); 371 let Inst{53-52} = !if(P.HasSrc0FloatMods, src0_modifiers{1-0}, 0); 372 let Inst{55} = !if(P.HasSrc0, src0{8}, 0); 373 let Inst{58-56} = !if(P.HasSrc1, src1_sel{2-0}, 0); 374 let Inst{59} = !if(P.HasSrc1IntMods, src1_modifiers{0}, 0); 375 let Inst{61-60} = !if(P.HasSrc1FloatMods, src1_modifiers{1-0}, 0); 376 let Inst{63} = 0; // src1_sgpr - should be specified in subclass 377} 378 379// gfx9 SDWA-A 380class VOP_SDWA9Ae<VOPProfile P> : VOP_SDWA9e<P> { 381 bits<3> dst_sel; 382 bits<2> dst_unused; 383 bits<1> clamp; 384 bits<2> omod; 385 386 let Inst{42-40} = !if(P.EmitDst, dst_sel{2-0}, 0); 387 let Inst{44-43} = !if(P.EmitDst, dst_unused{1-0}, 0); 388 let Inst{45} = !if(P.HasSDWAClamp, clamp{0}, 0); 389 let Inst{47-46} = !if(P.HasSDWAOMod, omod{1-0}, 0); 390} 391 392// gfx9 SDWA-B 393class VOP_SDWA9Be<VOPProfile P> : VOP_SDWA9e<P> { 394 bits<8> sdst; // {vcc_sdst{0}, sdst{6-0}} 395 396 let Inst{46-40} = !if(P.EmitDst, sdst{6-0}, 0); 397 let Inst{47} = !if(P.EmitDst, sdst{7}, 0); 398} 399 400class VOP_SDWA_Pseudo <string opName, VOPProfile P, list<dag> pattern=[]> : 401 InstSI <P.OutsSDWA, P.InsSDWA, "", pattern>, 402 VOP <opName>, 403 SIMCInstr <opName#"_sdwa", SIEncodingFamily.NONE>, 404 MnemonicAlias <opName#"_sdwa", opName> { 405 406 let isPseudo = 1; 407 let isCodeGenOnly = 1; 408 let UseNamedOperandTable = 1; 409 410 string Mnemonic = opName; 411 string AsmOperands = P.AsmSDWA; 412 string AsmOperands9 = P.AsmSDWA9; 413 414 let Size = 8; 415 let mayLoad = 0; 416 let mayStore = 0; 417 let hasSideEffects = 0; 418 419 let VALU = 1; 420 let SDWA = 1; 421 let Uses = [EXEC]; 422 423 let SubtargetPredicate = !if(P.HasExt, HasSDWA, DisableInst); 424 let AssemblerPredicate = !if(P.HasExt, HasSDWA, DisableInst); 425 let AsmVariantName = !if(P.HasExt, AMDGPUAsmVariants.SDWA, 426 AMDGPUAsmVariants.Disable); 427 let DecoderNamespace = "SDWA"; 428 429 VOPProfile Pfl = P; 430} 431 432class VOP_SDWA_Real <VOP_SDWA_Pseudo ps> : 433 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands, []>, 434 SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA> { 435 436 let isPseudo = 0; 437 let isCodeGenOnly = 0; 438 439 let Defs = ps.Defs; 440 let Uses = ps.Uses; 441 let SchedRW = ps.SchedRW; 442 let hasSideEffects = ps.hasSideEffects; 443 444 let Constraints = ps.Constraints; 445 let DisableEncoding = ps.DisableEncoding; 446 447 // Copy relevant pseudo op flags 448 let SubtargetPredicate = ps.SubtargetPredicate; 449 let AssemblerPredicate = ps.AssemblerPredicate; 450 let AsmMatchConverter = ps.AsmMatchConverter; 451 let AsmVariantName = ps.AsmVariantName; 452 let UseNamedOperandTable = ps.UseNamedOperandTable; 453 let DecoderNamespace = ps.DecoderNamespace; 454 let Constraints = ps.Constraints; 455 let DisableEncoding = ps.DisableEncoding; 456 let TSFlags = ps.TSFlags; 457} 458 459class VOP_SDWA9_Real <VOP_SDWA_Pseudo ps> : 460 InstSI <ps.OutOperandList, ps.InOperandList, ps.Mnemonic # ps.AsmOperands9, []>, 461 SIMCInstr <ps.PseudoInstr, SIEncodingFamily.SDWA9> { 462 463 let isPseudo = 0; 464 let isCodeGenOnly = 0; 465 466 let Defs = ps.Defs; 467 let Uses = ps.Uses; 468 let SchedRW = ps.SchedRW; 469 let hasSideEffects = ps.hasSideEffects; 470 471 let Constraints = ps.Constraints; 472 let DisableEncoding = ps.DisableEncoding; 473 474 let SubtargetPredicate = !if(ps.Pfl.HasSDWA9, HasSDWA9, DisableInst); 475 let AssemblerPredicate = !if(ps.Pfl.HasSDWA9, HasSDWA9, DisableInst); 476 let AsmVariantName = !if(ps.Pfl.HasSDWA9, AMDGPUAsmVariants.SDWA9, 477 AMDGPUAsmVariants.Disable); 478 let DecoderNamespace = "SDWA9"; 479 480 // Copy relevant pseudo op flags 481 let AsmMatchConverter = ps.AsmMatchConverter; 482 let UseNamedOperandTable = ps.UseNamedOperandTable; 483 let Constraints = ps.Constraints; 484 let DisableEncoding = ps.DisableEncoding; 485 let TSFlags = ps.TSFlags; 486} 487 488class VOP_DPPe<VOPProfile P> : Enc64 { 489 bits<2> src0_modifiers; 490 bits<8> src0; 491 bits<2> src1_modifiers; 492 bits<9> dpp_ctrl; 493 bits<1> bound_ctrl; 494 bits<4> bank_mask; 495 bits<4> row_mask; 496 497 let Inst{39-32} = !if(P.HasSrc0, src0{7-0}, 0); 498 let Inst{48-40} = dpp_ctrl; 499 let Inst{51} = bound_ctrl; 500 let Inst{52} = !if(P.HasSrc0Mods, src0_modifiers{0}, 0); // src0_neg 501 let Inst{53} = !if(P.HasSrc0Mods, src0_modifiers{1}, 0); // src0_abs 502 let Inst{54} = !if(P.HasSrc1Mods, src1_modifiers{0}, 0); // src1_neg 503 let Inst{55} = !if(P.HasSrc1Mods, src1_modifiers{1}, 0); // src1_abs 504 let Inst{59-56} = bank_mask; 505 let Inst{63-60} = row_mask; 506} 507 508class VOP_DPP <string OpName, VOPProfile P> : 509 InstSI <P.OutsDPP, P.InsDPP, OpName#P.AsmDPP, []>, 510 VOP_DPPe<P> { 511 512 let mayLoad = 0; 513 let mayStore = 0; 514 let hasSideEffects = 0; 515 let UseNamedOperandTable = 1; 516 517 let VALU = 1; 518 let DPP = 1; 519 let Size = 8; 520 521 let AsmMatchConverter = !if(!eq(P.HasModifiers,1), "cvtDPP", ""); 522 let SubtargetPredicate = HasDPP; 523 let AssemblerPredicate = !if(P.HasExt, HasDPP, DisableInst); 524 let AsmVariantName = !if(P.HasExt, AMDGPUAsmVariants.DPP, 525 AMDGPUAsmVariants.Disable); 526 let Constraints = !if(P.NumSrcArgs, "$old = $vdst", ""); 527 let DisableEncoding = !if(P.NumSrcArgs, "$old", ""); 528 let DecoderNamespace = "DPP"; 529} 530 531include "VOPCInstructions.td" 532include "VOP1Instructions.td" 533include "VOP2Instructions.td" 534include "VOP3Instructions.td" 535include "VOP3PInstructions.td" 536