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