1//===-- SIInstructions.td - SI Instruction Defintions ---------------------===// 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// This file was originally auto-generated from a GPU register header file and 9// all the instruction definitions were originally commented out. Instructions 10// that are not yet supported remain commented out. 11//===----------------------------------------------------------------------===// 12 13class GCNPat<dag pattern, dag result> : Pat<pattern, result>, GCNPredicateControl { 14 15} 16 17include "SOPInstructions.td" 18include "VOPInstructions.td" 19include "SMInstructions.td" 20include "FLATInstructions.td" 21include "BUFInstructions.td" 22 23//===----------------------------------------------------------------------===// 24// EXP Instructions 25//===----------------------------------------------------------------------===// 26 27defm EXP : EXP_m<0>; 28defm EXP_DONE : EXP_m<1>; 29 30// FIXME: GlobalISel successfully imports this pattern, but fails to 31// select because the i1 done_val does a type check on done_val, which 32// only works on register operands. 33class ExpPattern<ValueType vt, Instruction Inst, int done_val> : GCNPat< 34 (int_amdgcn_exp timm:$tgt, timm:$en, 35 (vt ExpSrc0:$src0), (vt ExpSrc1:$src1), 36 (vt ExpSrc2:$src2), (vt ExpSrc3:$src3), 37 done_val, timm:$vm), 38 (Inst timm:$tgt, ExpSrc0:$src0, ExpSrc1:$src1, 39 ExpSrc2:$src2, ExpSrc3:$src3, timm:$vm, 0, timm:$en) 40>; 41 42class ExpComprPattern<ValueType vt, Instruction Inst, int done_val> : GCNPat< 43 (int_amdgcn_exp_compr timm:$tgt, timm:$en, 44 (vt ExpSrc0:$src0), (vt ExpSrc1:$src1), 45 done_val, timm:$vm), 46 (Inst timm:$tgt, ExpSrc0:$src0, ExpSrc1:$src1, 47 (IMPLICIT_DEF), (IMPLICIT_DEF), timm:$vm, 1, timm:$en) 48>; 49 50// FIXME: The generated DAG matcher seems to have strange behavior 51// with a 1-bit literal to match, so use a -1 for checking a true 52// 1-bit value. 53def : ExpPattern<i32, EXP, 0>; 54def : ExpPattern<i32, EXP_DONE, -1>; 55def : ExpPattern<f32, EXP, 0>; 56def : ExpPattern<f32, EXP_DONE, -1>; 57 58def : ExpComprPattern<v2i16, EXP, 0>; 59def : ExpComprPattern<v2i16, EXP_DONE, -1>; 60def : ExpComprPattern<v2f16, EXP, 0>; 61def : ExpComprPattern<v2f16, EXP_DONE, -1>; 62 63//===----------------------------------------------------------------------===// 64// VINTRP Instructions 65//===----------------------------------------------------------------------===// 66 67// Used to inject printing of "_e32" suffix for VI (there are "_e64" variants for VI) 68def VINTRPDst : VINTRPDstOperand <VGPR_32>; 69 70let Uses = [M0, EXEC] in { 71 72// FIXME: Specify SchedRW for VINTRP insturctions. 73 74multiclass V_INTERP_P1_F32_m : VINTRP_m < 75 0x00000000, 76 (outs VINTRPDst:$vdst), 77 (ins VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 78 "v_interp_p1_f32$vdst, $vsrc, $attr$attrchan", 79 [(set f32:$vdst, (int_amdgcn_interp_p1 f32:$vsrc, 80 (i32 timm:$attrchan), (i32 timm:$attr), M0))] 81>; 82 83let OtherPredicates = [has32BankLDS] in { 84 85defm V_INTERP_P1_F32 : V_INTERP_P1_F32_m; 86 87} // End OtherPredicates = [has32BankLDS] 88 89let OtherPredicates = [has16BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 in { 90 91defm V_INTERP_P1_F32_16bank : V_INTERP_P1_F32_m; 92 93} // End OtherPredicates = [has32BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 94 95let DisableEncoding = "$src0", Constraints = "$src0 = $vdst" in { 96 97defm V_INTERP_P2_F32 : VINTRP_m < 98 0x00000001, 99 (outs VINTRPDst:$vdst), 100 (ins VGPR_32:$src0, VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 101 "v_interp_p2_f32$vdst, $vsrc, $attr$attrchan", 102 [(set f32:$vdst, (int_amdgcn_interp_p2 f32:$src0, f32:$vsrc, 103 (i32 timm:$attrchan), (i32 timm:$attr), M0))]>; 104 105} // End DisableEncoding = "$src0", Constraints = "$src0 = $vdst" 106 107defm V_INTERP_MOV_F32 : VINTRP_m < 108 0x00000002, 109 (outs VINTRPDst:$vdst), 110 (ins InterpSlot:$vsrc, Attr:$attr, AttrChan:$attrchan), 111 "v_interp_mov_f32$vdst, $vsrc, $attr$attrchan", 112 [(set f32:$vdst, (int_amdgcn_interp_mov (i32 timm:$vsrc), 113 (i32 timm:$attrchan), (i32 timm:$attr), M0))]>; 114 115} // End Uses = [M0, EXEC] 116 117//===----------------------------------------------------------------------===// 118// Pseudo Instructions 119//===----------------------------------------------------------------------===// 120def ATOMIC_FENCE : SPseudoInstSI< 121 (outs), (ins i32imm:$ordering, i32imm:$scope), 122 [(atomic_fence (i32 timm:$ordering), (i32 timm:$scope))], 123 "ATOMIC_FENCE $ordering, $scope"> { 124 let hasSideEffects = 1; 125 let maybeAtomic = 1; 126} 127 128def VOP_I64_I64_DPP : VOPProfile <[i64, i64, untyped, untyped]> { 129 let HasExt = 1; 130 let HasExtDPP = 1; 131} 132 133let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] in { 134 135// For use in patterns 136def V_CNDMASK_B64_PSEUDO : VOP3Common <(outs VReg_64:$vdst), 137 (ins VSrc_b64:$src0, VSrc_b64:$src1, SSrc_b64:$src2), "", []> { 138 let isPseudo = 1; 139 let isCodeGenOnly = 1; 140 let usesCustomInserter = 1; 141} 142 143// 64-bit vector move instruction. This is mainly used by the 144// SIFoldOperands pass to enable folding of inline immediates. 145def V_MOV_B64_PSEUDO : VPseudoInstSI <(outs VReg_64:$vdst), 146 (ins VSrc_b64:$src0)>; 147 148// 64-bit vector move with dpp. Expanded post-RA. 149def V_MOV_B64_DPP_PSEUDO : VOP_DPP_Pseudo <"v_mov_b64_dpp", VOP_I64_I64_DPP> { 150 let Size = 16; // Requires two 8-byte v_mov_b32_dpp to complete. 151} 152 153// Pseudoinstruction for @llvm.amdgcn.wqm. It is turned into a copy after the 154// WQM pass processes it. 155def WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>; 156 157// Pseudoinstruction for @llvm.amdgcn.softwqm. Like @llvm.amdgcn.wqm it is 158// turned into a copy by WQM pass, but does not seed WQM requirements. 159def SOFT_WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>; 160 161// Pseudoinstruction for @llvm.amdgcn.wwm. It is turned into a copy post-RA, so 162// that the @earlyclobber is respected. The @earlyclobber is to make sure that 163// the instruction that defines $src0 (which is run in WWM) doesn't 164// accidentally clobber inactive channels of $vdst. 165let Constraints = "@earlyclobber $vdst" in { 166def WWM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>; 167} 168 169} // End let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] 170 171def ENTER_WWM : SPseudoInstSI <(outs SReg_1:$sdst), (ins i64imm:$src0)> { 172 let Defs = [EXEC]; 173 let hasSideEffects = 0; 174 let mayLoad = 0; 175 let mayStore = 0; 176} 177 178def EXIT_WWM : SPseudoInstSI <(outs SReg_1:$sdst), (ins SReg_1:$src0)> { 179 let hasSideEffects = 0; 180 let mayLoad = 0; 181 let mayStore = 0; 182} 183 184// Invert the exec mask and overwrite the inactive lanes of dst with inactive, 185// restoring it after we're done. 186def V_SET_INACTIVE_B32 : VPseudoInstSI <(outs VGPR_32:$vdst), 187 (ins VGPR_32: $src, VSrc_b32:$inactive), 188 [(set i32:$vdst, (int_amdgcn_set_inactive i32:$src, i32:$inactive))]> { 189 let Constraints = "$src = $vdst"; 190} 191 192def V_SET_INACTIVE_B64 : VPseudoInstSI <(outs VReg_64:$vdst), 193 (ins VReg_64: $src, VSrc_b64:$inactive), 194 [(set i64:$vdst, (int_amdgcn_set_inactive i64:$src, i64:$inactive))]> { 195 let Constraints = "$src = $vdst"; 196} 197 198 199let usesCustomInserter = 1, Defs = [SCC] in { 200def S_ADD_U64_PSEUDO : SPseudoInstSI < 201 (outs SReg_64:$vdst), (ins SSrc_b64:$src0, SSrc_b64:$src1), 202 [(set SReg_64:$vdst, (add i64:$src0, i64:$src1))] 203>; 204 205def S_SUB_U64_PSEUDO : SPseudoInstSI < 206 (outs SReg_64:$vdst), (ins SSrc_b64:$src0, SSrc_b64:$src1), 207 [(set SReg_64:$vdst, (sub i64:$src0, i64:$src1))] 208>; 209 210def S_ADD_U64_CO_PSEUDO : SPseudoInstSI < 211 (outs SReg_64:$vdst, VOPDstS64orS32:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1) 212>; 213 214def S_SUB_U64_CO_PSEUDO : SPseudoInstSI < 215 (outs SReg_64:$vdst, VOPDstS64orS32:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1) 216>; 217} // End usesCustomInserter = 1, Defs = [SCC] 218 219let usesCustomInserter = 1 in { 220def GET_GROUPSTATICSIZE : SPseudoInstSI <(outs SReg_32:$sdst), (ins), 221 [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>; 222} // End let usesCustomInserter = 1, SALU = 1 223 224// Wrap an instruction by duplicating it, except for setting isTerminator. 225class WrapTerminatorInst<SOP_Pseudo base_inst> : SPseudoInstSI< 226 base_inst.OutOperandList, 227 base_inst.InOperandList> { 228 let Uses = base_inst.Uses; 229 let Defs = base_inst.Defs; 230 let isTerminator = 1; 231 let isAsCheapAsAMove = base_inst.isAsCheapAsAMove; 232 let hasSideEffects = base_inst.hasSideEffects; 233 let UseNamedOperandTable = base_inst.UseNamedOperandTable; 234 let CodeSize = base_inst.CodeSize; 235} 236 237let WaveSizePredicate = isWave64 in { 238def S_MOV_B64_term : WrapTerminatorInst<S_MOV_B64>; 239def S_XOR_B64_term : WrapTerminatorInst<S_XOR_B64>; 240def S_ANDN2_B64_term : WrapTerminatorInst<S_ANDN2_B64>; 241} 242 243let WaveSizePredicate = isWave32 in { 244def S_MOV_B32_term : WrapTerminatorInst<S_MOV_B32>; 245def S_XOR_B32_term : WrapTerminatorInst<S_XOR_B32>; 246def S_OR_B32_term : WrapTerminatorInst<S_OR_B32>; 247def S_ANDN2_B32_term : WrapTerminatorInst<S_ANDN2_B32>; 248} 249 250def WAVE_BARRIER : SPseudoInstSI<(outs), (ins), 251 [(int_amdgcn_wave_barrier)]> { 252 let SchedRW = []; 253 let hasNoSchedulingInfo = 1; 254 let hasSideEffects = 1; 255 let mayLoad = 1; 256 let mayStore = 1; 257 let isConvergent = 1; 258 let FixedSize = 1; 259 let Size = 0; 260} 261 262// SI pseudo instructions. These are used by the CFG structurizer pass 263// and should be lowered to ISA instructions prior to codegen. 264 265// Dummy terminator instruction to use after control flow instructions 266// replaced with exec mask operations. 267def SI_MASK_BRANCH : VPseudoInstSI < 268 (outs), (ins brtarget:$target)> { 269 let isBranch = 0; 270 let isTerminator = 1; 271 let isBarrier = 0; 272 let SchedRW = []; 273 let hasNoSchedulingInfo = 1; 274 let FixedSize = 1; 275 let Size = 0; 276} 277 278let isTerminator = 1 in { 279 280let OtherPredicates = [EnableLateCFGStructurize] in { 281 def SI_NON_UNIFORM_BRCOND_PSEUDO : CFPseudoInstSI < 282 (outs), 283 (ins SReg_1:$vcc, brtarget:$target), 284 [(brcond i1:$vcc, bb:$target)]> { 285 let Size = 12; 286} 287} 288 289def SI_IF: CFPseudoInstSI < 290 (outs SReg_1:$dst), (ins SReg_1:$vcc, brtarget:$target), 291 [(set i1:$dst, (AMDGPUif i1:$vcc, bb:$target))], 1, 1> { 292 let Constraints = ""; 293 let Size = 12; 294 let hasSideEffects = 1; 295} 296 297def SI_ELSE : CFPseudoInstSI < 298 (outs SReg_1:$dst), 299 (ins SReg_1:$src, brtarget:$target, i1imm:$execfix), [], 1, 1> { 300 let Size = 12; 301 let hasSideEffects = 1; 302} 303 304def SI_LOOP : CFPseudoInstSI < 305 (outs), (ins SReg_1:$saved, brtarget:$target), 306 [(AMDGPUloop i1:$saved, bb:$target)], 1, 1> { 307 let Size = 8; 308 let isBranch = 1; 309 let hasSideEffects = 1; 310} 311 312} // End isTerminator = 1 313 314def SI_END_CF : CFPseudoInstSI < 315 (outs), (ins SReg_1:$saved), [], 1, 1> { 316 let Size = 4; 317 let isAsCheapAsAMove = 1; 318 let isReMaterializable = 1; 319 let hasSideEffects = 1; 320 let mayLoad = 1; // FIXME: Should not need memory flags 321 let mayStore = 1; 322} 323 324def SI_IF_BREAK : CFPseudoInstSI < 325 (outs SReg_1:$dst), (ins SReg_1:$vcc, SReg_1:$src), []> { 326 let Size = 4; 327 let isAsCheapAsAMove = 1; 328 let isReMaterializable = 1; 329} 330 331let Uses = [EXEC] in { 332 333multiclass PseudoInstKill <dag ins> { 334 // Even though this pseudo can usually be expanded without an SCC def, we 335 // conservatively assume that it has an SCC def, both because it is sometimes 336 // required in degenerate cases (when V_CMPX cannot be used due to constant 337 // bus limitations) and because it allows us to avoid having to track SCC 338 // liveness across basic blocks. 339 let Defs = [EXEC,VCC,SCC] in 340 def _PSEUDO : PseudoInstSI <(outs), ins> { 341 let isConvergent = 1; 342 let usesCustomInserter = 1; 343 } 344 345 let Defs = [EXEC,VCC,SCC] in 346 def _TERMINATOR : SPseudoInstSI <(outs), ins> { 347 let isTerminator = 1; 348 } 349} 350 351defm SI_KILL_I1 : PseudoInstKill <(ins SCSrc_i1:$src, i1imm:$killvalue)>; 352defm SI_KILL_F32_COND_IMM : PseudoInstKill <(ins VSrc_b32:$src0, i32imm:$src1, i32imm:$cond)>; 353 354let Defs = [EXEC,VCC] in 355def SI_ILLEGAL_COPY : SPseudoInstSI < 356 (outs unknown:$dst), (ins unknown:$src), 357 [], " ; illegal copy $src to $dst">; 358 359} // End Uses = [EXEC], Defs = [EXEC,VCC] 360 361// Branch on undef scc. Used to avoid intermediate copy from 362// IMPLICIT_DEF to SCC. 363def SI_BR_UNDEF : SPseudoInstSI <(outs), (ins sopp_brtarget:$simm16)> { 364 let isTerminator = 1; 365 let usesCustomInserter = 1; 366 let isBranch = 1; 367} 368 369def SI_PS_LIVE : PseudoInstSI < 370 (outs SReg_1:$dst), (ins), 371 [(set i1:$dst, (int_amdgcn_ps_live))]> { 372 let SALU = 1; 373} 374 375def SI_MASKED_UNREACHABLE : SPseudoInstSI <(outs), (ins), 376 [(int_amdgcn_unreachable)], 377 "; divergent unreachable"> { 378 let Size = 0; 379 let hasNoSchedulingInfo = 1; 380 let FixedSize = 1; 381} 382 383// Used as an isel pseudo to directly emit initialization with an 384// s_mov_b32 rather than a copy of another initialized 385// register. MachineCSE skips copies, and we don't want to have to 386// fold operands before it runs. 387def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> { 388 let Defs = [M0]; 389 let usesCustomInserter = 1; 390 let isAsCheapAsAMove = 1; 391 let isReMaterializable = 1; 392} 393 394def SI_INIT_EXEC : SPseudoInstSI < 395 (outs), (ins i64imm:$src), 396 [(int_amdgcn_init_exec (i64 timm:$src))]> { 397 let Defs = [EXEC]; 398 let usesCustomInserter = 1; 399 let isAsCheapAsAMove = 1; 400 let WaveSizePredicate = isWave64; 401} 402 403// FIXME: Intrinsic should be mangled for wave size. 404def SI_INIT_EXEC_LO : SPseudoInstSI < 405 (outs), (ins i32imm:$src), []> { 406 let Defs = [EXEC_LO]; 407 let usesCustomInserter = 1; 408 let isAsCheapAsAMove = 1; 409 let WaveSizePredicate = isWave32; 410} 411 412// FIXME: Wave32 version 413def SI_INIT_EXEC_FROM_INPUT : SPseudoInstSI < 414 (outs), (ins SSrc_b32:$input, i32imm:$shift), 415 [(int_amdgcn_init_exec_from_input i32:$input, (i32 timm:$shift))]> { 416 let Defs = [EXEC]; 417 let usesCustomInserter = 1; 418} 419 420def : GCNPat < 421 (int_amdgcn_init_exec timm:$src), 422 (SI_INIT_EXEC_LO (as_i32imm imm:$src))> { 423 let WaveSizePredicate = isWave32; 424} 425 426// Return for returning shaders to a shader variant epilog. 427def SI_RETURN_TO_EPILOG : SPseudoInstSI < 428 (outs), (ins variable_ops), [(AMDGPUreturn_to_epilog)]> { 429 let isTerminator = 1; 430 let isBarrier = 1; 431 let isReturn = 1; 432 let hasNoSchedulingInfo = 1; 433 let DisableWQM = 1; 434 let FixedSize = 1; 435} 436 437// Return for returning function calls. 438def SI_RETURN : SPseudoInstSI < 439 (outs), (ins), [], 440 "; return"> { 441 let isTerminator = 1; 442 let isBarrier = 1; 443 let isReturn = 1; 444 let SchedRW = [WriteBranch]; 445} 446 447// Return for returning function calls without output register. 448// 449// This version is only needed so we can fill in the output regiter in 450// the custom inserter. 451def SI_CALL_ISEL : SPseudoInstSI < 452 (outs), (ins SSrc_b64:$src0, unknown:$callee), 453 [(AMDGPUcall i64:$src0, tglobaladdr:$callee)]> { 454 let Size = 4; 455 let isCall = 1; 456 let SchedRW = [WriteBranch]; 457 let usesCustomInserter = 1; 458 // TODO: Should really base this on the call target 459 let isConvergent = 1; 460} 461 462// Wrapper around s_swappc_b64 with extra $callee parameter to track 463// the called function after regalloc. 464def SI_CALL : SPseudoInstSI < 465 (outs SReg_64:$dst), (ins SSrc_b64:$src0, unknown:$callee)> { 466 let Size = 4; 467 let isCall = 1; 468 let UseNamedOperandTable = 1; 469 let SchedRW = [WriteBranch]; 470 // TODO: Should really base this on the call target 471 let isConvergent = 1; 472} 473 474// Tail call handling pseudo 475def SI_TCRETURN : SPseudoInstSI <(outs), 476 (ins SSrc_b64:$src0, unknown:$callee, i32imm:$fpdiff), 477 [(AMDGPUtc_return i64:$src0, tglobaladdr:$callee, i32:$fpdiff)]> { 478 let Size = 4; 479 let isCall = 1; 480 let isTerminator = 1; 481 let isReturn = 1; 482 let isBarrier = 1; 483 let UseNamedOperandTable = 1; 484 let SchedRW = [WriteBranch]; 485 // TODO: Should really base this on the call target 486 let isConvergent = 1; 487} 488 489 490def ADJCALLSTACKUP : SPseudoInstSI< 491 (outs), (ins i32imm:$amt0, i32imm:$amt1), 492 [(callseq_start timm:$amt0, timm:$amt1)], 493 "; adjcallstackup $amt0 $amt1"> { 494 let Size = 8; // Worst case. (s_add_u32 + constant) 495 let FixedSize = 1; 496 let hasSideEffects = 1; 497 let usesCustomInserter = 1; 498 let SchedRW = [WriteSALU]; 499 let Defs = [SCC]; 500} 501 502def ADJCALLSTACKDOWN : SPseudoInstSI< 503 (outs), (ins i32imm:$amt1, i32imm:$amt2), 504 [(callseq_end timm:$amt1, timm:$amt2)], 505 "; adjcallstackdown $amt1"> { 506 let Size = 8; // Worst case. (s_add_u32 + constant) 507 let hasSideEffects = 1; 508 let usesCustomInserter = 1; 509 let SchedRW = [WriteSALU]; 510 let Defs = [SCC]; 511} 512 513let Defs = [M0, EXEC, SCC], 514 UseNamedOperandTable = 1 in { 515 516// SI_INDIRECT_SRC/DST are only used by legacy SelectionDAG indirect 517// addressing implementation. 518class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI < 519 (outs VGPR_32:$vdst), 520 (ins rc:$src, VS_32:$idx, i32imm:$offset)> { 521 let usesCustomInserter = 1; 522} 523 524class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI < 525 (outs rc:$vdst), 526 (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> { 527 let Constraints = "$src = $vdst"; 528 let usesCustomInserter = 1; 529} 530 531def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>; 532def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>; 533def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>; 534def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>; 535def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>; 536 537def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>; 538def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>; 539def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>; 540def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>; 541def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>; 542 543} // End Uses = [EXEC], Defs = [M0, EXEC] 544 545 546// This is a pseudo variant of the v_movreld_b32 (or v_mov_b32 547// expecting to be executed with gpr indexing mode enabled) 548// instruction in which the vector operand appears only twice, once as 549// def and once as use. Using this pseudo avoids problems with the Two 550// Address instructions pass. 551class INDIRECT_REG_WRITE_pseudo<RegisterClass rc, 552 RegisterOperand val_ty> : PseudoInstSI < 553 (outs rc:$vdst), (ins rc:$vsrc, val_ty:$val, i32imm:$subreg)> { 554 let Constraints = "$vsrc = $vdst"; 555 let Uses = [M0]; 556} 557 558class V_INDIRECT_REG_WRITE_B32_pseudo<RegisterClass rc> : 559 INDIRECT_REG_WRITE_pseudo<rc, VSrc_b32> { 560 let VALU = 1; 561 let VOP1 = 1; 562 let Uses = [M0, EXEC]; 563} 564 565class S_INDIRECT_REG_WRITE_pseudo<RegisterClass rc, 566 RegisterOperand val_ty> : 567 INDIRECT_REG_WRITE_pseudo<rc, val_ty> { 568 let SALU = 1; 569 let SOP1 = 1; 570 let Uses = [M0]; 571} 572 573class S_INDIRECT_REG_WRITE_B32_pseudo<RegisterClass rc> : 574 S_INDIRECT_REG_WRITE_pseudo<rc, SSrc_b32>; 575class S_INDIRECT_REG_WRITE_B64_pseudo<RegisterClass rc> : 576 S_INDIRECT_REG_WRITE_pseudo<rc, SSrc_b64>; 577 578 579def V_INDIRECT_REG_WRITE_B32_V1 : V_INDIRECT_REG_WRITE_B32_pseudo<VGPR_32>; 580def V_INDIRECT_REG_WRITE_B32_V2 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_64>; 581def V_INDIRECT_REG_WRITE_B32_V3 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_96>; 582def V_INDIRECT_REG_WRITE_B32_V4 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_128>; 583def V_INDIRECT_REG_WRITE_B32_V5 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_160>; 584def V_INDIRECT_REG_WRITE_B32_V8 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_256>; 585def V_INDIRECT_REG_WRITE_B32_V16 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_512>; 586def V_INDIRECT_REG_WRITE_B32_V32 : V_INDIRECT_REG_WRITE_B32_pseudo<VReg_1024>; 587 588def S_INDIRECT_REG_WRITE_B32_V1 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_32>; 589def S_INDIRECT_REG_WRITE_B32_V2 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_64>; 590def S_INDIRECT_REG_WRITE_B32_V3 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_96>; 591def S_INDIRECT_REG_WRITE_B32_V4 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_128>; 592def S_INDIRECT_REG_WRITE_B32_V5 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_160>; 593def S_INDIRECT_REG_WRITE_B32_V8 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_256>; 594def S_INDIRECT_REG_WRITE_B32_V16 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_512>; 595def S_INDIRECT_REG_WRITE_B32_V32 : S_INDIRECT_REG_WRITE_B32_pseudo<SReg_1024>; 596 597def S_INDIRECT_REG_WRITE_B64_V1 : S_INDIRECT_REG_WRITE_B64_pseudo<SReg_64>; 598def S_INDIRECT_REG_WRITE_B64_V2 : S_INDIRECT_REG_WRITE_B64_pseudo<SReg_128>; 599def S_INDIRECT_REG_WRITE_B64_V4 : S_INDIRECT_REG_WRITE_B64_pseudo<SReg_256>; 600def S_INDIRECT_REG_WRITE_B64_V8 : S_INDIRECT_REG_WRITE_B64_pseudo<SReg_512>; 601def S_INDIRECT_REG_WRITE_B64_V16 : S_INDIRECT_REG_WRITE_B64_pseudo<SReg_1024>; 602 603 604multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> { 605 let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in { 606 def _SAVE : PseudoInstSI < 607 (outs), 608 (ins sgpr_class:$data, i32imm:$addr)> { 609 let mayStore = 1; 610 let mayLoad = 0; 611 } 612 613 def _RESTORE : PseudoInstSI < 614 (outs sgpr_class:$data), 615 (ins i32imm:$addr)> { 616 let mayStore = 0; 617 let mayLoad = 1; 618 } 619 } // End UseNamedOperandTable = 1 620} 621 622// You cannot use M0 as the output of v_readlane_b32 instructions or 623// use it in the sdata operand of SMEM instructions. We still need to 624// be able to spill the physical register m0, so allow it for 625// SI_SPILL_32_* instructions. 626defm SI_SPILL_S32 : SI_SPILL_SGPR <SReg_32>; 627defm SI_SPILL_S64 : SI_SPILL_SGPR <SReg_64>; 628defm SI_SPILL_S96 : SI_SPILL_SGPR <SReg_96>; 629defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>; 630defm SI_SPILL_S160 : SI_SPILL_SGPR <SReg_160>; 631defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>; 632defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>; 633defm SI_SPILL_S1024 : SI_SPILL_SGPR <SReg_1024>; 634 635multiclass SI_SPILL_VGPR <RegisterClass vgpr_class> { 636 let UseNamedOperandTable = 1, VGPRSpill = 1, 637 SchedRW = [WriteVMEM] in { 638 def _SAVE : VPseudoInstSI < 639 (outs), 640 (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc, 641 SReg_32:$soffset, i32imm:$offset)> { 642 let mayStore = 1; 643 let mayLoad = 0; 644 // (2 * 4) + (8 * num_subregs) bytes maximum 645 int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 646 // Size field is unsigned char and cannot fit more. 647 let Size = !if(!le(MaxSize, 256), MaxSize, 252); 648 } 649 650 def _RESTORE : VPseudoInstSI < 651 (outs vgpr_class:$vdata), 652 (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset, 653 i32imm:$offset)> { 654 let mayStore = 0; 655 let mayLoad = 1; 656 657 // (2 * 4) + (8 * num_subregs) bytes maximum 658 int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 659 // Size field is unsigned char and cannot fit more. 660 let Size = !if(!le(MaxSize, 256), MaxSize, 252); 661 } 662 } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM] 663} 664 665defm SI_SPILL_V32 : SI_SPILL_VGPR <VGPR_32>; 666defm SI_SPILL_V64 : SI_SPILL_VGPR <VReg_64>; 667defm SI_SPILL_V96 : SI_SPILL_VGPR <VReg_96>; 668defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>; 669defm SI_SPILL_V160 : SI_SPILL_VGPR <VReg_160>; 670defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>; 671defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>; 672defm SI_SPILL_V1024 : SI_SPILL_VGPR <VReg_1024>; 673 674multiclass SI_SPILL_AGPR <RegisterClass vgpr_class> { 675 let UseNamedOperandTable = 1, VGPRSpill = 1, 676 Constraints = "@earlyclobber $tmp", 677 SchedRW = [WriteVMEM] in { 678 def _SAVE : VPseudoInstSI < 679 (outs VGPR_32:$tmp), 680 (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc, 681 SReg_32:$soffset, i32imm:$offset)> { 682 let mayStore = 1; 683 let mayLoad = 0; 684 // (2 * 4) + (16 * num_subregs) bytes maximum 685 int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), 4), 8); 686 // Size field is unsigned char and cannot fit more. 687 let Size = !if(!le(MaxSize, 256), MaxSize, 252); 688 } 689 690 def _RESTORE : VPseudoInstSI < 691 (outs vgpr_class:$vdata, VGPR_32:$tmp), 692 (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset, 693 i32imm:$offset)> { 694 let mayStore = 0; 695 let mayLoad = 1; 696 697 // (2 * 4) + (16 * num_subregs) bytes maximum 698 int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), 4), 8); 699 // Size field is unsigned char and cannot fit more. 700 let Size = !if(!le(MaxSize, 256), MaxSize, 252); 701 } 702 } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM] 703} 704 705defm SI_SPILL_A32 : SI_SPILL_AGPR <AGPR_32>; 706defm SI_SPILL_A64 : SI_SPILL_AGPR <AReg_64>; 707defm SI_SPILL_A128 : SI_SPILL_AGPR <AReg_128>; 708defm SI_SPILL_A512 : SI_SPILL_AGPR <AReg_512>; 709defm SI_SPILL_A1024 : SI_SPILL_AGPR <AReg_1024>; 710 711def SI_PC_ADD_REL_OFFSET : SPseudoInstSI < 712 (outs SReg_64:$dst), 713 (ins si_ga:$ptr_lo, si_ga:$ptr_hi), 714 [(set SReg_64:$dst, 715 (i64 (SIpc_add_rel_offset tglobaladdr:$ptr_lo, tglobaladdr:$ptr_hi)))]> { 716 let Defs = [SCC]; 717} 718 719def : GCNPat < 720 (SIpc_add_rel_offset tglobaladdr:$ptr_lo, 0), 721 (SI_PC_ADD_REL_OFFSET $ptr_lo, (i32 0)) 722>; 723 724def : GCNPat< 725 (AMDGPUtrap timm:$trapid), 726 (S_TRAP $trapid) 727>; 728 729def : GCNPat< 730 (AMDGPUelse i1:$src, bb:$target), 731 (SI_ELSE $src, $target, 0) 732>; 733 734def : Pat < 735 // -1.0 as i32 (LowerINTRINSIC_VOID converts all other constants to -1.0) 736 (AMDGPUkill (i32 -1082130432)), 737 (SI_KILL_I1_PSEUDO (i1 0), 0) 738>; 739 740def : Pat < 741 (int_amdgcn_kill i1:$src), 742 (SI_KILL_I1_PSEUDO SCSrc_i1:$src, 0) 743>; 744 745def : Pat < 746 (int_amdgcn_kill (i1 (not i1:$src))), 747 (SI_KILL_I1_PSEUDO SCSrc_i1:$src, -1) 748>; 749 750def : Pat < 751 (AMDGPUkill i32:$src), 752 (SI_KILL_F32_COND_IMM_PSEUDO VSrc_b32:$src, 0, 3) // 3 means SETOGE 753>; 754 755def : Pat < 756 (int_amdgcn_kill (i1 (setcc f32:$src, InlineImmFP32:$imm, cond:$cond))), 757 (SI_KILL_F32_COND_IMM_PSEUDO VSrc_b32:$src, (bitcast_fpimm_to_i32 $imm), (cond_as_i32imm $cond)) 758>; 759 760 // TODO: we could add more variants for other types of conditionals 761 762def : Pat < 763 (i64 (int_amdgcn_icmp i1:$src, (i1 0), (i32 33))), 764 (COPY $src) // Return the SGPRs representing i1 src 765>; 766 767def : Pat < 768 (i32 (int_amdgcn_icmp i1:$src, (i1 0), (i32 33))), 769 (COPY $src) // Return the SGPRs representing i1 src 770>; 771 772//===----------------------------------------------------------------------===// 773// VOP1 Patterns 774//===----------------------------------------------------------------------===// 775 776let OtherPredicates = [UnsafeFPMath] in { 777 778//def : RcpPat<V_RCP_F64_e32, f64>; 779//defm : RsqPat<V_RSQ_F64_e32, f64>; 780//defm : RsqPat<V_RSQ_F32_e32, f32>; 781 782def : RsqPat<V_RSQ_F32_e32, f32>; 783def : RsqPat<V_RSQ_F64_e32, f64>; 784 785// Convert (x - floor(x)) to fract(x) 786def : GCNPat < 787 (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)), 788 (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))), 789 (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 790>; 791 792// Convert (x + (-floor(x))) to fract(x) 793def : GCNPat < 794 (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)), 795 (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))), 796 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 797>; 798 799} // End OtherPredicates = [UnsafeFPMath] 800 801 802// f16_to_fp patterns 803def : GCNPat < 804 (f32 (f16_to_fp i32:$src0)), 805 (V_CVT_F32_F16_e64 SRCMODS.NONE, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 806>; 807 808def : GCNPat < 809 (f32 (f16_to_fp (and_oneuse i32:$src0, 0x7fff))), 810 (V_CVT_F32_F16_e64 SRCMODS.ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 811>; 812 813def : GCNPat < 814 (f32 (f16_to_fp (i32 (srl_oneuse (and_oneuse i32:$src0, 0x7fff0000), (i32 16))))), 815 (V_CVT_F32_F16_e64 SRCMODS.ABS, (i32 (V_LSHRREV_B32_e64 (i32 16), i32:$src0)), DSTCLAMP.NONE, DSTOMOD.NONE) 816>; 817 818def : GCNPat < 819 (f32 (f16_to_fp (or_oneuse i32:$src0, 0x8000))), 820 (V_CVT_F32_F16_e64 SRCMODS.NEG_ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 821>; 822 823def : GCNPat < 824 (f32 (f16_to_fp (xor_oneuse i32:$src0, 0x8000))), 825 (V_CVT_F32_F16_e64 SRCMODS.NEG, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 826>; 827 828def : GCNPat < 829 (f64 (fpextend f16:$src)), 830 (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src)) 831>; 832 833// fp_to_fp16 patterns 834def : GCNPat < 835 (i32 (AMDGPUfp_to_f16 (f32 (VOP3Mods f32:$src0, i32:$src0_modifiers)))), 836 (V_CVT_F16_F32_e64 $src0_modifiers, f32:$src0, DSTCLAMP.NONE, DSTOMOD.NONE) 837>; 838 839def : GCNPat < 840 (i32 (fp_to_sint f16:$src)), 841 (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 VSrc_b32:$src)) 842>; 843 844def : GCNPat < 845 (i32 (fp_to_uint f16:$src)), 846 (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 VSrc_b32:$src)) 847>; 848 849def : GCNPat < 850 (f16 (sint_to_fp i32:$src)), 851 (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 VSrc_b32:$src)) 852>; 853 854def : GCNPat < 855 (f16 (uint_to_fp i32:$src)), 856 (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 VSrc_b32:$src)) 857>; 858 859//===----------------------------------------------------------------------===// 860// VOP2 Patterns 861//===----------------------------------------------------------------------===// 862 863multiclass FMADPat <ValueType vt, Instruction inst> { 864 def : GCNPat < 865 (vt (fmad (VOP3NoMods vt:$src0), 866 (VOP3NoMods vt:$src1), 867 (VOP3NoMods vt:$src2))), 868 (inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1, 869 SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 870 >; 871} 872 873defm : FMADPat <f16, V_MAC_F16_e64>; 874defm : FMADPat <f32, V_MAC_F32_e64>; 875 876class FMADModsPat<Instruction inst, SDPatternOperator mad_opr, ValueType Ty> 877 : GCNPat< 878 (Ty (mad_opr (Ty (VOP3Mods Ty:$src0, i32:$src0_mod)), 879 (Ty (VOP3Mods Ty:$src1, i32:$src1_mod)), 880 (Ty (VOP3Mods Ty:$src2, i32:$src2_mod)))), 881 (inst $src0_mod, $src0, $src1_mod, $src1, 882 $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 883>; 884 885// FIXME: This should select to V_MAC_F32 886def : FMADModsPat<V_MAD_F32, AMDGPUfmad_ftz, f32>; 887def : FMADModsPat<V_MAD_F16, AMDGPUfmad_ftz, f16> { 888 let SubtargetPredicate = Has16BitInsts; 889} 890 891class VOPSelectModsPat <ValueType vt> : GCNPat < 892 (vt (select i1:$src0, (VOP3Mods vt:$src1, i32:$src1_mods), 893 (VOP3Mods vt:$src2, i32:$src2_mods))), 894 (V_CNDMASK_B32_e64 FP32InputMods:$src2_mods, VSrc_b32:$src2, 895 FP32InputMods:$src1_mods, VSrc_b32:$src1, SSrc_i1:$src0) 896>; 897 898class VOPSelectPat <ValueType vt> : GCNPat < 899 (vt (select i1:$src0, vt:$src1, vt:$src2)), 900 (V_CNDMASK_B32_e64 0, VSrc_b32:$src2, 0, VSrc_b32:$src1, SSrc_i1:$src0) 901>; 902 903def : VOPSelectModsPat <i32>; 904def : VOPSelectModsPat <f32>; 905def : VOPSelectPat <f16>; 906def : VOPSelectPat <i16>; 907 908let AddedComplexity = 1 in { 909def : GCNPat < 910 (i32 (add (i32 (getDivergentFrag<ctpop>.ret i32:$popcnt)), i32:$val)), 911 (V_BCNT_U32_B32_e64 $popcnt, $val) 912>; 913} 914 915def : GCNPat < 916 (i32 (ctpop i32:$popcnt)), 917 (V_BCNT_U32_B32_e64 VSrc_b32:$popcnt, (i32 0)) 918>; 919 920def : GCNPat < 921 (i16 (add (i16 (trunc (i32 (getDivergentFrag<ctpop>.ret i32:$popcnt)))), i16:$val)), 922 (V_BCNT_U32_B32_e64 $popcnt, $val) 923>; 924 925/********** ============================================ **********/ 926/********** Extraction, Insertion, Building and Casting **********/ 927/********** ============================================ **********/ 928 929foreach Index = 0-2 in { 930 def Extract_Element_v2i32_#Index : Extract_Element < 931 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 932 >; 933 def Insert_Element_v2i32_#Index : Insert_Element < 934 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 935 >; 936 937 def Extract_Element_v2f32_#Index : Extract_Element < 938 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 939 >; 940 def Insert_Element_v2f32_#Index : Insert_Element < 941 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 942 >; 943} 944 945foreach Index = 0-2 in { 946 def Extract_Element_v3i32_#Index : Extract_Element < 947 i32, v3i32, Index, !cast<SubRegIndex>(sub#Index) 948 >; 949 def Insert_Element_v3i32_#Index : Insert_Element < 950 i32, v3i32, Index, !cast<SubRegIndex>(sub#Index) 951 >; 952 953 def Extract_Element_v3f32_#Index : Extract_Element < 954 f32, v3f32, Index, !cast<SubRegIndex>(sub#Index) 955 >; 956 def Insert_Element_v3f32_#Index : Insert_Element < 957 f32, v3f32, Index, !cast<SubRegIndex>(sub#Index) 958 >; 959} 960 961foreach Index = 0-3 in { 962 def Extract_Element_v4i32_#Index : Extract_Element < 963 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 964 >; 965 def Insert_Element_v4i32_#Index : Insert_Element < 966 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 967 >; 968 969 def Extract_Element_v4f32_#Index : Extract_Element < 970 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 971 >; 972 def Insert_Element_v4f32_#Index : Insert_Element < 973 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 974 >; 975} 976 977foreach Index = 0-4 in { 978 def Extract_Element_v5i32_#Index : Extract_Element < 979 i32, v5i32, Index, !cast<SubRegIndex>(sub#Index) 980 >; 981 def Insert_Element_v5i32_#Index : Insert_Element < 982 i32, v5i32, Index, !cast<SubRegIndex>(sub#Index) 983 >; 984 985 def Extract_Element_v5f32_#Index : Extract_Element < 986 f32, v5f32, Index, !cast<SubRegIndex>(sub#Index) 987 >; 988 def Insert_Element_v5f32_#Index : Insert_Element < 989 f32, v5f32, Index, !cast<SubRegIndex>(sub#Index) 990 >; 991} 992 993foreach Index = 0-7 in { 994 def Extract_Element_v8i32_#Index : Extract_Element < 995 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 996 >; 997 def Insert_Element_v8i32_#Index : Insert_Element < 998 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 999 >; 1000 1001 def Extract_Element_v8f32_#Index : Extract_Element < 1002 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 1003 >; 1004 def Insert_Element_v8f32_#Index : Insert_Element < 1005 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 1006 >; 1007} 1008 1009foreach Index = 0-15 in { 1010 def Extract_Element_v16i32_#Index : Extract_Element < 1011 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 1012 >; 1013 def Insert_Element_v16i32_#Index : Insert_Element < 1014 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 1015 >; 1016 1017 def Extract_Element_v16f32_#Index : Extract_Element < 1018 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 1019 >; 1020 def Insert_Element_v16f32_#Index : Insert_Element < 1021 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 1022 >; 1023} 1024 1025 1026def : Pat < 1027 (extract_subvector v4i16:$vec, (i32 0)), 1028 (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub0)) 1029>; 1030 1031def : Pat < 1032 (extract_subvector v4i16:$vec, (i32 2)), 1033 (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub1)) 1034>; 1035 1036def : Pat < 1037 (extract_subvector v4f16:$vec, (i32 0)), 1038 (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub0)) 1039>; 1040 1041def : Pat < 1042 (extract_subvector v4f16:$vec, (i32 2)), 1043 (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub1)) 1044>; 1045 1046foreach Index = 0-31 in { 1047 def Extract_Element_v32i32_#Index : Extract_Element < 1048 i32, v32i32, Index, !cast<SubRegIndex>(sub#Index) 1049 >; 1050 1051 def Insert_Element_v32i32_#Index : Insert_Element < 1052 i32, v32i32, Index, !cast<SubRegIndex>(sub#Index) 1053 >; 1054 1055 def Extract_Element_v32f32_#Index : Extract_Element < 1056 f32, v32f32, Index, !cast<SubRegIndex>(sub#Index) 1057 >; 1058 1059 def Insert_Element_v32f32_#Index : Insert_Element < 1060 f32, v32f32, Index, !cast<SubRegIndex>(sub#Index) 1061 >; 1062} 1063 1064// FIXME: Why do only some of these type combinations for SReg and 1065// VReg? 1066// 16-bit bitcast 1067def : BitConvert <i16, f16, VGPR_32>; 1068def : BitConvert <f16, i16, VGPR_32>; 1069def : BitConvert <i16, f16, SReg_32>; 1070def : BitConvert <f16, i16, SReg_32>; 1071 1072// 32-bit bitcast 1073def : BitConvert <i32, f32, VGPR_32>; 1074def : BitConvert <f32, i32, VGPR_32>; 1075def : BitConvert <i32, f32, SReg_32>; 1076def : BitConvert <f32, i32, SReg_32>; 1077def : BitConvert <v2i16, i32, SReg_32>; 1078def : BitConvert <i32, v2i16, SReg_32>; 1079def : BitConvert <v2f16, i32, SReg_32>; 1080def : BitConvert <i32, v2f16, SReg_32>; 1081def : BitConvert <v2i16, v2f16, SReg_32>; 1082def : BitConvert <v2f16, v2i16, SReg_32>; 1083def : BitConvert <v2f16, f32, SReg_32>; 1084def : BitConvert <f32, v2f16, SReg_32>; 1085def : BitConvert <v2i16, f32, SReg_32>; 1086def : BitConvert <f32, v2i16, SReg_32>; 1087 1088// 64-bit bitcast 1089def : BitConvert <i64, f64, VReg_64>; 1090def : BitConvert <f64, i64, VReg_64>; 1091def : BitConvert <v2i32, v2f32, VReg_64>; 1092def : BitConvert <v2f32, v2i32, VReg_64>; 1093def : BitConvert <i64, v2i32, VReg_64>; 1094def : BitConvert <v2i32, i64, VReg_64>; 1095def : BitConvert <i64, v2f32, VReg_64>; 1096def : BitConvert <v2f32, i64, VReg_64>; 1097def : BitConvert <f64, v2f32, VReg_64>; 1098def : BitConvert <v2f32, f64, VReg_64>; 1099def : BitConvert <f64, v2i32, VReg_64>; 1100def : BitConvert <v2i32, f64, VReg_64>; 1101def : BitConvert <v4i16, v4f16, VReg_64>; 1102def : BitConvert <v4f16, v4i16, VReg_64>; 1103 1104// FIXME: Make SGPR 1105def : BitConvert <v2i32, v4f16, VReg_64>; 1106def : BitConvert <v4f16, v2i32, VReg_64>; 1107def : BitConvert <v2i32, v4f16, VReg_64>; 1108def : BitConvert <v2i32, v4i16, VReg_64>; 1109def : BitConvert <v4i16, v2i32, VReg_64>; 1110def : BitConvert <v2f32, v4f16, VReg_64>; 1111def : BitConvert <v4f16, v2f32, VReg_64>; 1112def : BitConvert <v2f32, v4i16, VReg_64>; 1113def : BitConvert <v4i16, v2f32, VReg_64>; 1114def : BitConvert <v4i16, f64, VReg_64>; 1115def : BitConvert <v4f16, f64, VReg_64>; 1116def : BitConvert <f64, v4i16, VReg_64>; 1117def : BitConvert <f64, v4f16, VReg_64>; 1118def : BitConvert <v4i16, i64, VReg_64>; 1119def : BitConvert <v4f16, i64, VReg_64>; 1120def : BitConvert <i64, v4i16, VReg_64>; 1121def : BitConvert <i64, v4f16, VReg_64>; 1122 1123def : BitConvert <v4i32, v4f32, VReg_128>; 1124def : BitConvert <v4f32, v4i32, VReg_128>; 1125 1126// 96-bit bitcast 1127def : BitConvert <v3i32, v3f32, SGPR_96>; 1128def : BitConvert <v3f32, v3i32, SGPR_96>; 1129 1130// 128-bit bitcast 1131def : BitConvert <v2i64, v4i32, SReg_128>; 1132def : BitConvert <v4i32, v2i64, SReg_128>; 1133def : BitConvert <v2f64, v4f32, VReg_128>; 1134def : BitConvert <v2f64, v4i32, VReg_128>; 1135def : BitConvert <v4f32, v2f64, VReg_128>; 1136def : BitConvert <v4i32, v2f64, VReg_128>; 1137def : BitConvert <v2i64, v2f64, VReg_128>; 1138def : BitConvert <v2f64, v2i64, VReg_128>; 1139 1140// 160-bit bitcast 1141def : BitConvert <v5i32, v5f32, SGPR_160>; 1142def : BitConvert <v5f32, v5i32, SGPR_160>; 1143 1144// 256-bit bitcast 1145def : BitConvert <v8i32, v8f32, SReg_256>; 1146def : BitConvert <v8f32, v8i32, SReg_256>; 1147def : BitConvert <v8i32, v8f32, VReg_256>; 1148def : BitConvert <v8f32, v8i32, VReg_256>; 1149 1150// 512-bit bitcast 1151def : BitConvert <v16i32, v16f32, VReg_512>; 1152def : BitConvert <v16f32, v16i32, VReg_512>; 1153 1154// 1024-bit bitcast 1155def : BitConvert <v32i32, v32f32, VReg_1024>; 1156def : BitConvert <v32f32, v32i32, VReg_1024>; 1157 1158/********** =================== **********/ 1159/********** Src & Dst modifiers **********/ 1160/********** =================== **********/ 1161 1162 1163// If denormals are not enabled, it only impacts the compare of the 1164// inputs. The output result is not flushed. 1165class ClampPat<Instruction inst, ValueType vt> : GCNPat < 1166 (vt (AMDGPUclamp (VOP3Mods vt:$src0, i32:$src0_modifiers))), 1167 (inst i32:$src0_modifiers, vt:$src0, 1168 i32:$src0_modifiers, vt:$src0, DSTCLAMP.ENABLE, DSTOMOD.NONE) 1169>; 1170 1171def : ClampPat<V_MAX_F32_e64, f32>; 1172def : ClampPat<V_MAX_F64, f64>; 1173def : ClampPat<V_MAX_F16_e64, f16>; 1174 1175let SubtargetPredicate = HasVOP3PInsts in { 1176def : GCNPat < 1177 (v2f16 (AMDGPUclamp (VOP3PMods v2f16:$src0, i32:$src0_modifiers))), 1178 (V_PK_MAX_F16 $src0_modifiers, $src0, 1179 $src0_modifiers, $src0, DSTCLAMP.ENABLE) 1180>; 1181} 1182 1183/********** ================================ **********/ 1184/********** Floating point absolute/negative **********/ 1185/********** ================================ **********/ 1186 1187// Prevent expanding both fneg and fabs. 1188// TODO: Add IgnoredBySelectionDAG bit? 1189let AddedComplexity = 1 in { // Prefer SALU to VALU patterns for DAG 1190 1191def : GCNPat < 1192 (fneg (fabs (f32 SReg_32:$src))), 1193 (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80000000))) // Set sign bit 1194>; 1195 1196def : GCNPat < 1197 (fabs (f32 SReg_32:$src)), 1198 (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x7fffffff))) 1199>; 1200 1201def : GCNPat < 1202 (fneg (f32 SReg_32:$src)), 1203 (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80000000))) 1204>; 1205 1206def : GCNPat < 1207 (fneg (f16 SReg_32:$src)), 1208 (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00008000))) 1209>; 1210 1211def : GCNPat < 1212 (fneg (f16 VGPR_32:$src)), 1213 (V_XOR_B32_e32 (S_MOV_B32 (i32 0x00008000)), VGPR_32:$src) 1214>; 1215 1216def : GCNPat < 1217 (fabs (f16 SReg_32:$src)), 1218 (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00007fff))) 1219>; 1220 1221def : GCNPat < 1222 (fneg (fabs (f16 SReg_32:$src))), 1223 (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit 1224>; 1225 1226def : GCNPat < 1227 (fneg (fabs (f16 VGPR_32:$src))), 1228 (V_OR_B32_e32 (S_MOV_B32 (i32 0x00008000)), VGPR_32:$src) // Set sign bit 1229>; 1230 1231def : GCNPat < 1232 (fneg (v2f16 SReg_32:$src)), 1233 (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000))) 1234>; 1235 1236def : GCNPat < 1237 (fabs (v2f16 SReg_32:$src)), 1238 (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x7fff7fff))) 1239>; 1240 1241// This is really (fneg (fabs v2f16:$src)) 1242// 1243// fabs is not reported as free because there is modifier for it in 1244// VOP3P instructions, so it is turned into the bit op. 1245def : GCNPat < 1246 (fneg (v2f16 (bitconvert (and_oneuse (i32 SReg_32:$src), 0x7fff7fff)))), 1247 (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit 1248>; 1249 1250def : GCNPat < 1251 (fneg (v2f16 (fabs SReg_32:$src))), 1252 (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit 1253>; 1254 1255// FIXME: The implicit-def of scc from S_[X]OR_B32 is mishandled 1256 // def : GCNPat < 1257// (fneg (f64 SReg_64:$src)), 1258// (REG_SEQUENCE SReg_64, 1259// (i32 (EXTRACT_SUBREG SReg_64:$src, sub0)), 1260// sub0, 1261// (S_XOR_B32 (i32 (EXTRACT_SUBREG SReg_64:$src, sub1)), 1262// (i32 (S_MOV_B32 (i32 0x80000000)))), 1263// sub1) 1264// >; 1265 1266// def : GCNPat < 1267// (fneg (fabs (f64 SReg_64:$src))), 1268// (REG_SEQUENCE SReg_64, 1269// (i32 (EXTRACT_SUBREG SReg_64:$src, sub0)), 1270// sub0, 1271// (S_OR_B32 (i32 (EXTRACT_SUBREG SReg_64:$src, sub1)), 1272// (S_MOV_B32 (i32 0x80000000))), // Set sign bit. 1273// sub1) 1274// >; 1275 1276} // End let AddedComplexity = 1 1277 1278def : GCNPat < 1279 (fabs (f32 VGPR_32:$src)), 1280 (V_AND_B32_e32 (S_MOV_B32 (i32 0x7fffffff)), VGPR_32:$src) 1281>; 1282 1283def : GCNPat < 1284 (fneg (f32 VGPR_32:$src)), 1285 (V_XOR_B32_e32 (S_MOV_B32 (i32 0x80000000)), VGPR_32:$src) 1286>; 1287 1288def : GCNPat < 1289 (fabs (f16 VGPR_32:$src)), 1290 (V_AND_B32_e32 (S_MOV_B32 (i32 0x00007fff)), VGPR_32:$src) 1291>; 1292 1293def : GCNPat < 1294 (fneg (v2f16 VGPR_32:$src)), 1295 (V_XOR_B32_e32 (S_MOV_B32 (i32 0x80008000)), VGPR_32:$src) 1296>; 1297 1298def : GCNPat < 1299 (fabs (v2f16 VGPR_32:$src)), 1300 (V_AND_B32_e32 (S_MOV_B32 (i32 0x7fff7fff)), VGPR_32:$src) 1301>; 1302 1303def : GCNPat < 1304 (fneg (v2f16 (fabs VGPR_32:$src))), 1305 (V_OR_B32_e32 (S_MOV_B32 (i32 0x80008000)), VGPR_32:$src) // Set sign bit 1306>; 1307 1308def : GCNPat < 1309 (fabs (f64 VReg_64:$src)), 1310 (REG_SEQUENCE VReg_64, 1311 (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)), 1312 sub0, 1313 (V_AND_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$src, sub1)), 1314 (V_MOV_B32_e32 (i32 0x7fffffff))), // Set sign bit. 1315 sub1) 1316>; 1317 1318// TODO: Use SGPR for constant 1319def : GCNPat < 1320 (fneg (f64 VReg_64:$src)), 1321 (REG_SEQUENCE VReg_64, 1322 (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)), 1323 sub0, 1324 (V_XOR_B32_e32 (i32 (EXTRACT_SUBREG VReg_64:$src, sub1)), 1325 (i32 (V_MOV_B32_e32 (i32 0x80000000)))), 1326 sub1) 1327>; 1328 1329// TODO: Use SGPR for constant 1330def : GCNPat < 1331 (fneg (fabs (f64 VReg_64:$src))), 1332 (REG_SEQUENCE VReg_64, 1333 (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)), 1334 sub0, 1335 (V_OR_B32_e32 (i32 (EXTRACT_SUBREG VReg_64:$src, sub1)), 1336 (V_MOV_B32_e32 (i32 0x80000000))), // Set sign bit. 1337 sub1) 1338>; 1339 1340def : GCNPat < 1341 (fcopysign f16:$src0, f16:$src1), 1342 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, $src1) 1343>; 1344 1345def : GCNPat < 1346 (fcopysign f32:$src0, f16:$src1), 1347 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), $src0, 1348 (V_LSHLREV_B32_e64 (i32 16), $src1)) 1349>; 1350 1351def : GCNPat < 1352 (fcopysign f64:$src0, f16:$src1), 1353 (REG_SEQUENCE SReg_64, 1354 (i32 (EXTRACT_SUBREG $src0, sub0)), sub0, 1355 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), (i32 (EXTRACT_SUBREG $src0, sub1)), 1356 (V_LSHLREV_B32_e64 (i32 16), $src1)), sub1) 1357>; 1358 1359def : GCNPat < 1360 (fcopysign f16:$src0, f32:$src1), 1361 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 1362 (V_LSHRREV_B32_e64 (i32 16), $src1)) 1363>; 1364 1365def : GCNPat < 1366 (fcopysign f16:$src0, f64:$src1), 1367 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 1368 (V_LSHRREV_B32_e64 (i32 16), (EXTRACT_SUBREG $src1, sub1))) 1369>; 1370 1371/********** ================== **********/ 1372/********** Immediate Patterns **********/ 1373/********** ================== **********/ 1374 1375def : GCNPat < 1376 (VGPRImm<(i32 imm)>:$imm), 1377 (V_MOV_B32_e32 imm:$imm) 1378>; 1379 1380def : GCNPat < 1381 (VGPRImm<(f32 fpimm)>:$imm), 1382 (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm))) 1383>; 1384 1385def : GCNPat < 1386 (i32 imm:$imm), 1387 (S_MOV_B32 imm:$imm) 1388>; 1389 1390def : GCNPat < 1391 (VGPRImm<(SIlds tglobaladdr:$ga)>), 1392 (V_MOV_B32_e32 $ga) 1393>; 1394 1395def : GCNPat < 1396 (SIlds tglobaladdr:$ga), 1397 (S_MOV_B32 $ga) 1398>; 1399 1400// FIXME: Workaround for ordering issue with peephole optimizer where 1401// a register class copy interferes with immediate folding. Should 1402// use s_mov_b32, which can be shrunk to s_movk_i32 1403def : GCNPat < 1404 (VGPRImm<(f16 fpimm)>:$imm), 1405 (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm))) 1406>; 1407 1408def : GCNPat < 1409 (f32 fpimm:$imm), 1410 (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm))) 1411>; 1412 1413def : GCNPat < 1414 (f16 fpimm:$imm), 1415 (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm))) 1416>; 1417 1418def : GCNPat < 1419 (i32 frameindex:$fi), 1420 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi))) 1421>; 1422 1423def : GCNPat < 1424 (i64 InlineImm64:$imm), 1425 (S_MOV_B64 InlineImm64:$imm) 1426>; 1427 1428// XXX - Should this use a s_cmp to set SCC? 1429 1430// Set to sign-extended 64-bit value (true = -1, false = 0) 1431def : GCNPat < 1432 (i1 imm:$imm), 1433 (S_MOV_B64 (i64 (as_i64imm $imm))) 1434> { 1435 let WaveSizePredicate = isWave64; 1436} 1437 1438def : GCNPat < 1439 (i1 imm:$imm), 1440 (S_MOV_B32 (i32 (as_i32imm $imm))) 1441> { 1442 let WaveSizePredicate = isWave32; 1443} 1444 1445def : GCNPat < 1446 (f64 InlineImmFP64:$imm), 1447 (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineImmFP64:$imm))) 1448>; 1449 1450/********** ================== **********/ 1451/********** Intrinsic Patterns **********/ 1452/********** ================== **********/ 1453 1454// FIXME: Should use _e64 and select source modifiers. 1455def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>; 1456 1457def : GCNPat < 1458 (i32 (sext i1:$src0)), 1459 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1460 /*src1mod*/(i32 0), /*src1*/(i32 -1), $src0) 1461>; 1462 1463class Ext32Pat <SDNode ext> : GCNPat < 1464 (i32 (ext i1:$src0)), 1465 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1466 /*src1mod*/(i32 0), /*src1*/(i32 1), $src0) 1467>; 1468 1469def : Ext32Pat <zext>; 1470def : Ext32Pat <anyext>; 1471 1472// The multiplication scales from [0,1] to the unsigned integer range 1473def : GCNPat < 1474 (AMDGPUurecip i32:$src0), 1475 (V_CVT_U32_F32_e32 1476 (V_MUL_F32_e32 (i32 CONST.FP_UINT_MAX_PLUS_1), 1477 (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0)))) 1478>; 1479 1480//===----------------------------------------------------------------------===// 1481// VOP3 Patterns 1482//===----------------------------------------------------------------------===// 1483 1484def : IMad24Pat<V_MAD_I32_I24, 1>; 1485def : UMad24Pat<V_MAD_U32_U24, 1>; 1486 1487// FIXME: This should only be done for VALU inputs 1488defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>; 1489def : ROTRPattern <V_ALIGNBIT_B32>; 1490 1491def : GCNPat<(i32 (trunc (srl i64:$src0, (and i32:$src1, (i32 31))))), 1492 (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)), 1493 (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>; 1494 1495def : GCNPat<(i32 (trunc (srl i64:$src0, (i32 ShiftAmt32Imm:$src1)))), 1496 (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)), 1497 (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>; 1498 1499/********** ====================== **********/ 1500/********** Indirect addressing **********/ 1501/********** ====================== **********/ 1502 1503multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> { 1504 // Extract with offset 1505 def : GCNPat< 1506 (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))), 1507 (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset) 1508 >; 1509 1510 // Insert with offset 1511 def : GCNPat< 1512 (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))), 1513 (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val) 1514 >; 1515} 1516 1517defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">; 1518defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">; 1519defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">; 1520defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">; 1521 1522defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">; 1523defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">; 1524defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">; 1525defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">; 1526 1527//===----------------------------------------------------------------------===// 1528// SAD Patterns 1529//===----------------------------------------------------------------------===// 1530 1531def : GCNPat < 1532 (add (sub_oneuse (umax i32:$src0, i32:$src1), 1533 (umin i32:$src0, i32:$src1)), 1534 i32:$src2), 1535 (V_SAD_U32 $src0, $src1, $src2, (i1 0)) 1536>; 1537 1538def : GCNPat < 1539 (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)), 1540 (sub i32:$src0, i32:$src1), 1541 (sub i32:$src1, i32:$src0)), 1542 i32:$src2), 1543 (V_SAD_U32 $src0, $src1, $src2, (i1 0)) 1544>; 1545 1546//===----------------------------------------------------------------------===// 1547// Conversion Patterns 1548//===----------------------------------------------------------------------===// 1549 1550def : GCNPat<(i32 (sext_inreg i32:$src, i1)), 1551 (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16 1552 1553// Handle sext_inreg in i64 1554def : GCNPat < 1555 (i64 (sext_inreg i64:$src, i1)), 1556 (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16 1557>; 1558 1559def : GCNPat < 1560 (i16 (sext_inreg i16:$src, i1)), 1561 (S_BFE_I32 $src, (i32 0x00010000)) // 0 | 1 << 16 1562>; 1563 1564def : GCNPat < 1565 (i16 (sext_inreg i16:$src, i8)), 1566 (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16 1567>; 1568 1569def : GCNPat < 1570 (i64 (sext_inreg i64:$src, i8)), 1571 (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16 1572>; 1573 1574def : GCNPat < 1575 (i64 (sext_inreg i64:$src, i16)), 1576 (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16 1577>; 1578 1579def : GCNPat < 1580 (i64 (sext_inreg i64:$src, i32)), 1581 (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16 1582>; 1583 1584def : GCNPat < 1585 (i64 (zext i32:$src)), 1586 (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1) 1587>; 1588 1589def : GCNPat < 1590 (i64 (anyext i32:$src)), 1591 (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1) 1592>; 1593 1594class ZExt_i64_i1_Pat <SDNode ext> : GCNPat < 1595 (i64 (ext i1:$src)), 1596 (REG_SEQUENCE VReg_64, 1597 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1598 /*src1mod*/(i32 0), /*src1*/(i32 1), $src), 1599 sub0, (S_MOV_B32 (i32 0)), sub1) 1600>; 1601 1602 1603def : ZExt_i64_i1_Pat<zext>; 1604def : ZExt_i64_i1_Pat<anyext>; 1605 1606// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that 1607// REG_SEQUENCE patterns don't support instructions with multiple outputs. 1608def : GCNPat < 1609 (i64 (sext i32:$src)), 1610 (REG_SEQUENCE SReg_64, $src, sub0, 1611 (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1) 1612>; 1613 1614def : GCNPat < 1615 (i64 (sext i1:$src)), 1616 (REG_SEQUENCE VReg_64, 1617 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1618 /*src1mod*/(i32 0), /*src1*/(i32 -1), $src), sub0, 1619 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1620 /*src1mod*/(i32 0), /*src1*/(i32 -1), $src), sub1) 1621>; 1622 1623class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : GCNPat < 1624 (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))), 1625 (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE)) 1626>; 1627 1628def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>; 1629def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>; 1630def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>; 1631def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>; 1632 1633// If we need to perform a logical operation on i1 values, we need to 1634// use vector comparisons since there is only one SCC register. Vector 1635// comparisons may write to a pair of SGPRs or a single SGPR, so treat 1636// these as 32 or 64-bit comparisons. When legalizing SGPR copies, 1637// instructions resulting in the copies from SCC to these instructions 1638// will be moved to the VALU. 1639 1640let WaveSizePredicate = isWave64 in { 1641def : GCNPat < 1642 (i1 (and i1:$src0, i1:$src1)), 1643 (S_AND_B64 $src0, $src1) 1644>; 1645 1646def : GCNPat < 1647 (i1 (or i1:$src0, i1:$src1)), 1648 (S_OR_B64 $src0, $src1) 1649>; 1650 1651def : GCNPat < 1652 (i1 (xor i1:$src0, i1:$src1)), 1653 (S_XOR_B64 $src0, $src1) 1654>; 1655 1656def : GCNPat < 1657 (i1 (add i1:$src0, i1:$src1)), 1658 (S_XOR_B64 $src0, $src1) 1659>; 1660 1661def : GCNPat < 1662 (i1 (sub i1:$src0, i1:$src1)), 1663 (S_XOR_B64 $src0, $src1) 1664>; 1665 1666let AddedComplexity = 1 in { 1667def : GCNPat < 1668 (i1 (add i1:$src0, (i1 -1))), 1669 (S_NOT_B64 $src0) 1670>; 1671 1672def : GCNPat < 1673 (i1 (sub i1:$src0, (i1 -1))), 1674 (S_NOT_B64 $src0) 1675>; 1676} 1677} // end isWave64 1678 1679let WaveSizePredicate = isWave32 in { 1680def : GCNPat < 1681 (i1 (and i1:$src0, i1:$src1)), 1682 (S_AND_B32 $src0, $src1) 1683>; 1684 1685def : GCNPat < 1686 (i1 (or i1:$src0, i1:$src1)), 1687 (S_OR_B32 $src0, $src1) 1688>; 1689 1690def : GCNPat < 1691 (i1 (xor i1:$src0, i1:$src1)), 1692 (S_XOR_B32 $src0, $src1) 1693>; 1694 1695def : GCNPat < 1696 (i1 (add i1:$src0, i1:$src1)), 1697 (S_XOR_B32 $src0, $src1) 1698>; 1699 1700def : GCNPat < 1701 (i1 (sub i1:$src0, i1:$src1)), 1702 (S_XOR_B32 $src0, $src1) 1703>; 1704 1705let AddedComplexity = 1 in { 1706def : GCNPat < 1707 (i1 (add i1:$src0, (i1 -1))), 1708 (S_NOT_B32 $src0) 1709>; 1710 1711def : GCNPat < 1712 (i1 (sub i1:$src0, (i1 -1))), 1713 (S_NOT_B32 $src0) 1714>; 1715} 1716} // end isWave32 1717 1718def : GCNPat < 1719 (f16 (sint_to_fp i1:$src)), 1720 (V_CVT_F16_F32_e32 ( 1721 V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1722 /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_NEG_ONE), 1723 SSrc_i1:$src)) 1724>; 1725 1726def : GCNPat < 1727 (f16 (uint_to_fp i1:$src)), 1728 (V_CVT_F16_F32_e32 ( 1729 V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1730 /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_ONE), 1731 SSrc_i1:$src)) 1732>; 1733 1734def : GCNPat < 1735 (f32 (sint_to_fp i1:$src)), 1736 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1737 /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_NEG_ONE), 1738 SSrc_i1:$src) 1739>; 1740 1741def : GCNPat < 1742 (f32 (uint_to_fp i1:$src)), 1743 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1744 /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_ONE), 1745 SSrc_i1:$src) 1746>; 1747 1748def : GCNPat < 1749 (f64 (sint_to_fp i1:$src)), 1750 (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1751 /*src1mod*/(i32 0), /*src1*/(i32 -1), 1752 SSrc_i1:$src)) 1753>; 1754 1755def : GCNPat < 1756 (f64 (uint_to_fp i1:$src)), 1757 (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0), 1758 /*src1mod*/(i32 0), /*src1*/(i32 1), 1759 SSrc_i1:$src)) 1760>; 1761 1762//===----------------------------------------------------------------------===// 1763// Miscellaneous Patterns 1764//===----------------------------------------------------------------------===// 1765def : GCNPat < 1766 (i32 (AMDGPUfp16_zext f16:$src)), 1767 (COPY $src) 1768>; 1769 1770 1771def : GCNPat < 1772 (i32 (trunc i64:$a)), 1773 (EXTRACT_SUBREG $a, sub0) 1774>; 1775 1776def : GCNPat < 1777 (i1 (trunc i32:$a)), 1778 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1779>; 1780 1781def : GCNPat < 1782 (i1 (trunc i16:$a)), 1783 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1784>; 1785 1786def : GCNPat < 1787 (i1 (trunc i64:$a)), 1788 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), 1789 (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1)) 1790>; 1791 1792def : GCNPat < 1793 (i32 (bswap i32:$a)), 1794 (V_BFI_B32 (S_MOV_B32 (i32 0x00ff00ff)), 1795 (V_ALIGNBIT_B32 $a, $a, (i32 24)), 1796 (V_ALIGNBIT_B32 $a, $a, (i32 8))) 1797>; 1798 1799let OtherPredicates = [NoFP16Denormals] in { 1800def : GCNPat< 1801 (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))), 1802 (V_MUL_F16_e64 0, (i32 CONST.FP16_ONE), $src_mods, $src, 0, 0) 1803>; 1804 1805def : GCNPat< 1806 (fcanonicalize (f16 (fneg (VOP3Mods f16:$src, i32:$src_mods)))), 1807 (V_MUL_F16_e64 0, (i32 CONST.FP16_NEG_ONE), $src_mods, $src, 0, 0) 1808>; 1809 1810def : GCNPat< 1811 (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))), 1812 (V_PK_MUL_F16 0, (i32 CONST.FP16_ONE), $src_mods, $src, DSTCLAMP.NONE) 1813>; 1814} 1815 1816let OtherPredicates = [FP16Denormals] in { 1817def : GCNPat< 1818 (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))), 1819 (V_MAX_F16_e64 $src_mods, $src, $src_mods, $src, 0, 0) 1820>; 1821 1822let SubtargetPredicate = HasVOP3PInsts in { 1823def : GCNPat< 1824 (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))), 1825 (V_PK_MAX_F16 $src_mods, $src, $src_mods, $src, DSTCLAMP.NONE) 1826>; 1827} 1828} 1829 1830let OtherPredicates = [NoFP32Denormals] in { 1831def : GCNPat< 1832 (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))), 1833 (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), $src_mods, $src, 0, 0) 1834>; 1835 1836def : GCNPat< 1837 (fcanonicalize (f32 (fneg (VOP3Mods f32:$src, i32:$src_mods)))), 1838 (V_MUL_F32_e64 0, (i32 CONST.FP32_NEG_ONE), $src_mods, $src, 0, 0) 1839>; 1840} 1841 1842let OtherPredicates = [FP32Denormals] in { 1843def : GCNPat< 1844 (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))), 1845 (V_MAX_F32_e64 $src_mods, $src, $src_mods, $src, 0, 0) 1846>; 1847} 1848 1849let OtherPredicates = [NoFP64Denormals] in { 1850def : GCNPat< 1851 (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))), 1852 (V_MUL_F64 0, CONST.FP64_ONE, $src_mods, $src, 0, 0) 1853>; 1854} 1855 1856let OtherPredicates = [FP64Denormals] in { 1857def : GCNPat< 1858 (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))), 1859 (V_MAX_F64 $src_mods, $src, $src_mods, $src, 0, 0) 1860>; 1861} 1862 1863let OtherPredicates = [HasDLInsts] in { 1864def : GCNPat < 1865 (fma (f32 (VOP3Mods0 f32:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)), 1866 (f32 (VOP3Mods f32:$src1, i32:$src1_modifiers)), 1867 (f32 (VOP3NoMods f32:$src2))), 1868 (V_FMAC_F32_e64 $src0_modifiers, $src0, $src1_modifiers, $src1, 1869 SRCMODS.NONE, $src2, $clamp, $omod) 1870>; 1871} // End OtherPredicates = [HasDLInsts] 1872 1873let SubtargetPredicate = isGFX10Plus in 1874def : GCNPat < 1875 (fma (f16 (VOP3Mods0 f32:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)), 1876 (f16 (VOP3Mods f32:$src1, i32:$src1_modifiers)), 1877 (f16 (VOP3NoMods f32:$src2))), 1878 (V_FMAC_F16_e64 $src0_modifiers, $src0, $src1_modifiers, $src1, 1879 SRCMODS.NONE, $src2, $clamp, $omod) 1880>; 1881 1882// COPY is workaround tablegen bug from multiple outputs 1883// from S_LSHL_B32's multiple outputs from implicit scc def. 1884def : GCNPat < 1885 (v2i16 (build_vector (i16 0), (i16 SReg_32:$src1))), 1886 (S_LSHL_B32 SReg_32:$src1, (i16 16)) 1887>; 1888 1889def : GCNPat < 1890 (v2i16 (build_vector (i16 SReg_32:$src0), (i16 undef))), 1891 (COPY_TO_REGCLASS SReg_32:$src0, SReg_32) 1892>; 1893 1894def : GCNPat < 1895 (v2i16 (build_vector (i16 VGPR_32:$src0), (i16 undef))), 1896 (COPY_TO_REGCLASS VGPR_32:$src0, VGPR_32) 1897>; 1898 1899def : GCNPat < 1900 (v2f16 (build_vector f16:$src0, (f16 undef))), 1901 (COPY $src0) 1902>; 1903 1904def : GCNPat < 1905 (v2i16 (build_vector (i16 undef), (i16 SReg_32:$src1))), 1906 (S_LSHL_B32 SReg_32:$src1, (i32 16)) 1907>; 1908 1909def : GCNPat < 1910 (v2f16 (build_vector (f16 undef), (f16 SReg_32:$src1))), 1911 (S_LSHL_B32 SReg_32:$src1, (i32 16)) 1912>; 1913 1914let SubtargetPredicate = HasVOP3PInsts in { 1915def : GCNPat < 1916 (v2i16 (build_vector (i16 SReg_32:$src0), (i16 SReg_32:$src1))), 1917 (S_PACK_LL_B32_B16 SReg_32:$src0, SReg_32:$src1) 1918>; 1919 1920// With multiple uses of the shift, this will duplicate the shift and 1921// increase register pressure. 1922def : GCNPat < 1923 (v2i16 (build_vector (i16 SReg_32:$src0), (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))), 1924 (v2i16 (S_PACK_LH_B32_B16 SReg_32:$src0, SReg_32:$src1)) 1925>; 1926 1927 1928def : GCNPat < 1929 (v2i16 (build_vector (i16 (trunc (srl_oneuse SReg_32:$src0, (i32 16)))), 1930 (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))), 1931 (S_PACK_HH_B32_B16 SReg_32:$src0, SReg_32:$src1) 1932>; 1933 1934// TODO: Should source modifiers be matched to v_pack_b32_f16? 1935def : GCNPat < 1936 (v2f16 (build_vector (f16 SReg_32:$src0), (f16 SReg_32:$src1))), 1937 (S_PACK_LL_B32_B16 SReg_32:$src0, SReg_32:$src1) 1938>; 1939 1940} // End SubtargetPredicate = HasVOP3PInsts 1941 1942 1943def : GCNPat < 1944 (v2f16 (scalar_to_vector f16:$src0)), 1945 (COPY $src0) 1946>; 1947 1948def : GCNPat < 1949 (v2i16 (scalar_to_vector i16:$src0)), 1950 (COPY $src0) 1951>; 1952 1953def : GCNPat < 1954 (v4i16 (scalar_to_vector i16:$src0)), 1955 (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0) 1956>; 1957 1958def : GCNPat < 1959 (v4f16 (scalar_to_vector f16:$src0)), 1960 (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0) 1961>; 1962 1963def : GCNPat < 1964 (i64 (int_amdgcn_mov_dpp i64:$src, timm:$dpp_ctrl, timm:$row_mask, 1965 timm:$bank_mask, timm:$bound_ctrl)), 1966 (V_MOV_B64_DPP_PSEUDO VReg_64:$src, VReg_64:$src, 1967 (as_i32timm $dpp_ctrl), (as_i32timm $row_mask), 1968 (as_i32timm $bank_mask), 1969 (as_i1timm $bound_ctrl)) 1970>; 1971 1972def : GCNPat < 1973 (i64 (int_amdgcn_update_dpp i64:$old, i64:$src, timm:$dpp_ctrl, timm:$row_mask, 1974 timm:$bank_mask, timm:$bound_ctrl)), 1975 (V_MOV_B64_DPP_PSEUDO VReg_64:$old, VReg_64:$src, (as_i32timm $dpp_ctrl), 1976 (as_i32timm $row_mask), (as_i32timm $bank_mask), 1977 (as_i1timm $bound_ctrl)) 1978>; 1979 1980//===----------------------------------------------------------------------===// 1981// Fract Patterns 1982//===----------------------------------------------------------------------===// 1983 1984let SubtargetPredicate = isGFX6 in { 1985 1986// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is 1987// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient 1988// way to implement it is using V_FRACT_F64. 1989// The workaround for the V_FRACT bug is: 1990// fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999) 1991 1992// Convert floor(x) to (x - fract(x)) 1993def : GCNPat < 1994 (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))), 1995 (V_ADD_F64 1996 $mods, 1997 $x, 1998 SRCMODS.NEG, 1999 (V_CNDMASK_B64_PSEUDO 2000 (V_MIN_F64 2001 SRCMODS.NONE, 2002 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE), 2003 SRCMODS.NONE, 2004 (V_MOV_B64_PSEUDO 0x3fefffffffffffff), 2005 DSTCLAMP.NONE, DSTOMOD.NONE), 2006 $x, 2007 (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))), 2008 DSTCLAMP.NONE, DSTOMOD.NONE) 2009>; 2010 2011} // End SubtargetPredicates = isGFX6 2012 2013//============================================================================// 2014// Miscellaneous Optimization Patterns 2015//============================================================================// 2016 2017// Undo sub x, c -> add x, -c canonicalization since c is more likely 2018// an inline immediate than -c. 2019// TODO: Also do for 64-bit. 2020def : GCNPat< 2021 (add i32:$src0, (i32 NegSubInlineConst32:$src1)), 2022 (S_SUB_I32 SReg_32:$src0, NegSubInlineConst32:$src1) 2023>; 2024 2025def : GCNPat< 2026 (add i32:$src0, (i32 NegSubInlineConst32:$src1)), 2027 (V_SUB_U32_e64 VS_32:$src0, NegSubInlineConst32:$src1)> { 2028 let SubtargetPredicate = HasAddNoCarryInsts; 2029} 2030 2031def : GCNPat< 2032 (add i32:$src0, (i32 NegSubInlineConst32:$src1)), 2033 (V_SUB_I32_e64 VS_32:$src0, NegSubInlineConst32:$src1)> { 2034 let SubtargetPredicate = NotHasAddNoCarryInsts; 2035} 2036 2037 2038// Avoid pointlessly materializing a constant in VGPR. 2039// FIXME: Should also do this for readlane, but tablegen crashes on 2040// the ignored src1. 2041def : GCNPat< 2042 (int_amdgcn_readfirstlane (i32 imm:$src)), 2043 (S_MOV_B32 SReg_32:$src) 2044>; 2045 2046multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> { 2047 def : GCNPat < 2048 (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)), 2049 (BFM $a, $b) 2050 >; 2051 2052 def : GCNPat < 2053 (vt (add (vt (shl 1, vt:$a)), -1)), 2054 (BFM $a, (MOV (i32 0))) 2055 >; 2056} 2057 2058defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>; 2059// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>; 2060 2061defm : BFEPattern <V_BFE_U32, V_BFE_I32, S_MOV_B32>; 2062defm : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64, SReg_64>; 2063 2064multiclass IntMed3Pat<Instruction med3Inst, 2065 SDPatternOperator min, 2066 SDPatternOperator max, 2067 SDPatternOperator min_oneuse, 2068 SDPatternOperator max_oneuse> { 2069 2070 // This matches 16 permutations of 2071 // min(max(a, b), max(min(a, b), c)) 2072 def : AMDGPUPat < 2073 (min (max_oneuse i32:$src0, i32:$src1), 2074 (max_oneuse (min_oneuse i32:$src0, i32:$src1), i32:$src2)), 2075 (med3Inst VSrc_b32:$src0, VSrc_b32:$src1, VSrc_b32:$src2) 2076>; 2077 2078 // This matches 16 permutations of 2079 // max(min(x, y), min(max(x, y), z)) 2080 def : AMDGPUPat < 2081 (max (min_oneuse i32:$src0, i32:$src1), 2082 (min_oneuse (max_oneuse i32:$src0, i32:$src1), i32:$src2)), 2083 (med3Inst VSrc_b32:$src0, VSrc_b32:$src1, VSrc_b32:$src2) 2084>; 2085} 2086 2087defm : IntMed3Pat<V_MED3_I32, smin, smax, smin_oneuse, smax_oneuse>; 2088defm : IntMed3Pat<V_MED3_U32, umin, umax, umin_oneuse, umax_oneuse>; 2089 2090// This matches 16 permutations of 2091// max(min(x, y), min(max(x, y), z)) 2092class FPMed3Pat<ValueType vt, 2093 //SDPatternOperator max, SDPatternOperator min, 2094 Instruction med3Inst> : GCNPat< 2095 (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 2096 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 2097 (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 2098 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 2099 (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))), 2100 (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 2101>; 2102 2103class FP16Med3Pat<ValueType vt, 2104 Instruction med3Inst> : GCNPat< 2105 (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 2106 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 2107 (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 2108 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 2109 (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))), 2110 (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE) 2111>; 2112 2113multiclass Int16Med3Pat<Instruction med3Inst, 2114 SDPatternOperator min, 2115 SDPatternOperator max, 2116 SDPatternOperator max_oneuse, 2117 SDPatternOperator min_oneuse> { 2118 // This matches 16 permutations of 2119 // max(min(x, y), min(max(x, y), z)) 2120 def : GCNPat < 2121 (max (min_oneuse i16:$src0, i16:$src1), 2122 (min_oneuse (max_oneuse i16:$src0, i16:$src1), i16:$src2)), 2123 (med3Inst SRCMODS.NONE, VSrc_b16:$src0, SRCMODS.NONE, VSrc_b16:$src1, SRCMODS.NONE, VSrc_b16:$src2, DSTCLAMP.NONE) 2124>; 2125 2126 // This matches 16 permutations of 2127 // min(max(a, b), max(min(a, b), c)) 2128 def : GCNPat < 2129 (min (max_oneuse i16:$src0, i16:$src1), 2130 (max_oneuse (min_oneuse i16:$src0, i16:$src1), i16:$src2)), 2131 (med3Inst SRCMODS.NONE, VSrc_b16:$src0, SRCMODS.NONE, VSrc_b16:$src1, SRCMODS.NONE, VSrc_b16:$src2, DSTCLAMP.NONE) 2132>; 2133} 2134 2135def : FPMed3Pat<f32, V_MED3_F32>; 2136 2137let OtherPredicates = [isGFX9Plus] in { 2138def : FP16Med3Pat<f16, V_MED3_F16>; 2139defm : Int16Med3Pat<V_MED3_I16, smin, smax, smax_oneuse, smin_oneuse>; 2140defm : Int16Med3Pat<V_MED3_U16, umin, umax, umax_oneuse, umin_oneuse>; 2141} // End Predicates = [isGFX9Plus] 2142 2143class AMDGPUGenericInstruction : GenericInstruction { 2144 let Namespace = "AMDGPU"; 2145} 2146 2147def G_AMDGPU_FFBH_U32 : AMDGPUGenericInstruction { 2148 let OutOperandList = (outs type0:$dst); 2149 let InOperandList = (ins type1:$src); 2150 let hasSideEffects = 0; 2151} 2152 2153class BufferLoadGenericInstruction : AMDGPUGenericInstruction { 2154 let OutOperandList = (outs type0:$dst); 2155 let InOperandList = (ins type1:$rsrc, type2:$vindex, type2:$voffset, 2156 type2:$soffset, untyped_imm_0:$offset, 2157 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2158 let hasSideEffects = 0; 2159 let mayLoad = 1; 2160} 2161 2162class TBufferLoadGenericInstruction : AMDGPUGenericInstruction { 2163 let OutOperandList = (outs type0:$dst); 2164 let InOperandList = (ins type1:$rsrc, type2:$vindex, type2:$voffset, 2165 type2:$soffset, untyped_imm_0:$offset, untyped_imm_0:$format, 2166 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2167 let hasSideEffects = 0; 2168 let mayLoad = 1; 2169} 2170 2171def G_AMDGPU_BUFFER_LOAD_UBYTE : BufferLoadGenericInstruction; 2172def G_AMDGPU_BUFFER_LOAD_SBYTE : BufferLoadGenericInstruction; 2173def G_AMDGPU_BUFFER_LOAD_USHORT : BufferLoadGenericInstruction; 2174def G_AMDGPU_BUFFER_LOAD_SSHORT : BufferLoadGenericInstruction; 2175def G_AMDGPU_BUFFER_LOAD : BufferLoadGenericInstruction; 2176def G_AMDGPU_BUFFER_LOAD_FORMAT : BufferLoadGenericInstruction; 2177def G_AMDGPU_BUFFER_LOAD_FORMAT_D16 : BufferLoadGenericInstruction; 2178def G_AMDGPU_TBUFFER_LOAD_FORMAT : TBufferLoadGenericInstruction; 2179def G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 : TBufferLoadGenericInstruction; 2180 2181class BufferStoreGenericInstruction : AMDGPUGenericInstruction { 2182 let OutOperandList = (outs); 2183 let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset, 2184 type2:$soffset, untyped_imm_0:$offset, 2185 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2186 let hasSideEffects = 0; 2187 let mayStore = 1; 2188} 2189 2190class TBufferStoreGenericInstruction : AMDGPUGenericInstruction { 2191 let OutOperandList = (outs); 2192 let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset, 2193 type2:$soffset, untyped_imm_0:$offset, 2194 untyped_imm_0:$format, 2195 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2196 let hasSideEffects = 0; 2197 let mayStore = 1; 2198} 2199 2200def G_AMDGPU_BUFFER_STORE : BufferStoreGenericInstruction; 2201def G_AMDGPU_BUFFER_STORE_BYTE : BufferStoreGenericInstruction; 2202def G_AMDGPU_BUFFER_STORE_SHORT : BufferStoreGenericInstruction; 2203def G_AMDGPU_BUFFER_STORE_FORMAT : BufferStoreGenericInstruction; 2204def G_AMDGPU_BUFFER_STORE_FORMAT_D16 : BufferStoreGenericInstruction; 2205def G_AMDGPU_TBUFFER_STORE_FORMAT : TBufferStoreGenericInstruction; 2206def G_AMDGPU_TBUFFER_STORE_FORMAT_D16 : TBufferStoreGenericInstruction; 2207 2208def G_AMDGPU_FMIN_LEGACY : AMDGPUGenericInstruction { 2209 let OutOperandList = (outs type0:$dst); 2210 let InOperandList = (ins type0:$src0, type0:$src1); 2211 let hasSideEffects = 0; 2212} 2213 2214def G_AMDGPU_FMAX_LEGACY : AMDGPUGenericInstruction { 2215 let OutOperandList = (outs type0:$dst); 2216 let InOperandList = (ins type0:$src0, type0:$src1); 2217 let hasSideEffects = 0; 2218} 2219 2220// Atomic cmpxchg. $cmpval ad $newval are packed in a single vector 2221// operand Expects a MachineMemOperand in addition to explicit 2222// operands. 2223def G_AMDGPU_ATOMIC_CMPXCHG : AMDGPUGenericInstruction { 2224 let OutOperandList = (outs type0:$oldval); 2225 let InOperandList = (ins ptype1:$addr, type0:$cmpval_newval); 2226 let hasSideEffects = 0; 2227 let mayLoad = 1; 2228 let mayStore = 1; 2229} 2230 2231let Namespace = "AMDGPU" in { 2232def G_AMDGPU_ATOMIC_INC : G_ATOMICRMW_OP; 2233def G_AMDGPU_ATOMIC_DEC : G_ATOMICRMW_OP; 2234} 2235 2236class BufferAtomicGenericInstruction : AMDGPUGenericInstruction { 2237 let OutOperandList = (outs type0:$dst); 2238 let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset, 2239 type2:$soffset, untyped_imm_0:$offset, 2240 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2241 let hasSideEffects = 0; 2242 let mayLoad = 1; 2243 let mayStore = 1; 2244} 2245 2246def G_AMDGPU_BUFFER_ATOMIC_SWAP : BufferAtomicGenericInstruction; 2247def G_AMDGPU_BUFFER_ATOMIC_ADD : BufferAtomicGenericInstruction; 2248def G_AMDGPU_BUFFER_ATOMIC_SUB : BufferAtomicGenericInstruction; 2249def G_AMDGPU_BUFFER_ATOMIC_SMIN : BufferAtomicGenericInstruction; 2250def G_AMDGPU_BUFFER_ATOMIC_UMIN : BufferAtomicGenericInstruction; 2251def G_AMDGPU_BUFFER_ATOMIC_SMAX : BufferAtomicGenericInstruction; 2252def G_AMDGPU_BUFFER_ATOMIC_UMAX : BufferAtomicGenericInstruction; 2253def G_AMDGPU_BUFFER_ATOMIC_AND : BufferAtomicGenericInstruction; 2254def G_AMDGPU_BUFFER_ATOMIC_OR : BufferAtomicGenericInstruction; 2255def G_AMDGPU_BUFFER_ATOMIC_XOR : BufferAtomicGenericInstruction; 2256def G_AMDGPU_BUFFER_ATOMIC_INC : BufferAtomicGenericInstruction; 2257def G_AMDGPU_BUFFER_ATOMIC_DEC : BufferAtomicGenericInstruction; 2258 2259def G_AMDGPU_BUFFER_ATOMIC_CMPSWAP : AMDGPUGenericInstruction { 2260 let OutOperandList = (outs type0:$dst); 2261 let InOperandList = (ins type0:$vdata, type0:$cmp, type1:$rsrc, type2:$vindex, 2262 type2:$voffset, type2:$soffset, untyped_imm_0:$offset, 2263 untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen); 2264 let hasSideEffects = 0; 2265 let mayLoad = 1; 2266 let mayStore = 1; 2267} 2268