1//===-- SIInstructions.td - SI 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// This file was originally auto-generated from a GPU register header file and 10// all the instruction definitions were originally commented out. Instructions 11// that are not yet supported remain commented out. 12//===----------------------------------------------------------------------===// 13 14class GCNPat<dag pattern, dag result> : Pat<pattern, result>, GCNPredicateControl { 15 let SubtargetPredicate = isGCN; 16} 17 18include "SOPInstructions.td" 19include "VOPInstructions.td" 20include "SMInstructions.td" 21include "FLATInstructions.td" 22include "BUFInstructions.td" 23 24//===----------------------------------------------------------------------===// 25// EXP Instructions 26//===----------------------------------------------------------------------===// 27 28defm EXP : EXP_m<0, AMDGPUexport>; 29defm EXP_DONE : EXP_m<1, AMDGPUexport_done>; 30 31//===----------------------------------------------------------------------===// 32// VINTRP Instructions 33//===----------------------------------------------------------------------===// 34 35// Used to inject printing of "_e32" suffix for VI (there are "_e64" variants for VI) 36def VINTRPDst : VINTRPDstOperand <VGPR_32>; 37 38let Uses = [M0, EXEC] in { 39 40// FIXME: Specify SchedRW for VINTRP insturctions. 41 42multiclass V_INTERP_P1_F32_m : VINTRP_m < 43 0x00000000, 44 (outs VINTRPDst:$vdst), 45 (ins VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 46 "v_interp_p1_f32$vdst, $vsrc, $attr$attrchan", 47 [(set f32:$vdst, (AMDGPUinterp_p1 f32:$vsrc, (i32 imm:$attrchan), 48 (i32 imm:$attr)))] 49>; 50 51let OtherPredicates = [has32BankLDS] in { 52 53defm V_INTERP_P1_F32 : V_INTERP_P1_F32_m; 54 55} // End OtherPredicates = [has32BankLDS] 56 57let OtherPredicates = [has16BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 in { 58 59defm V_INTERP_P1_F32_16bank : V_INTERP_P1_F32_m; 60 61} // End OtherPredicates = [has32BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 62 63let DisableEncoding = "$src0", Constraints = "$src0 = $vdst" in { 64 65defm V_INTERP_P2_F32 : VINTRP_m < 66 0x00000001, 67 (outs VINTRPDst:$vdst), 68 (ins VGPR_32:$src0, VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 69 "v_interp_p2_f32$vdst, $vsrc, $attr$attrchan", 70 [(set f32:$vdst, (AMDGPUinterp_p2 f32:$src0, f32:$vsrc, (i32 imm:$attrchan), 71 (i32 imm:$attr)))]>; 72 73} // End DisableEncoding = "$src0", Constraints = "$src0 = $vdst" 74 75defm V_INTERP_MOV_F32 : VINTRP_m < 76 0x00000002, 77 (outs VINTRPDst:$vdst), 78 (ins InterpSlot:$vsrc, Attr:$attr, AttrChan:$attrchan), 79 "v_interp_mov_f32$vdst, $vsrc, $attr$attrchan", 80 [(set f32:$vdst, (AMDGPUinterp_mov (i32 imm:$vsrc), (i32 imm:$attrchan), 81 (i32 imm:$attr)))]>; 82 83} // End Uses = [M0, EXEC] 84 85//===----------------------------------------------------------------------===// 86// Pseudo Instructions 87//===----------------------------------------------------------------------===// 88def ATOMIC_FENCE : SPseudoInstSI< 89 (outs), (ins i32imm:$ordering, i32imm:$scope), 90 [(atomic_fence (i32 imm:$ordering), (i32 imm:$scope))], 91 "ATOMIC_FENCE $ordering, $scope"> { 92 let hasSideEffects = 1; 93 let maybeAtomic = 1; 94} 95 96let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] in { 97 98// For use in patterns 99def V_CNDMASK_B64_PSEUDO : VOP3Common <(outs VReg_64:$vdst), 100 (ins VSrc_b64:$src0, VSrc_b64:$src1, SSrc_b64:$src2), "", []> { 101 let isPseudo = 1; 102 let isCodeGenOnly = 1; 103 let usesCustomInserter = 1; 104} 105 106// 64-bit vector move instruction. This is mainly used by the 107// SIFoldOperands pass to enable folding of inline immediates. 108def V_MOV_B64_PSEUDO : VPseudoInstSI <(outs VReg_64:$vdst), 109 (ins VSrc_b64:$src0)>; 110 111// Pseudoinstruction for @llvm.amdgcn.wqm. It is turned into a copy after the 112// WQM pass processes it. 113def WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>; 114 115// Pseudoinstruction for @llvm.amdgcn.wwm. It is turned into a copy post-RA, so 116// that the @earlyclobber is respected. The @earlyclobber is to make sure that 117// the instruction that defines $src0 (which is run in WWM) doesn't 118// accidentally clobber inactive channels of $vdst. 119let Constraints = "@earlyclobber $vdst" in { 120def WWM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>; 121} 122 123} // End let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] 124 125def EXIT_WWM : SPseudoInstSI <(outs SReg_64:$sdst), (ins SReg_64:$src0)> { 126 let hasSideEffects = 0; 127 let mayLoad = 0; 128 let mayStore = 0; 129} 130 131// Invert the exec mask and overwrite the inactive lanes of dst with inactive, 132// restoring it after we're done. 133def V_SET_INACTIVE_B32 : VPseudoInstSI <(outs VGPR_32:$vdst), 134 (ins VGPR_32: $src, VSrc_b32:$inactive), 135 [(set i32:$vdst, (int_amdgcn_set_inactive i32:$src, i32:$inactive))]> { 136 let Constraints = "$src = $vdst"; 137} 138 139def V_SET_INACTIVE_B64 : VPseudoInstSI <(outs VReg_64:$vdst), 140 (ins VReg_64: $src, VSrc_b64:$inactive), 141 [(set i64:$vdst, (int_amdgcn_set_inactive i64:$src, i64:$inactive))]> { 142 let Constraints = "$src = $vdst"; 143} 144 145 146let usesCustomInserter = 1, Defs = [SCC] in { 147def S_ADD_U64_PSEUDO : SPseudoInstSI < 148 (outs SReg_64:$vdst), (ins SSrc_b64:$src0, SSrc_b64:$src1), 149 [(set SReg_64:$vdst, (add i64:$src0, i64:$src1))] 150>; 151 152def S_SUB_U64_PSEUDO : SPseudoInstSI < 153 (outs SReg_64:$vdst), (ins SSrc_b64:$src0, SSrc_b64:$src1), 154 [(set SReg_64:$vdst, (sub i64:$src0, i64:$src1))] 155>; 156 157def S_ADD_U64_CO_PSEUDO : SPseudoInstSI < 158 (outs SReg_64:$vdst, VOPDstS64:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1) 159>; 160 161def S_SUB_U64_CO_PSEUDO : SPseudoInstSI < 162 (outs SReg_64:$vdst, VOPDstS64:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1) 163>; 164 165} // End usesCustomInserter = 1, Defs = [SCC] 166 167let usesCustomInserter = 1 in { 168def GET_GROUPSTATICSIZE : SPseudoInstSI <(outs SReg_32:$sdst), (ins), 169 [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>; 170} // End let usesCustomInserter = 1, SALU = 1 171 172def S_MOV_B64_term : SPseudoInstSI<(outs SReg_64:$dst), 173 (ins SSrc_b64:$src0)> { 174 let isAsCheapAsAMove = 1; 175 let isTerminator = 1; 176} 177 178def S_XOR_B64_term : SPseudoInstSI<(outs SReg_64:$dst), 179 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 180 let isAsCheapAsAMove = 1; 181 let isTerminator = 1; 182 let Defs = [SCC]; 183} 184 185def S_ANDN2_B64_term : SPseudoInstSI<(outs SReg_64:$dst), 186 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 187 let isAsCheapAsAMove = 1; 188 let isTerminator = 1; 189} 190 191def WAVE_BARRIER : SPseudoInstSI<(outs), (ins), 192 [(int_amdgcn_wave_barrier)]> { 193 let SchedRW = []; 194 let hasNoSchedulingInfo = 1; 195 let hasSideEffects = 1; 196 let mayLoad = 1; 197 let mayStore = 1; 198 let isBarrier = 1; 199 let isConvergent = 1; 200 let FixedSize = 1; 201 let Size = 0; 202} 203 204// SI pseudo instructions. These are used by the CFG structurizer pass 205// and should be lowered to ISA instructions prior to codegen. 206 207// Dummy terminator instruction to use after control flow instructions 208// replaced with exec mask operations. 209def SI_MASK_BRANCH : VPseudoInstSI < 210 (outs), (ins brtarget:$target)> { 211 let isBranch = 0; 212 let isTerminator = 1; 213 let isBarrier = 0; 214 let SchedRW = []; 215 let hasNoSchedulingInfo = 1; 216 let FixedSize = 1; 217 let Size = 0; 218} 219 220let isTerminator = 1 in { 221 222let OtherPredicates = [EnableLateCFGStructurize] in { 223 def SI_NON_UNIFORM_BRCOND_PSEUDO : CFPseudoInstSI < 224 (outs), 225 (ins SReg_64:$vcc, brtarget:$target), 226 [(brcond i1:$vcc, bb:$target)]> { 227 let Size = 12; 228} 229} 230 231def SI_IF: CFPseudoInstSI < 232 (outs SReg_64:$dst), (ins SReg_64:$vcc, brtarget:$target), 233 [(set i64:$dst, (AMDGPUif i1:$vcc, bb:$target))], 1, 1> { 234 let Constraints = ""; 235 let Size = 12; 236 let hasSideEffects = 1; 237} 238 239def SI_ELSE : CFPseudoInstSI < 240 (outs SReg_64:$dst), 241 (ins SReg_64:$src, brtarget:$target, i1imm:$execfix), [], 1, 1> { 242 let Size = 12; 243 let hasSideEffects = 1; 244} 245 246def SI_LOOP : CFPseudoInstSI < 247 (outs), (ins SReg_64:$saved, brtarget:$target), 248 [(AMDGPUloop i64:$saved, bb:$target)], 1, 1> { 249 let Size = 8; 250 let isBranch = 0; 251 let hasSideEffects = 1; 252} 253 254} // End isTerminator = 1 255 256def SI_END_CF : CFPseudoInstSI < 257 (outs), (ins SReg_64:$saved), 258 [(int_amdgcn_end_cf i64:$saved)], 1, 1> { 259 let Size = 4; 260 let isAsCheapAsAMove = 1; 261 let isReMaterializable = 1; 262 let hasSideEffects = 1; 263 let mayLoad = 1; // FIXME: Should not need memory flags 264 let mayStore = 1; 265} 266 267def SI_BREAK : CFPseudoInstSI < 268 (outs SReg_64:$dst), (ins SReg_64:$src), 269 [(set i64:$dst, (int_amdgcn_break i64:$src))], 1> { 270 let Size = 4; 271 let isAsCheapAsAMove = 1; 272 let isReMaterializable = 1; 273} 274 275def SI_IF_BREAK : CFPseudoInstSI < 276 (outs SReg_64:$dst), (ins SReg_64:$vcc, SReg_64:$src), 277 [(set i64:$dst, (int_amdgcn_if_break i1:$vcc, i64:$src))]> { 278 let Size = 4; 279 let isAsCheapAsAMove = 1; 280 let isReMaterializable = 1; 281} 282 283def SI_ELSE_BREAK : CFPseudoInstSI < 284 (outs SReg_64:$dst), (ins SReg_64:$src0, SReg_64:$src1), 285 [(set i64:$dst, (int_amdgcn_else_break i64:$src0, i64:$src1))]> { 286 let Size = 4; 287 let isAsCheapAsAMove = 1; 288 let isReMaterializable = 1; 289} 290 291let Uses = [EXEC] in { 292 293multiclass PseudoInstKill <dag ins> { 294 // Even though this pseudo can usually be expanded without an SCC def, we 295 // conservatively assume that it has an SCC def, both because it is sometimes 296 // required in degenerate cases (when V_CMPX cannot be used due to constant 297 // bus limitations) and because it allows us to avoid having to track SCC 298 // liveness across basic blocks. 299 let Defs = [EXEC,VCC,SCC] in 300 def _PSEUDO : PseudoInstSI <(outs), ins> { 301 let isConvergent = 1; 302 let usesCustomInserter = 1; 303 } 304 305 let Defs = [EXEC,VCC,SCC] in 306 def _TERMINATOR : SPseudoInstSI <(outs), ins> { 307 let isTerminator = 1; 308 } 309} 310 311defm SI_KILL_I1 : PseudoInstKill <(ins SSrc_b64:$src, i1imm:$killvalue)>; 312defm SI_KILL_F32_COND_IMM : PseudoInstKill <(ins VSrc_b32:$src0, i32imm:$src1, i32imm:$cond)>; 313 314let Defs = [EXEC,VCC] in 315def SI_ILLEGAL_COPY : SPseudoInstSI < 316 (outs unknown:$dst), (ins unknown:$src), 317 [], " ; illegal copy $src to $dst">; 318 319} // End Uses = [EXEC], Defs = [EXEC,VCC] 320 321// Branch on undef scc. Used to avoid intermediate copy from 322// IMPLICIT_DEF to SCC. 323def SI_BR_UNDEF : SPseudoInstSI <(outs), (ins sopp_brtarget:$simm16)> { 324 let isTerminator = 1; 325 let usesCustomInserter = 1; 326} 327 328def SI_PS_LIVE : PseudoInstSI < 329 (outs SReg_64:$dst), (ins), 330 [(set i1:$dst, (int_amdgcn_ps_live))]> { 331 let SALU = 1; 332} 333 334def SI_MASKED_UNREACHABLE : SPseudoInstSI <(outs), (ins), 335 [(int_amdgcn_unreachable)], 336 "; divergent unreachable"> { 337 let Size = 0; 338 let hasNoSchedulingInfo = 1; 339 let FixedSize = 1; 340} 341 342// Used as an isel pseudo to directly emit initialization with an 343// s_mov_b32 rather than a copy of another initialized 344// register. MachineCSE skips copies, and we don't want to have to 345// fold operands before it runs. 346def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> { 347 let Defs = [M0]; 348 let usesCustomInserter = 1; 349 let isAsCheapAsAMove = 1; 350 let isReMaterializable = 1; 351} 352 353def SI_INIT_EXEC : SPseudoInstSI < 354 (outs), (ins i64imm:$src), []> { 355 let Defs = [EXEC]; 356 let usesCustomInserter = 1; 357 let isAsCheapAsAMove = 1; 358} 359 360def SI_INIT_EXEC_FROM_INPUT : SPseudoInstSI < 361 (outs), (ins SSrc_b32:$input, i32imm:$shift), []> { 362 let Defs = [EXEC]; 363 let usesCustomInserter = 1; 364} 365 366// Return for returning shaders to a shader variant epilog. 367def SI_RETURN_TO_EPILOG : SPseudoInstSI < 368 (outs), (ins variable_ops), [(AMDGPUreturn_to_epilog)]> { 369 let isTerminator = 1; 370 let isBarrier = 1; 371 let isReturn = 1; 372 let hasNoSchedulingInfo = 1; 373 let DisableWQM = 1; 374 let FixedSize = 1; 375} 376 377// Return for returning function calls. 378def SI_RETURN : SPseudoInstSI < 379 (outs), (ins), [], 380 "; return"> { 381 let isTerminator = 1; 382 let isBarrier = 1; 383 let isReturn = 1; 384 let SchedRW = [WriteBranch]; 385} 386 387// Return for returning function calls without output register. 388// 389// This version is only needed so we can fill in the output regiter in 390// the custom inserter. 391def SI_CALL_ISEL : SPseudoInstSI < 392 (outs), (ins SSrc_b64:$src0), [(AMDGPUcall i64:$src0)]> { 393 let Size = 4; 394 let isCall = 1; 395 let SchedRW = [WriteBranch]; 396 let usesCustomInserter = 1; 397} 398 399// Wrapper around s_swappc_b64 with extra $callee parameter to track 400// the called function after regalloc. 401def SI_CALL : SPseudoInstSI < 402 (outs SReg_64:$dst), (ins SSrc_b64:$src0, unknown:$callee)> { 403 let Size = 4; 404 let isCall = 1; 405 let UseNamedOperandTable = 1; 406 let SchedRW = [WriteBranch]; 407} 408 409// Tail call handling pseudo 410def SI_TCRETURN_ISEL : SPseudoInstSI<(outs), 411 (ins SSrc_b64:$src0, i32imm:$fpdiff), 412 [(AMDGPUtc_return i64:$src0, i32:$fpdiff)]> { 413 let isCall = 1; 414 let isTerminator = 1; 415 let isReturn = 1; 416 let isBarrier = 1; 417 let SchedRW = [WriteBranch]; 418 let usesCustomInserter = 1; 419} 420 421def SI_TCRETURN : SPseudoInstSI < 422 (outs), 423 (ins SSrc_b64:$src0, unknown:$callee, i32imm:$fpdiff)> { 424 let Size = 4; 425 let isCall = 1; 426 let isTerminator = 1; 427 let isReturn = 1; 428 let isBarrier = 1; 429 let UseNamedOperandTable = 1; 430 let SchedRW = [WriteBranch]; 431} 432 433 434def ADJCALLSTACKUP : SPseudoInstSI< 435 (outs), (ins i32imm:$amt0, i32imm:$amt1), 436 [(callseq_start timm:$amt0, timm:$amt1)], 437 "; adjcallstackup $amt0 $amt1"> { 438 let Size = 8; // Worst case. (s_add_u32 + constant) 439 let FixedSize = 1; 440 let hasSideEffects = 1; 441 let usesCustomInserter = 1; 442} 443 444def ADJCALLSTACKDOWN : SPseudoInstSI< 445 (outs), (ins i32imm:$amt1, i32imm:$amt2), 446 [(callseq_end timm:$amt1, timm:$amt2)], 447 "; adjcallstackdown $amt1"> { 448 let Size = 8; // Worst case. (s_add_u32 + constant) 449 let hasSideEffects = 1; 450 let usesCustomInserter = 1; 451} 452 453let Defs = [M0, EXEC, SCC], 454 UseNamedOperandTable = 1 in { 455 456class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI < 457 (outs VGPR_32:$vdst), 458 (ins rc:$src, VS_32:$idx, i32imm:$offset)> { 459 let usesCustomInserter = 1; 460} 461 462class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI < 463 (outs rc:$vdst), 464 (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> { 465 let Constraints = "$src = $vdst"; 466 let usesCustomInserter = 1; 467} 468 469// TODO: We can support indirect SGPR access. 470def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>; 471def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>; 472def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>; 473def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>; 474def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>; 475 476def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>; 477def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>; 478def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>; 479def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>; 480def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>; 481 482} // End Uses = [EXEC], Defs = [M0, EXEC] 483 484multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> { 485 let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in { 486 def _SAVE : PseudoInstSI < 487 (outs), 488 (ins sgpr_class:$data, i32imm:$addr)> { 489 let mayStore = 1; 490 let mayLoad = 0; 491 } 492 493 def _RESTORE : PseudoInstSI < 494 (outs sgpr_class:$data), 495 (ins i32imm:$addr)> { 496 let mayStore = 0; 497 let mayLoad = 1; 498 } 499 } // End UseNamedOperandTable = 1 500} 501 502// You cannot use M0 as the output of v_readlane_b32 instructions or 503// use it in the sdata operand of SMEM instructions. We still need to 504// be able to spill the physical register m0, so allow it for 505// SI_SPILL_32_* instructions. 506defm SI_SPILL_S32 : SI_SPILL_SGPR <SReg_32>; 507defm SI_SPILL_S64 : SI_SPILL_SGPR <SReg_64>; 508defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>; 509defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>; 510defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>; 511 512multiclass SI_SPILL_VGPR <RegisterClass vgpr_class> { 513 let UseNamedOperandTable = 1, VGPRSpill = 1, 514 SchedRW = [WriteVMEM] in { 515 def _SAVE : VPseudoInstSI < 516 (outs), 517 (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc, 518 SReg_32:$soffset, i32imm:$offset)> { 519 let mayStore = 1; 520 let mayLoad = 0; 521 // (2 * 4) + (8 * num_subregs) bytes maximum 522 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 523 } 524 525 def _RESTORE : VPseudoInstSI < 526 (outs vgpr_class:$vdata), 527 (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset, 528 i32imm:$offset)> { 529 let mayStore = 0; 530 let mayLoad = 1; 531 532 // (2 * 4) + (8 * num_subregs) bytes maximum 533 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 534 } 535 } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM] 536} 537 538defm SI_SPILL_V32 : SI_SPILL_VGPR <VGPR_32>; 539defm SI_SPILL_V64 : SI_SPILL_VGPR <VReg_64>; 540defm SI_SPILL_V96 : SI_SPILL_VGPR <VReg_96>; 541defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>; 542defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>; 543defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>; 544 545def SI_PC_ADD_REL_OFFSET : SPseudoInstSI < 546 (outs SReg_64:$dst), 547 (ins si_ga:$ptr_lo, si_ga:$ptr_hi), 548 [(set SReg_64:$dst, 549 (i64 (SIpc_add_rel_offset (tglobaladdr:$ptr_lo), (tglobaladdr:$ptr_hi))))]> { 550 let Defs = [SCC]; 551} 552 553def : GCNPat < 554 (AMDGPUinit_exec i64:$src), 555 (SI_INIT_EXEC (as_i64imm $src)) 556>; 557 558def : GCNPat < 559 (AMDGPUinit_exec_from_input i32:$input, i32:$shift), 560 (SI_INIT_EXEC_FROM_INPUT (i32 $input), (as_i32imm $shift)) 561>; 562 563def : GCNPat< 564 (AMDGPUtrap timm:$trapid), 565 (S_TRAP $trapid) 566>; 567 568def : GCNPat< 569 (AMDGPUelse i64:$src, bb:$target), 570 (SI_ELSE $src, $target, 0) 571>; 572 573def : Pat < 574 // -1.0 as i32 (LowerINTRINSIC_VOID converts all other constants to -1.0) 575 (AMDGPUkill (i32 -1082130432)), 576 (SI_KILL_I1_PSEUDO (i1 0), 0) 577>; 578 579def : Pat < 580 (int_amdgcn_kill i1:$src), 581 (SI_KILL_I1_PSEUDO $src, 0) 582>; 583 584def : Pat < 585 (int_amdgcn_kill (i1 (not i1:$src))), 586 (SI_KILL_I1_PSEUDO $src, -1) 587>; 588 589def : Pat < 590 (AMDGPUkill i32:$src), 591 (SI_KILL_F32_COND_IMM_PSEUDO $src, 0, 3) // 3 means SETOGE 592>; 593 594def : Pat < 595 (int_amdgcn_kill (i1 (setcc f32:$src, InlineFPImm<f32>:$imm, cond:$cond))), 596 (SI_KILL_F32_COND_IMM_PSEUDO $src, (bitcast_fpimm_to_i32 $imm), (cond_as_i32imm $cond)) 597>; 598// TODO: we could add more variants for other types of conditionals 599 600//===----------------------------------------------------------------------===// 601// VOP1 Patterns 602//===----------------------------------------------------------------------===// 603 604let SubtargetPredicate = isGCN, OtherPredicates = [UnsafeFPMath] in { 605 606//def : RcpPat<V_RCP_F64_e32, f64>; 607//defm : RsqPat<V_RSQ_F64_e32, f64>; 608//defm : RsqPat<V_RSQ_F32_e32, f32>; 609 610def : RsqPat<V_RSQ_F32_e32, f32>; 611def : RsqPat<V_RSQ_F64_e32, f64>; 612 613// Convert (x - floor(x)) to fract(x) 614def : GCNPat < 615 (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)), 616 (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))), 617 (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 618>; 619 620// Convert (x + (-floor(x))) to fract(x) 621def : GCNPat < 622 (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)), 623 (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))), 624 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 625>; 626 627} // End SubtargetPredicate = isGCN, OtherPredicates = [UnsafeFPMath] 628 629 630// f16_to_fp patterns 631def : GCNPat < 632 (f32 (f16_to_fp i32:$src0)), 633 (V_CVT_F32_F16_e64 SRCMODS.NONE, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 634>; 635 636def : GCNPat < 637 (f32 (f16_to_fp (and_oneuse i32:$src0, 0x7fff))), 638 (V_CVT_F32_F16_e64 SRCMODS.ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 639>; 640 641def : GCNPat < 642 (f32 (f16_to_fp (i32 (srl_oneuse (and_oneuse i32:$src0, 0x7fff0000), (i32 16))))), 643 (V_CVT_F32_F16_e64 SRCMODS.ABS, (i32 (V_LSHRREV_B32_e64 (i32 16), i32:$src0)), DSTCLAMP.NONE, DSTOMOD.NONE) 644>; 645 646def : GCNPat < 647 (f32 (f16_to_fp (or_oneuse i32:$src0, 0x8000))), 648 (V_CVT_F32_F16_e64 SRCMODS.NEG_ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 649>; 650 651def : GCNPat < 652 (f32 (f16_to_fp (xor_oneuse i32:$src0, 0x8000))), 653 (V_CVT_F32_F16_e64 SRCMODS.NEG, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 654>; 655 656def : GCNPat < 657 (f64 (fpextend f16:$src)), 658 (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src)) 659>; 660 661// fp_to_fp16 patterns 662def : GCNPat < 663 (i32 (AMDGPUfp_to_f16 (f32 (VOP3Mods f32:$src0, i32:$src0_modifiers)))), 664 (V_CVT_F16_F32_e64 $src0_modifiers, f32:$src0, DSTCLAMP.NONE, DSTOMOD.NONE) 665>; 666 667def : GCNPat < 668 (i32 (fp_to_sint f16:$src)), 669 (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 $src)) 670>; 671 672def : GCNPat < 673 (i32 (fp_to_uint f16:$src)), 674 (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 $src)) 675>; 676 677def : GCNPat < 678 (f16 (sint_to_fp i32:$src)), 679 (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 $src)) 680>; 681 682def : GCNPat < 683 (f16 (uint_to_fp i32:$src)), 684 (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 $src)) 685>; 686 687//===----------------------------------------------------------------------===// 688// VOP2 Patterns 689//===----------------------------------------------------------------------===// 690 691multiclass FMADPat <ValueType vt, Instruction inst> { 692 def : GCNPat < 693 (vt (fmad (VOP3NoMods vt:$src0), 694 (VOP3NoMods vt:$src1), 695 (VOP3NoMods vt:$src2))), 696 (inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1, 697 SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 698 >; 699} 700 701defm : FMADPat <f16, V_MAC_F16_e64>; 702defm : FMADPat <f32, V_MAC_F32_e64>; 703 704class FMADModsPat<Instruction inst, SDPatternOperator mad_opr, ValueType Ty> 705 : GCNPat< 706 (Ty (mad_opr (VOP3Mods Ty:$src0, i32:$src0_mod), 707 (VOP3Mods Ty:$src1, i32:$src1_mod), 708 (VOP3Mods Ty:$src2, i32:$src2_mod))), 709 (inst $src0_mod, $src0, $src1_mod, $src1, 710 $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 711>; 712 713def : FMADModsPat<V_MAD_F32, AMDGPUfmad_ftz, f32>; 714def : FMADModsPat<V_MAD_F16, AMDGPUfmad_ftz, f16> { 715 let SubtargetPredicate = Has16BitInsts; 716} 717 718multiclass SelectPat <ValueType vt, Instruction inst> { 719 def : GCNPat < 720 (vt (select i1:$src0, vt:$src1, vt:$src2)), 721 (inst $src2, $src1, $src0) 722 >; 723} 724 725defm : SelectPat <i16, V_CNDMASK_B32_e64>; 726defm : SelectPat <i32, V_CNDMASK_B32_e64>; 727defm : SelectPat <f16, V_CNDMASK_B32_e64>; 728defm : SelectPat <f32, V_CNDMASK_B32_e64>; 729 730let AddedComplexity = 1 in { 731def : GCNPat < 732 (i32 (add (i32 (getDivergentFrag<ctpop>.ret i32:$popcnt)), i32:$val)), 733 (V_BCNT_U32_B32_e64 $popcnt, $val) 734>; 735} 736def : GCNPat < 737 (i16 (add (i16 (trunc (getDivergentFrag<ctpop>.ret i32:$popcnt))), i16:$val)), 738 (V_BCNT_U32_B32_e64 $popcnt, $val) 739>; 740 741/********** ============================================ **********/ 742/********** Extraction, Insertion, Building and Casting **********/ 743/********** ============================================ **********/ 744 745foreach Index = 0-2 in { 746 def Extract_Element_v2i32_#Index : Extract_Element < 747 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 748 >; 749 def Insert_Element_v2i32_#Index : Insert_Element < 750 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 751 >; 752 753 def Extract_Element_v2f32_#Index : Extract_Element < 754 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 755 >; 756 def Insert_Element_v2f32_#Index : Insert_Element < 757 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 758 >; 759} 760 761foreach Index = 0-3 in { 762 def Extract_Element_v4i32_#Index : Extract_Element < 763 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 764 >; 765 def Insert_Element_v4i32_#Index : Insert_Element < 766 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 767 >; 768 769 def Extract_Element_v4f32_#Index : Extract_Element < 770 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 771 >; 772 def Insert_Element_v4f32_#Index : Insert_Element < 773 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 774 >; 775} 776 777foreach Index = 0-7 in { 778 def Extract_Element_v8i32_#Index : Extract_Element < 779 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 780 >; 781 def Insert_Element_v8i32_#Index : Insert_Element < 782 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 783 >; 784 785 def Extract_Element_v8f32_#Index : Extract_Element < 786 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 787 >; 788 def Insert_Element_v8f32_#Index : Insert_Element < 789 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 790 >; 791} 792 793foreach Index = 0-15 in { 794 def Extract_Element_v16i32_#Index : Extract_Element < 795 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 796 >; 797 def Insert_Element_v16i32_#Index : Insert_Element < 798 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 799 >; 800 801 def Extract_Element_v16f32_#Index : Extract_Element < 802 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 803 >; 804 def Insert_Element_v16f32_#Index : Insert_Element < 805 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 806 >; 807} 808 809 810def : Pat < 811 (extract_subvector v4i16:$vec, (i32 0)), 812 (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub0)) 813>; 814 815def : Pat < 816 (extract_subvector v4i16:$vec, (i32 2)), 817 (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub1)) 818>; 819 820def : Pat < 821 (extract_subvector v4f16:$vec, (i32 0)), 822 (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub0)) 823>; 824 825def : Pat < 826 (extract_subvector v4f16:$vec, (i32 2)), 827 (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub1)) 828>; 829 830let SubtargetPredicate = isGCN in { 831 832// FIXME: Why do only some of these type combinations for SReg and 833// VReg? 834// 16-bit bitcast 835def : BitConvert <i16, f16, VGPR_32>; 836def : BitConvert <f16, i16, VGPR_32>; 837def : BitConvert <i16, f16, SReg_32>; 838def : BitConvert <f16, i16, SReg_32>; 839 840// 32-bit bitcast 841def : BitConvert <i32, f32, VGPR_32>; 842def : BitConvert <f32, i32, VGPR_32>; 843def : BitConvert <i32, f32, SReg_32>; 844def : BitConvert <f32, i32, SReg_32>; 845def : BitConvert <v2i16, i32, SReg_32>; 846def : BitConvert <i32, v2i16, SReg_32>; 847def : BitConvert <v2f16, i32, SReg_32>; 848def : BitConvert <i32, v2f16, SReg_32>; 849def : BitConvert <v2i16, v2f16, SReg_32>; 850def : BitConvert <v2f16, v2i16, SReg_32>; 851def : BitConvert <v2f16, f32, SReg_32>; 852def : BitConvert <f32, v2f16, SReg_32>; 853def : BitConvert <v2i16, f32, SReg_32>; 854def : BitConvert <f32, v2i16, SReg_32>; 855 856// 64-bit bitcast 857def : BitConvert <i64, f64, VReg_64>; 858def : BitConvert <f64, i64, VReg_64>; 859def : BitConvert <v2i32, v2f32, VReg_64>; 860def : BitConvert <v2f32, v2i32, VReg_64>; 861def : BitConvert <i64, v2i32, VReg_64>; 862def : BitConvert <v2i32, i64, VReg_64>; 863def : BitConvert <i64, v2f32, VReg_64>; 864def : BitConvert <v2f32, i64, VReg_64>; 865def : BitConvert <f64, v2f32, VReg_64>; 866def : BitConvert <v2f32, f64, VReg_64>; 867def : BitConvert <f64, v2i32, VReg_64>; 868def : BitConvert <v2i32, f64, VReg_64>; 869 870// FIXME: Make SGPR 871def : BitConvert <v2i32, v4f16, VReg_64>; 872def : BitConvert <v4f16, v2i32, VReg_64>; 873def : BitConvert <v2i32, v4f16, VReg_64>; 874def : BitConvert <v2i32, v4i16, VReg_64>; 875def : BitConvert <v4i16, v2i32, VReg_64>; 876def : BitConvert <v2f32, v4f16, VReg_64>; 877def : BitConvert <v4f16, v2f32, VReg_64>; 878def : BitConvert <v2f32, v4i16, VReg_64>; 879def : BitConvert <v4i16, v2f32, VReg_64>; 880def : BitConvert <v4i16, f64, VReg_64>; 881def : BitConvert <v4f16, f64, VReg_64>; 882def : BitConvert <f64, v4i16, VReg_64>; 883def : BitConvert <f64, v4f16, VReg_64>; 884def : BitConvert <v4i16, i64, VReg_64>; 885def : BitConvert <v4f16, i64, VReg_64>; 886def : BitConvert <i64, v4i16, VReg_64>; 887def : BitConvert <i64, v4f16, VReg_64>; 888 889def : BitConvert <v4i32, v4f32, VReg_128>; 890def : BitConvert <v4f32, v4i32, VReg_128>; 891 892// 128-bit bitcast 893def : BitConvert <v2i64, v4i32, SReg_128>; 894def : BitConvert <v4i32, v2i64, SReg_128>; 895def : BitConvert <v2f64, v4f32, VReg_128>; 896def : BitConvert <v2f64, v4i32, VReg_128>; 897def : BitConvert <v4f32, v2f64, VReg_128>; 898def : BitConvert <v4i32, v2f64, VReg_128>; 899def : BitConvert <v2i64, v2f64, VReg_128>; 900def : BitConvert <v2f64, v2i64, VReg_128>; 901 902// 256-bit bitcast 903def : BitConvert <v8i32, v8f32, SReg_256>; 904def : BitConvert <v8f32, v8i32, SReg_256>; 905def : BitConvert <v8i32, v8f32, VReg_256>; 906def : BitConvert <v8f32, v8i32, VReg_256>; 907 908// 512-bit bitcast 909def : BitConvert <v16i32, v16f32, VReg_512>; 910def : BitConvert <v16f32, v16i32, VReg_512>; 911 912} // End SubtargetPredicate = isGCN 913 914/********** =================== **********/ 915/********** Src & Dst modifiers **********/ 916/********** =================== **********/ 917 918 919// If denormals are not enabled, it only impacts the compare of the 920// inputs. The output result is not flushed. 921class ClampPat<Instruction inst, ValueType vt> : GCNPat < 922 (vt (AMDGPUclamp (VOP3Mods vt:$src0, i32:$src0_modifiers))), 923 (inst i32:$src0_modifiers, vt:$src0, 924 i32:$src0_modifiers, vt:$src0, DSTCLAMP.ENABLE, DSTOMOD.NONE) 925>; 926 927def : ClampPat<V_MAX_F32_e64, f32>; 928def : ClampPat<V_MAX_F64, f64>; 929def : ClampPat<V_MAX_F16_e64, f16>; 930 931let SubtargetPredicate = HasVOP3PInsts in { 932def : GCNPat < 933 (v2f16 (AMDGPUclamp (VOP3PMods v2f16:$src0, i32:$src0_modifiers))), 934 (V_PK_MAX_F16 $src0_modifiers, $src0, 935 $src0_modifiers, $src0, DSTCLAMP.ENABLE) 936>; 937} 938 939/********** ================================ **********/ 940/********** Floating point absolute/negative **********/ 941/********** ================================ **********/ 942 943// Prevent expanding both fneg and fabs. 944 945def : GCNPat < 946 (fneg (fabs f32:$src)), 947 (S_OR_B32 $src, (S_MOV_B32(i32 0x80000000))) // Set sign bit 948>; 949 950// FIXME: Should use S_OR_B32 951def : GCNPat < 952 (fneg (fabs f64:$src)), 953 (REG_SEQUENCE VReg_64, 954 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 955 sub0, 956 (V_OR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 957 (V_MOV_B32_e32 (i32 0x80000000))), // Set sign bit. 958 sub1) 959>; 960 961def : GCNPat < 962 (fabs f32:$src), 963 (S_AND_B32 $src, (S_MOV_B32 (i32 0x7fffffff))) 964>; 965 966def : GCNPat < 967 (fneg f32:$src), 968 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x80000000))) 969>; 970 971def : GCNPat < 972 (fabs f64:$src), 973 (REG_SEQUENCE VReg_64, 974 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 975 sub0, 976 (V_AND_B32_e64 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 977 (V_MOV_B32_e32 (i32 0x7fffffff))), // Set sign bit. 978 sub1) 979>; 980 981def : GCNPat < 982 (fneg f64:$src), 983 (REG_SEQUENCE VReg_64, 984 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 985 sub0, 986 (V_XOR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 987 (i32 (V_MOV_B32_e32 (i32 0x80000000)))), 988 sub1) 989>; 990 991def : GCNPat < 992 (fcopysign f16:$src0, f16:$src1), 993 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, $src1) 994>; 995 996def : GCNPat < 997 (fcopysign f32:$src0, f16:$src1), 998 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), $src0, 999 (V_LSHLREV_B32_e64 (i32 16), $src1)) 1000>; 1001 1002def : GCNPat < 1003 (fcopysign f64:$src0, f16:$src1), 1004 (REG_SEQUENCE SReg_64, 1005 (i32 (EXTRACT_SUBREG $src0, sub0)), sub0, 1006 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), (i32 (EXTRACT_SUBREG $src0, sub1)), 1007 (V_LSHLREV_B32_e64 (i32 16), $src1)), sub1) 1008>; 1009 1010def : GCNPat < 1011 (fcopysign f16:$src0, f32:$src1), 1012 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 1013 (V_LSHRREV_B32_e64 (i32 16), $src1)) 1014>; 1015 1016def : GCNPat < 1017 (fcopysign f16:$src0, f64:$src1), 1018 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 1019 (V_LSHRREV_B32_e64 (i32 16), (EXTRACT_SUBREG $src1, sub1))) 1020>; 1021 1022def : GCNPat < 1023 (fneg f16:$src), 1024 (S_XOR_B32 $src, (S_MOV_B32 (i32 0x00008000))) 1025>; 1026 1027def : GCNPat < 1028 (fabs f16:$src), 1029 (S_AND_B32 $src, (S_MOV_B32 (i32 0x00007fff))) 1030>; 1031 1032def : GCNPat < 1033 (fneg (fabs f16:$src)), 1034 (S_OR_B32 $src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit 1035>; 1036 1037def : GCNPat < 1038 (fneg v2f16:$src), 1039 (S_XOR_B32 $src, (S_MOV_B32 (i32 0x80008000))) 1040>; 1041 1042def : GCNPat < 1043 (fabs v2f16:$src), 1044 (S_AND_B32 $src, (S_MOV_B32 (i32 0x7fff7fff))) 1045>; 1046 1047// This is really (fneg (fabs v2f16:$src)) 1048// 1049// fabs is not reported as free because there is modifier for it in 1050// VOP3P instructions, so it is turned into the bit op. 1051def : GCNPat < 1052 (fneg (v2f16 (bitconvert (and_oneuse i32:$src, 0x7fff7fff)))), 1053 (S_OR_B32 $src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit 1054>; 1055 1056def : GCNPat < 1057 (fneg (v2f16 (fabs v2f16:$src))), 1058 (S_OR_B32 $src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit 1059>; 1060 1061/********** ================== **********/ 1062/********** Immediate Patterns **********/ 1063/********** ================== **********/ 1064 1065def : GCNPat < 1066 (VGPRImm<(i32 imm)>:$imm), 1067 (V_MOV_B32_e32 imm:$imm) 1068>; 1069 1070def : GCNPat < 1071 (VGPRImm<(f32 fpimm)>:$imm), 1072 (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm))) 1073>; 1074 1075def : GCNPat < 1076 (i32 imm:$imm), 1077 (S_MOV_B32 imm:$imm) 1078>; 1079 1080// FIXME: Workaround for ordering issue with peephole optimizer where 1081// a register class copy interferes with immediate folding. Should 1082// use s_mov_b32, which can be shrunk to s_movk_i32 1083def : GCNPat < 1084 (VGPRImm<(f16 fpimm)>:$imm), 1085 (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm))) 1086>; 1087 1088def : GCNPat < 1089 (f32 fpimm:$imm), 1090 (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm))) 1091>; 1092 1093def : GCNPat < 1094 (f16 fpimm:$imm), 1095 (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm))) 1096>; 1097 1098def : GCNPat < 1099 (i32 frameindex:$fi), 1100 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi))) 1101>; 1102 1103def : GCNPat < 1104 (i64 InlineImm<i64>:$imm), 1105 (S_MOV_B64 InlineImm<i64>:$imm) 1106>; 1107 1108// XXX - Should this use a s_cmp to set SCC? 1109 1110// Set to sign-extended 64-bit value (true = -1, false = 0) 1111def : GCNPat < 1112 (i1 imm:$imm), 1113 (S_MOV_B64 (i64 (as_i64imm $imm))) 1114>; 1115 1116def : GCNPat < 1117 (f64 InlineFPImm<f64>:$imm), 1118 (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineFPImm<f64>:$imm))) 1119>; 1120 1121/********** ================== **********/ 1122/********** Intrinsic Patterns **********/ 1123/********** ================== **********/ 1124 1125let SubtargetPredicate = isGCN in { 1126def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>; 1127} 1128 1129def : GCNPat < 1130 (i32 (sext i1:$src0)), 1131 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src0) 1132>; 1133 1134class Ext32Pat <SDNode ext> : GCNPat < 1135 (i32 (ext i1:$src0)), 1136 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src0) 1137>; 1138 1139def : Ext32Pat <zext>; 1140def : Ext32Pat <anyext>; 1141 1142// The multiplication scales from [0,1] to the unsigned integer range 1143def : GCNPat < 1144 (AMDGPUurecip i32:$src0), 1145 (V_CVT_U32_F32_e32 1146 (V_MUL_F32_e32 (i32 CONST.FP_UINT_MAX_PLUS_1), 1147 (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0)))) 1148>; 1149 1150//===----------------------------------------------------------------------===// 1151// VOP3 Patterns 1152//===----------------------------------------------------------------------===// 1153 1154let SubtargetPredicate = isGCN in { 1155 1156def : IMad24Pat<V_MAD_I32_I24, 1>; 1157def : UMad24Pat<V_MAD_U32_U24, 1>; 1158 1159// FIXME: This should only be done for VALU inputs 1160defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>; 1161def : ROTRPattern <V_ALIGNBIT_B32>; 1162 1163} 1164 1165def : GCNPat<(i32 (trunc (srl i64:$src0, (and i32:$src1, (i32 31))))), 1166 (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)), 1167 (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>; 1168 1169def : GCNPat<(i32 (trunc (srl i64:$src0, (i32 ShiftAmt32Imm:$src1)))), 1170 (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)), 1171 (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>; 1172 1173/********** ====================== **********/ 1174/********** Indirect addressing **********/ 1175/********** ====================== **********/ 1176 1177multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> { 1178 // Extract with offset 1179 def : GCNPat< 1180 (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))), 1181 (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset) 1182 >; 1183 1184 // Insert with offset 1185 def : GCNPat< 1186 (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))), 1187 (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val) 1188 >; 1189} 1190 1191defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">; 1192defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">; 1193defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">; 1194defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">; 1195 1196defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">; 1197defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">; 1198defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">; 1199defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">; 1200 1201//===----------------------------------------------------------------------===// 1202// SAD Patterns 1203//===----------------------------------------------------------------------===// 1204 1205def : GCNPat < 1206 (add (sub_oneuse (umax i32:$src0, i32:$src1), 1207 (umin i32:$src0, i32:$src1)), 1208 i32:$src2), 1209 (V_SAD_U32 $src0, $src1, $src2, (i1 0)) 1210>; 1211 1212def : GCNPat < 1213 (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)), 1214 (sub i32:$src0, i32:$src1), 1215 (sub i32:$src1, i32:$src0)), 1216 i32:$src2), 1217 (V_SAD_U32 $src0, $src1, $src2, (i1 0)) 1218>; 1219 1220//===----------------------------------------------------------------------===// 1221// Conversion Patterns 1222//===----------------------------------------------------------------------===// 1223 1224def : GCNPat<(i32 (sext_inreg i32:$src, i1)), 1225 (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16 1226 1227// Handle sext_inreg in i64 1228def : GCNPat < 1229 (i64 (sext_inreg i64:$src, i1)), 1230 (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16 1231>; 1232 1233def : GCNPat < 1234 (i16 (sext_inreg i16:$src, i1)), 1235 (S_BFE_I32 $src, (i32 0x00010000)) // 0 | 1 << 16 1236>; 1237 1238def : GCNPat < 1239 (i16 (sext_inreg i16:$src, i8)), 1240 (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16 1241>; 1242 1243def : GCNPat < 1244 (i64 (sext_inreg i64:$src, i8)), 1245 (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16 1246>; 1247 1248def : GCNPat < 1249 (i64 (sext_inreg i64:$src, i16)), 1250 (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16 1251>; 1252 1253def : GCNPat < 1254 (i64 (sext_inreg i64:$src, i32)), 1255 (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16 1256>; 1257 1258def : GCNPat < 1259 (i64 (zext i32:$src)), 1260 (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1) 1261>; 1262 1263def : GCNPat < 1264 (i64 (anyext i32:$src)), 1265 (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1) 1266>; 1267 1268class ZExt_i64_i1_Pat <SDNode ext> : GCNPat < 1269 (i64 (ext i1:$src)), 1270 (REG_SEQUENCE VReg_64, 1271 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src), sub0, 1272 (S_MOV_B32 (i32 0)), sub1) 1273>; 1274 1275 1276def : ZExt_i64_i1_Pat<zext>; 1277def : ZExt_i64_i1_Pat<anyext>; 1278 1279// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that 1280// REG_SEQUENCE patterns don't support instructions with multiple outputs. 1281def : GCNPat < 1282 (i64 (sext i32:$src)), 1283 (REG_SEQUENCE SReg_64, $src, sub0, 1284 (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1) 1285>; 1286 1287def : GCNPat < 1288 (i64 (sext i1:$src)), 1289 (REG_SEQUENCE VReg_64, 1290 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub0, 1291 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub1) 1292>; 1293 1294class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : GCNPat < 1295 (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))), 1296 (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE)) 1297>; 1298 1299def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>; 1300def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>; 1301def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>; 1302def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>; 1303 1304// If we need to perform a logical operation on i1 values, we need to 1305// use vector comparisons since there is only one SCC register. Vector 1306// comparisons still write to a pair of SGPRs, so treat these as 1307// 64-bit comparisons. When legalizing SGPR copies, instructions 1308// resulting in the copies from SCC to these instructions will be 1309// moved to the VALU. 1310def : GCNPat < 1311 (i1 (and i1:$src0, i1:$src1)), 1312 (S_AND_B64 $src0, $src1) 1313>; 1314 1315def : GCNPat < 1316 (i1 (or i1:$src0, i1:$src1)), 1317 (S_OR_B64 $src0, $src1) 1318>; 1319 1320def : GCNPat < 1321 (i1 (xor i1:$src0, i1:$src1)), 1322 (S_XOR_B64 $src0, $src1) 1323>; 1324 1325def : GCNPat < 1326 (i1 (add i1:$src0, i1:$src1)), 1327 (S_XOR_B64 $src0, $src1) 1328>; 1329 1330def : GCNPat < 1331 (i1 (sub i1:$src0, i1:$src1)), 1332 (S_XOR_B64 $src0, $src1) 1333>; 1334 1335let AddedComplexity = 1 in { 1336def : GCNPat < 1337 (i1 (add i1:$src0, (i1 -1))), 1338 (S_NOT_B64 $src0) 1339>; 1340 1341def : GCNPat < 1342 (i1 (sub i1:$src0, (i1 -1))), 1343 (S_NOT_B64 $src0) 1344>; 1345} 1346 1347def : GCNPat < 1348 (f16 (sint_to_fp i1:$src)), 1349 (V_CVT_F16_F32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_NEG_ONE), $src)) 1350>; 1351 1352def : GCNPat < 1353 (f16 (uint_to_fp i1:$src)), 1354 (V_CVT_F16_F32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_ONE), $src)) 1355>; 1356 1357def : GCNPat < 1358 (f32 (sint_to_fp i1:$src)), 1359 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_NEG_ONE), $src) 1360>; 1361 1362def : GCNPat < 1363 (f32 (uint_to_fp i1:$src)), 1364 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_ONE), $src) 1365>; 1366 1367def : GCNPat < 1368 (f64 (sint_to_fp i1:$src)), 1369 (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src)) 1370>; 1371 1372def : GCNPat < 1373 (f64 (uint_to_fp i1:$src)), 1374 (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src)) 1375>; 1376 1377//===----------------------------------------------------------------------===// 1378// Miscellaneous Patterns 1379//===----------------------------------------------------------------------===// 1380def : GCNPat < 1381 (i32 (AMDGPUfp16_zext f16:$src)), 1382 (COPY $src) 1383>; 1384 1385 1386def : GCNPat < 1387 (i32 (trunc i64:$a)), 1388 (EXTRACT_SUBREG $a, sub0) 1389>; 1390 1391def : GCNPat < 1392 (i1 (trunc i32:$a)), 1393 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1394>; 1395 1396def : GCNPat < 1397 (i1 (trunc i16:$a)), 1398 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1399>; 1400 1401def : GCNPat < 1402 (i1 (trunc i64:$a)), 1403 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), 1404 (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1)) 1405>; 1406 1407def : GCNPat < 1408 (i32 (bswap i32:$a)), 1409 (V_BFI_B32 (S_MOV_B32 (i32 0x00ff00ff)), 1410 (V_ALIGNBIT_B32 $a, $a, (i32 24)), 1411 (V_ALIGNBIT_B32 $a, $a, (i32 8))) 1412>; 1413 1414let OtherPredicates = [NoFP16Denormals] in { 1415def : GCNPat< 1416 (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))), 1417 (V_MUL_F16_e64 0, (i32 CONST.FP16_ONE), $src_mods, $src, 0, 0) 1418>; 1419 1420def : GCNPat< 1421 (fcanonicalize (f16 (fneg (VOP3Mods f16:$src, i32:$src_mods)))), 1422 (V_MUL_F16_e64 0, (i32 CONST.FP16_NEG_ONE), $src_mods, $src, 0, 0) 1423>; 1424 1425def : GCNPat< 1426 (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))), 1427 (V_PK_MUL_F16 0, (i32 CONST.V2FP16_ONE), $src_mods, $src, DSTCLAMP.NONE) 1428>; 1429} 1430 1431let OtherPredicates = [FP16Denormals] in { 1432def : GCNPat< 1433 (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))), 1434 (V_MAX_F16_e64 $src_mods, $src, $src_mods, $src, 0, 0) 1435>; 1436 1437let SubtargetPredicate = HasVOP3PInsts in { 1438def : GCNPat< 1439 (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))), 1440 (V_PK_MAX_F16 $src_mods, $src, $src_mods, $src, DSTCLAMP.NONE) 1441>; 1442} 1443} 1444 1445let OtherPredicates = [NoFP32Denormals] in { 1446def : GCNPat< 1447 (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))), 1448 (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), $src_mods, $src, 0, 0) 1449>; 1450 1451def : GCNPat< 1452 (fcanonicalize (f32 (fneg (VOP3Mods f32:$src, i32:$src_mods)))), 1453 (V_MUL_F32_e64 0, (i32 CONST.FP32_NEG_ONE), $src_mods, $src, 0, 0) 1454>; 1455} 1456 1457let OtherPredicates = [FP32Denormals] in { 1458def : GCNPat< 1459 (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))), 1460 (V_MAX_F32_e64 $src_mods, $src, $src_mods, $src, 0, 0) 1461>; 1462} 1463 1464let OtherPredicates = [NoFP64Denormals] in { 1465def : GCNPat< 1466 (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))), 1467 (V_MUL_F64 0, CONST.FP64_ONE, $src_mods, $src, 0, 0) 1468>; 1469} 1470 1471let OtherPredicates = [FP64Denormals] in { 1472def : GCNPat< 1473 (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))), 1474 (V_MAX_F64 $src_mods, $src, $src_mods, $src, 0, 0) 1475>; 1476} 1477 1478let OtherPredicates = [HasDLInsts] in { 1479def : GCNPat < 1480 (fma (f32 (VOP3Mods0 f32:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)), 1481 (f32 (VOP3Mods f32:$src1, i32:$src1_modifiers)), 1482 (f32 (VOP3NoMods f32:$src2))), 1483 (V_FMAC_F32_e64 $src0_modifiers, $src0, $src1_modifiers, $src1, 1484 SRCMODS.NONE, $src2, $clamp, $omod) 1485>; 1486} // End OtherPredicates = [HasDLInsts] 1487 1488 1489// Allow integer inputs 1490class ExpPattern<SDPatternOperator node, ValueType vt, Instruction Inst> : GCNPat< 1491 (node (i8 timm:$tgt), (i8 timm:$en), vt:$src0, vt:$src1, vt:$src2, vt:$src3, (i1 timm:$compr), (i1 timm:$vm)), 1492 (Inst i8:$tgt, vt:$src0, vt:$src1, vt:$src2, vt:$src3, i1:$vm, i1:$compr, i8:$en) 1493>; 1494 1495def : ExpPattern<AMDGPUexport, i32, EXP>; 1496def : ExpPattern<AMDGPUexport_done, i32, EXP_DONE>; 1497 1498// COPY is workaround tablegen bug from multiple outputs 1499// from S_LSHL_B32's multiple outputs from implicit scc def. 1500def : GCNPat < 1501 (v2i16 (build_vector (i16 0), i16:$src1)), 1502 (v2i16 (COPY (S_LSHL_B32 i16:$src1, (i16 16)))) 1503>; 1504 1505def : GCNPat < 1506 (v2i16 (build_vector i16:$src0, (i16 undef))), 1507 (v2i16 (COPY $src0)) 1508>; 1509 1510def : GCNPat < 1511 (v2f16 (build_vector f16:$src0, (f16 undef))), 1512 (v2f16 (COPY $src0)) 1513>; 1514 1515def : GCNPat < 1516 (v2i16 (build_vector (i16 undef), i16:$src1)), 1517 (v2i16 (COPY (S_LSHL_B32 $src1, (i32 16)))) 1518>; 1519 1520def : GCNPat < 1521 (v2f16 (build_vector (f16 undef), f16:$src1)), 1522 (v2f16 (COPY (S_LSHL_B32 $src1, (i32 16)))) 1523>; 1524 1525let SubtargetPredicate = HasVOP3PInsts in { 1526def : GCNPat < 1527 (v2i16 (build_vector i16:$src0, i16:$src1)), 1528 (v2i16 (S_PACK_LL_B32_B16 $src0, $src1)) 1529>; 1530 1531// With multiple uses of the shift, this will duplicate the shift and 1532// increase register pressure. 1533def : GCNPat < 1534 (v2i16 (build_vector i16:$src0, (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))), 1535 (v2i16 (S_PACK_LH_B32_B16 i16:$src0, i32:$src1)) 1536>; 1537 1538 1539def : GCNPat < 1540 (v2i16 (build_vector (i16 (trunc (srl_oneuse i32:$src0, (i32 16)))), 1541 (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))), 1542 (v2i16 (S_PACK_HH_B32_B16 $src0, $src1)) 1543>; 1544 1545// TODO: Should source modifiers be matched to v_pack_b32_f16? 1546def : GCNPat < 1547 (v2f16 (build_vector f16:$src0, f16:$src1)), 1548 (v2f16 (S_PACK_LL_B32_B16 $src0, $src1)) 1549>; 1550 1551} // End SubtargetPredicate = HasVOP3PInsts 1552 1553 1554// def : GCNPat < 1555// (v2f16 (scalar_to_vector f16:$src0)), 1556// (COPY $src0) 1557// >; 1558 1559// def : GCNPat < 1560// (v2i16 (scalar_to_vector i16:$src0)), 1561// (COPY $src0) 1562// >; 1563 1564def : GCNPat < 1565 (v4i16 (scalar_to_vector i16:$src0)), 1566 (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0) 1567>; 1568 1569def : GCNPat < 1570 (v4f16 (scalar_to_vector f16:$src0)), 1571 (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0) 1572>; 1573 1574//===----------------------------------------------------------------------===// 1575// Fract Patterns 1576//===----------------------------------------------------------------------===// 1577 1578let SubtargetPredicate = isSI in { 1579 1580// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is 1581// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient 1582// way to implement it is using V_FRACT_F64. 1583// The workaround for the V_FRACT bug is: 1584// fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999) 1585 1586// Convert floor(x) to (x - fract(x)) 1587def : GCNPat < 1588 (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))), 1589 (V_ADD_F64 1590 $mods, 1591 $x, 1592 SRCMODS.NEG, 1593 (V_CNDMASK_B64_PSEUDO 1594 (V_MIN_F64 1595 SRCMODS.NONE, 1596 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE), 1597 SRCMODS.NONE, 1598 (V_MOV_B64_PSEUDO 0x3fefffffffffffff), 1599 DSTCLAMP.NONE, DSTOMOD.NONE), 1600 $x, 1601 (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))), 1602 DSTCLAMP.NONE, DSTOMOD.NONE) 1603>; 1604 1605} // End SubtargetPredicates = isSI 1606 1607//============================================================================// 1608// Miscellaneous Optimization Patterns 1609//============================================================================// 1610 1611// Undo sub x, c -> add x, -c canonicalization since c is more likely 1612// an inline immediate than -c. 1613// TODO: Also do for 64-bit. 1614def : GCNPat< 1615 (add i32:$src0, (i32 NegSubInlineConst32:$src1)), 1616 (S_SUB_I32 $src0, NegSubInlineConst32:$src1) 1617>; 1618 1619 1620multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> { 1621 def : GCNPat < 1622 (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)), 1623 (BFM $a, $b) 1624 >; 1625 1626 def : GCNPat < 1627 (vt (add (vt (shl 1, vt:$a)), -1)), 1628 (BFM $a, (MOV (i32 0))) 1629 >; 1630} 1631 1632let SubtargetPredicate = isGCN in { 1633 1634defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>; 1635// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>; 1636 1637defm : BFEPattern <V_BFE_U32, V_BFE_I32, S_MOV_B32>; 1638defm : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64, SReg_64>; 1639 1640def : IntMed3Pat<V_MED3_I32, smax, smax_oneuse, smin_oneuse>; 1641def : IntMed3Pat<V_MED3_U32, umax, umax_oneuse, umin_oneuse>; 1642 1643} 1644 1645// This matches 16 permutations of 1646// max(min(x, y), min(max(x, y), z)) 1647class FPMed3Pat<ValueType vt, 1648 //SDPatternOperator max, SDPatternOperator min, 1649 Instruction med3Inst> : GCNPat< 1650 (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1651 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1652 (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1653 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1654 (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))), 1655 (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 1656>; 1657 1658class FP16Med3Pat<ValueType vt, 1659 Instruction med3Inst> : GCNPat< 1660 (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1661 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1662 (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1663 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1664 (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))), 1665 (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE) 1666>; 1667 1668class Int16Med3Pat<Instruction med3Inst, 1669 SDPatternOperator max, 1670 SDPatternOperator max_oneuse, 1671 SDPatternOperator min_oneuse, 1672 ValueType vt = i32> : GCNPat< 1673 (max (min_oneuse vt:$src0, vt:$src1), 1674 (min_oneuse (max_oneuse vt:$src0, vt:$src1), vt:$src2)), 1675 (med3Inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1, SRCMODS.NONE, $src2, DSTCLAMP.NONE) 1676>; 1677 1678def : FPMed3Pat<f32, V_MED3_F32>; 1679 1680let OtherPredicates = [isGFX9] in { 1681def : FP16Med3Pat<f16, V_MED3_F16>; 1682def : Int16Med3Pat<V_MED3_I16, smax, smax_oneuse, smin_oneuse, i16>; 1683def : Int16Med3Pat<V_MED3_U16, umax, umax_oneuse, umin_oneuse, i16>; 1684} // End Predicates = [isGFX9] 1685