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