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