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