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 isGCN : Predicate<"Subtarget->getGeneration() " 15 ">= SISubtarget::SOUTHERN_ISLANDS">, 16 AssemblerPredicate<"FeatureGCN">; 17def isSI : Predicate<"Subtarget->getGeneration() " 18 "== SISubtarget::SOUTHERN_ISLANDS">, 19 AssemblerPredicate<"FeatureSouthernIslands">; 20 21def has16BankLDS : Predicate<"Subtarget->getLDSBankCount() == 16">; 22def has32BankLDS : Predicate<"Subtarget->getLDSBankCount() == 32">; 23def HasVGPRIndexMode : Predicate<"Subtarget->hasVGPRIndexMode()">, 24 AssemblerPredicate<"FeatureVGPRIndexMode">; 25def HasMovrel : Predicate<"Subtarget->hasMovrel()">, 26 AssemblerPredicate<"FeatureMovrel">; 27 28include "VOPInstructions.td" 29include "SOPInstructions.td" 30include "SMInstructions.td" 31include "FLATInstructions.td" 32include "BUFInstructions.td" 33 34let SubtargetPredicate = isGCN in { 35 36//===----------------------------------------------------------------------===// 37// EXP Instructions 38//===----------------------------------------------------------------------===// 39 40defm EXP : EXP_m<0, AMDGPUexport>; 41defm EXP_DONE : EXP_m<1, AMDGPUexport_done>; 42 43//===----------------------------------------------------------------------===// 44// VINTRP Instructions 45//===----------------------------------------------------------------------===// 46 47let Uses = [M0, EXEC] in { 48 49// FIXME: Specify SchedRW for VINTRP insturctions. 50 51multiclass V_INTERP_P1_F32_m : VINTRP_m < 52 0x00000000, 53 (outs VGPR_32:$vdst), 54 (ins VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 55 "v_interp_p1_f32 $vdst, $vsrc, $attr$attrchan", 56 [(set f32:$vdst, (AMDGPUinterp_p1 f32:$vsrc, (i32 imm:$attrchan), 57 (i32 imm:$attr)))] 58>; 59 60let OtherPredicates = [has32BankLDS] in { 61 62defm V_INTERP_P1_F32 : V_INTERP_P1_F32_m; 63 64} // End OtherPredicates = [has32BankLDS] 65 66let OtherPredicates = [has16BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 in { 67 68defm V_INTERP_P1_F32_16bank : V_INTERP_P1_F32_m; 69 70} // End OtherPredicates = [has32BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 71 72let DisableEncoding = "$src0", Constraints = "$src0 = $vdst" in { 73 74defm V_INTERP_P2_F32 : VINTRP_m < 75 0x00000001, 76 (outs VGPR_32:$vdst), 77 (ins VGPR_32:$src0, VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan), 78 "v_interp_p2_f32 $vdst, $vsrc, $attr$attrchan", 79 [(set f32:$vdst, (AMDGPUinterp_p2 f32:$src0, f32:$vsrc, (i32 imm:$attrchan), 80 (i32 imm:$attr)))]>; 81 82} // End DisableEncoding = "$src0", Constraints = "$src0 = $vdst" 83 84defm V_INTERP_MOV_F32 : VINTRP_m < 85 0x00000002, 86 (outs VGPR_32:$vdst), 87 (ins InterpSlot:$vsrc, Attr:$attr, AttrChan:$attrchan), 88 "v_interp_mov_f32 $vdst, $vsrc, $attr$attrchan", 89 [(set f32:$vdst, (AMDGPUinterp_mov (i32 imm:$vsrc), (i32 imm:$attrchan), 90 (i32 imm:$attr)))]>; 91 92} // End Uses = [M0, EXEC] 93 94//===----------------------------------------------------------------------===// 95// Pseudo Instructions 96//===----------------------------------------------------------------------===// 97 98let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] in { 99 100// For use in patterns 101def V_CNDMASK_B64_PSEUDO : VOP3Common <(outs VReg_64:$vdst), 102 (ins VSrc_b64:$src0, VSrc_b64:$src1, SSrc_b64:$src2), "", []> { 103 let isPseudo = 1; 104 let isCodeGenOnly = 1; 105 let usesCustomInserter = 1; 106} 107 108// 64-bit vector move instruction. This is mainly used by the SIFoldOperands 109// pass to enable folding of inline immediates. 110def V_MOV_B64_PSEUDO : VPseudoInstSI <(outs VReg_64:$vdst), 111 (ins VSrc_b64:$src0)>; 112} // End let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] 113 114def S_TRAP_PSEUDO : SPseudoInstSI <(outs), (ins i16imm:$simm16)> { 115 let hasSideEffects = 1; 116 let SALU = 1; 117 let usesCustomInserter = 1; 118} 119 120let usesCustomInserter = 1, SALU = 1 in { 121def GET_GROUPSTATICSIZE : PseudoInstSI <(outs SReg_32:$sdst), (ins), 122 [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>; 123} // End let usesCustomInserter = 1, SALU = 1 124 125def S_MOV_B64_term : PseudoInstSI<(outs SReg_64:$dst), 126 (ins SSrc_b64:$src0)> { 127 let SALU = 1; 128 let isAsCheapAsAMove = 1; 129 let isTerminator = 1; 130} 131 132def S_XOR_B64_term : PseudoInstSI<(outs SReg_64:$dst), 133 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 134 let SALU = 1; 135 let isAsCheapAsAMove = 1; 136 let isTerminator = 1; 137} 138 139def S_ANDN2_B64_term : PseudoInstSI<(outs SReg_64:$dst), 140 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 141 let SALU = 1; 142 let isAsCheapAsAMove = 1; 143 let isTerminator = 1; 144} 145 146def WAVE_BARRIER : SPseudoInstSI<(outs), (ins), 147 [(int_amdgcn_wave_barrier)]> { 148 let SchedRW = []; 149 let hasNoSchedulingInfo = 1; 150 let hasSideEffects = 1; 151 let mayLoad = 1; 152 let mayStore = 1; 153 let isBarrier = 1; 154 let isConvergent = 1; 155} 156 157// SI pseudo instructions. These are used by the CFG structurizer pass 158// and should be lowered to ISA instructions prior to codegen. 159 160// Dummy terminator instruction to use after control flow instructions 161// replaced with exec mask operations. 162def SI_MASK_BRANCH : PseudoInstSI < 163 (outs), (ins brtarget:$target)> { 164 let isBranch = 0; 165 let isTerminator = 1; 166 let isBarrier = 0; 167 let Uses = [EXEC]; 168 let SchedRW = []; 169 let hasNoSchedulingInfo = 1; 170} 171 172let isTerminator = 1 in { 173 174def SI_IF: CFPseudoInstSI < 175 (outs SReg_64:$dst), (ins SReg_64:$vcc, brtarget:$target), 176 [(set i64:$dst, (int_amdgcn_if i1:$vcc, bb:$target))], 1, 1> { 177 let Constraints = ""; 178 let Size = 12; 179 let mayLoad = 1; 180 let mayStore = 1; 181 let hasSideEffects = 1; 182} 183 184def SI_ELSE : CFPseudoInstSI < 185 (outs SReg_64:$dst), (ins SReg_64:$src, brtarget:$target, i1imm:$execfix), [], 1, 1> { 186 let Constraints = "$src = $dst"; 187 let Size = 12; 188 let mayStore = 1; 189 let mayLoad = 1; 190 let hasSideEffects = 1; 191} 192 193def SI_LOOP : CFPseudoInstSI < 194 (outs), (ins SReg_64:$saved, brtarget:$target), 195 [(int_amdgcn_loop i64:$saved, bb:$target)], 1, 1> { 196 let Size = 8; 197 let isBranch = 1; 198 let hasSideEffects = 1; 199 let mayLoad = 1; 200 let mayStore = 1; 201} 202 203} // End isBranch = 1, isTerminator = 1 204 205def SI_END_CF : CFPseudoInstSI < 206 (outs), (ins SReg_64:$saved), 207 [(int_amdgcn_end_cf i64:$saved)], 1, 1> { 208 let Size = 4; 209 let isAsCheapAsAMove = 1; 210 let isReMaterializable = 1; 211 let mayLoad = 1; 212 let mayStore = 1; 213 let hasSideEffects = 1; 214} 215 216def SI_BREAK : CFPseudoInstSI < 217 (outs SReg_64:$dst), (ins SReg_64:$src), 218 [(set i64:$dst, (int_amdgcn_break i64:$src))], 1> { 219 let Size = 4; 220 let isAsCheapAsAMove = 1; 221 let isReMaterializable = 1; 222} 223 224def SI_IF_BREAK : CFPseudoInstSI < 225 (outs SReg_64:$dst), (ins SReg_64:$vcc, SReg_64:$src), 226 [(set i64:$dst, (int_amdgcn_if_break i1:$vcc, i64:$src))]> { 227 let Size = 4; 228 let isAsCheapAsAMove = 1; 229 let isReMaterializable = 1; 230} 231 232def SI_ELSE_BREAK : CFPseudoInstSI < 233 (outs SReg_64:$dst), (ins SReg_64:$src0, SReg_64:$src1), 234 [(set i64:$dst, (int_amdgcn_else_break i64:$src0, i64:$src1))]> { 235 let Size = 4; 236 let isAsCheapAsAMove = 1; 237 let isReMaterializable = 1; 238} 239 240let Uses = [EXEC], Defs = [EXEC,VCC] in { 241def SI_KILL : PseudoInstSI < 242 (outs), (ins VSrc_b32:$src), 243 [(AMDGPUkill i32:$src)]> { 244 let isConvergent = 1; 245 let usesCustomInserter = 1; 246} 247 248def SI_KILL_TERMINATOR : SPseudoInstSI < 249 (outs), (ins VSrc_b32:$src)> { 250 let isTerminator = 1; 251} 252 253} // End Uses = [EXEC], Defs = [EXEC,VCC] 254 255// Branch on undef scc. Used to avoid intermediate copy from 256// IMPLICIT_DEF to SCC. 257def SI_BR_UNDEF : SPseudoInstSI <(outs), (ins sopp_brtarget:$simm16)> { 258 let isTerminator = 1; 259 let usesCustomInserter = 1; 260} 261 262def SI_PS_LIVE : PseudoInstSI < 263 (outs SReg_64:$dst), (ins), 264 [(set i1:$dst, (int_amdgcn_ps_live))]> { 265 let SALU = 1; 266} 267 268// Used as an isel pseudo to directly emit initialization with an 269// s_mov_b32 rather than a copy of another initialized 270// register. MachineCSE skips copies, and we don't want to have to 271// fold operands before it runs. 272def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> { 273 let Defs = [M0]; 274 let usesCustomInserter = 1; 275 let isAsCheapAsAMove = 1; 276 let isReMaterializable = 1; 277} 278 279def SI_RETURN : SPseudoInstSI < 280 (outs), (ins variable_ops), [(AMDGPUreturn)]> { 281 let isTerminator = 1; 282 let isBarrier = 1; 283 let isReturn = 1; 284 let hasSideEffects = 1; 285 let hasNoSchedulingInfo = 1; 286 let DisableWQM = 1; 287} 288 289let Defs = [M0, EXEC], 290 UseNamedOperandTable = 1 in { 291 292class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI < 293 (outs VGPR_32:$vdst), 294 (ins rc:$src, VS_32:$idx, i32imm:$offset)> { 295 let usesCustomInserter = 1; 296} 297 298class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI < 299 (outs rc:$vdst), 300 (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> { 301 let Constraints = "$src = $vdst"; 302 let usesCustomInserter = 1; 303} 304 305// TODO: We can support indirect SGPR access. 306def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>; 307def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>; 308def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>; 309def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>; 310def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>; 311 312def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>; 313def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>; 314def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>; 315def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>; 316def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>; 317 318} // End Uses = [EXEC], Defs = [M0, EXEC] 319 320multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> { 321 let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in { 322 def _SAVE : PseudoInstSI < 323 (outs), 324 (ins sgpr_class:$data, i32imm:$addr)> { 325 let mayStore = 1; 326 let mayLoad = 0; 327 } 328 329 def _RESTORE : PseudoInstSI < 330 (outs sgpr_class:$data), 331 (ins i32imm:$addr)> { 332 let mayStore = 0; 333 let mayLoad = 1; 334 } 335 } // End UseNamedOperandTable = 1 336} 337 338// You cannot use M0 as the output of v_readlane_b32 instructions or 339// use it in the sdata operand of SMEM instructions. We still need to 340// be able to spill the physical register m0, so allow it for 341// SI_SPILL_32_* instructions. 342defm SI_SPILL_S32 : SI_SPILL_SGPR <SReg_32>; 343defm SI_SPILL_S64 : SI_SPILL_SGPR <SReg_64>; 344defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>; 345defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>; 346defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>; 347 348multiclass SI_SPILL_VGPR <RegisterClass vgpr_class> { 349 let UseNamedOperandTable = 1, VGPRSpill = 1, 350 SchedRW = [WriteVMEM] in { 351 def _SAVE : VPseudoInstSI < 352 (outs), 353 (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc, 354 SReg_32:$soffset, i32imm:$offset)> { 355 let mayStore = 1; 356 let mayLoad = 0; 357 // (2 * 4) + (8 * num_subregs) bytes maximum 358 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 359 } 360 361 def _RESTORE : VPseudoInstSI < 362 (outs vgpr_class:$vdata), 363 (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset, 364 i32imm:$offset)> { 365 let mayStore = 0; 366 let mayLoad = 1; 367 368 // (2 * 4) + (8 * num_subregs) bytes maximum 369 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 370 } 371 } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM] 372} 373 374defm SI_SPILL_V32 : SI_SPILL_VGPR <VGPR_32>; 375defm SI_SPILL_V64 : SI_SPILL_VGPR <VReg_64>; 376defm SI_SPILL_V96 : SI_SPILL_VGPR <VReg_96>; 377defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>; 378defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>; 379defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>; 380 381def SI_PC_ADD_REL_OFFSET : SPseudoInstSI < 382 (outs SReg_64:$dst), 383 (ins si_ga:$ptr_lo, si_ga:$ptr_hi), 384 [(set SReg_64:$dst, 385 (i64 (SIpc_add_rel_offset (tglobaladdr:$ptr_lo), (tglobaladdr:$ptr_hi))))]> { 386 let Defs = [SCC]; 387} 388 389} // End SubtargetPredicate = isGCN 390 391let Predicates = [isGCN] in { 392def : Pat< 393 (trap), 394 (S_TRAP_PSEUDO TRAPID.LLVM_TRAP) 395>; 396 397def : Pat< 398 (debugtrap), 399 (S_TRAP_PSEUDO TRAPID.LLVM_DEBUG_TRAP) 400>; 401 402def : Pat< 403 (int_amdgcn_else i64:$src, bb:$target), 404 (SI_ELSE $src, $target, 0) 405>; 406 407def : Pat < 408 (int_AMDGPU_kilp), 409 (SI_KILL (i32 0xbf800000)) 410>; 411 412//===----------------------------------------------------------------------===// 413// VOP1 Patterns 414//===----------------------------------------------------------------------===// 415 416let Predicates = [UnsafeFPMath] in { 417 418//def : RcpPat<V_RCP_F64_e32, f64>; 419//defm : RsqPat<V_RSQ_F64_e32, f64>; 420//defm : RsqPat<V_RSQ_F32_e32, f32>; 421 422def : RsqPat<V_RSQ_F32_e32, f32>; 423def : RsqPat<V_RSQ_F64_e32, f64>; 424 425// Convert (x - floor(x)) to fract(x) 426def : Pat < 427 (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)), 428 (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))), 429 (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 430>; 431 432// Convert (x + (-floor(x))) to fract(x) 433def : Pat < 434 (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)), 435 (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))), 436 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 437>; 438 439} // End Predicates = [UnsafeFPMath] 440 441 442// f16_to_fp patterns 443def : Pat < 444 (f32 (f16_to_fp i32:$src0)), 445 (V_CVT_F32_F16_e64 SRCMODS.NONE, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 446>; 447 448def : Pat < 449 (f32 (f16_to_fp (and_oneuse i32:$src0, 0x7fff))), 450 (V_CVT_F32_F16_e64 SRCMODS.ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 451>; 452 453def : Pat < 454 (f32 (f16_to_fp (or_oneuse i32:$src0, 0x8000))), 455 (V_CVT_F32_F16_e64 SRCMODS.NEG_ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 456>; 457 458def : Pat < 459 (f32 (f16_to_fp (xor_oneuse i32:$src0, 0x8000))), 460 (V_CVT_F32_F16_e64 SRCMODS.NEG, $src0, DSTCLAMP.NONE, DSTOMOD.NONE) 461>; 462 463def : Pat < 464 (f64 (fpextend f16:$src)), 465 (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src)) 466>; 467 468// fp_to_fp16 patterns 469def : Pat < 470 (i32 (fp_to_f16 (f32 (VOP3Mods0 f32:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)))), 471 (V_CVT_F16_F32_e64 $src0_modifiers, f32:$src0, $clamp, $omod) 472>; 473 474def : Pat < 475 (i32 (fp_to_sint f16:$src)), 476 (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 $src)) 477>; 478 479def : Pat < 480 (i32 (fp_to_uint f16:$src)), 481 (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 $src)) 482>; 483 484def : Pat < 485 (f16 (sint_to_fp i32:$src)), 486 (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 $src)) 487>; 488 489def : Pat < 490 (f16 (uint_to_fp i32:$src)), 491 (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 $src)) 492>; 493 494//===----------------------------------------------------------------------===// 495// VOP2 Patterns 496//===----------------------------------------------------------------------===// 497 498multiclass FMADPat <ValueType vt, Instruction inst> { 499 def : Pat < 500 (vt (fmad (VOP3NoMods0 vt:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod), 501 (VOP3NoMods vt:$src1, i32:$src1_modifiers), 502 (VOP3NoMods vt:$src2, i32:$src2_modifiers))), 503 (inst $src0_modifiers, $src0, $src1_modifiers, $src1, 504 $src2_modifiers, $src2, $clamp, $omod) 505 >; 506} 507 508defm : FMADPat <f16, V_MAC_F16_e64>; 509defm : FMADPat <f32, V_MAC_F32_e64>; 510 511class FMADModsPat<Instruction inst, SDPatternOperator mad_opr> : Pat< 512 (f32 (mad_opr (VOP3Mods f32:$src0, i32:$src0_mod), 513 (VOP3Mods f32:$src1, i32:$src1_mod), 514 (VOP3Mods f32:$src2, i32:$src2_mod))), 515 (inst $src0_mod, $src0, $src1_mod, $src1, 516 $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 517>; 518 519def : FMADModsPat<V_MAD_F32, AMDGPUfmad_ftz>; 520 521multiclass SelectPat <ValueType vt, Instruction inst> { 522 def : Pat < 523 (vt (select i1:$src0, vt:$src1, vt:$src2)), 524 (inst $src2, $src1, $src0) 525 >; 526} 527 528defm : SelectPat <i16, V_CNDMASK_B32_e64>; 529defm : SelectPat <i32, V_CNDMASK_B32_e64>; 530defm : SelectPat <f16, V_CNDMASK_B32_e64>; 531defm : SelectPat <f32, V_CNDMASK_B32_e64>; 532 533def : Pat < 534 (i32 (add (i32 (ctpop i32:$popcnt)), i32:$val)), 535 (V_BCNT_U32_B32_e64 $popcnt, $val) 536>; 537 538/********** ============================================ **********/ 539/********** Extraction, Insertion, Building and Casting **********/ 540/********** ============================================ **********/ 541 542foreach Index = 0-2 in { 543 def Extract_Element_v2i32_#Index : Extract_Element < 544 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 545 >; 546 def Insert_Element_v2i32_#Index : Insert_Element < 547 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 548 >; 549 550 def Extract_Element_v2f32_#Index : Extract_Element < 551 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 552 >; 553 def Insert_Element_v2f32_#Index : Insert_Element < 554 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 555 >; 556} 557 558foreach Index = 0-3 in { 559 def Extract_Element_v4i32_#Index : Extract_Element < 560 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 561 >; 562 def Insert_Element_v4i32_#Index : Insert_Element < 563 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 564 >; 565 566 def Extract_Element_v4f32_#Index : Extract_Element < 567 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 568 >; 569 def Insert_Element_v4f32_#Index : Insert_Element < 570 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 571 >; 572} 573 574foreach Index = 0-7 in { 575 def Extract_Element_v8i32_#Index : Extract_Element < 576 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 577 >; 578 def Insert_Element_v8i32_#Index : Insert_Element < 579 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 580 >; 581 582 def Extract_Element_v8f32_#Index : Extract_Element < 583 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 584 >; 585 def Insert_Element_v8f32_#Index : Insert_Element < 586 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 587 >; 588} 589 590foreach Index = 0-15 in { 591 def Extract_Element_v16i32_#Index : Extract_Element < 592 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 593 >; 594 def Insert_Element_v16i32_#Index : Insert_Element < 595 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 596 >; 597 598 def Extract_Element_v16f32_#Index : Extract_Element < 599 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 600 >; 601 def Insert_Element_v16f32_#Index : Insert_Element < 602 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 603 >; 604} 605 606// FIXME: Why do only some of these type combinations for SReg and 607// VReg? 608// 16-bit bitcast 609def : BitConvert <i16, f16, VGPR_32>; 610def : BitConvert <f16, i16, VGPR_32>; 611def : BitConvert <i16, f16, SReg_32>; 612def : BitConvert <f16, i16, SReg_32>; 613 614// 32-bit bitcast 615def : BitConvert <i32, f32, VGPR_32>; 616def : BitConvert <f32, i32, VGPR_32>; 617def : BitConvert <i32, f32, SReg_32>; 618def : BitConvert <f32, i32, SReg_32>; 619def : BitConvert <v2i16, i32, SReg_32>; 620def : BitConvert <i32, v2i16, SReg_32>; 621def : BitConvert <v2f16, i32, SReg_32>; 622def : BitConvert <i32, v2f16, SReg_32>; 623def : BitConvert <v2i16, v2f16, SReg_32>; 624def : BitConvert <v2f16, v2i16, SReg_32>; 625def : BitConvert <v2f16, f32, SReg_32>; 626def : BitConvert <f32, v2f16, SReg_32>; 627def : BitConvert <v2i16, f32, SReg_32>; 628def : BitConvert <f32, v2i16, SReg_32>; 629 630// 64-bit bitcast 631def : BitConvert <i64, f64, VReg_64>; 632def : BitConvert <f64, i64, VReg_64>; 633def : BitConvert <v2i32, v2f32, VReg_64>; 634def : BitConvert <v2f32, v2i32, VReg_64>; 635def : BitConvert <i64, v2i32, VReg_64>; 636def : BitConvert <v2i32, i64, VReg_64>; 637def : BitConvert <i64, v2f32, VReg_64>; 638def : BitConvert <v2f32, i64, VReg_64>; 639def : BitConvert <f64, v2f32, VReg_64>; 640def : BitConvert <v2f32, f64, VReg_64>; 641def : BitConvert <f64, v2i32, VReg_64>; 642def : BitConvert <v2i32, f64, VReg_64>; 643def : BitConvert <v4i32, v4f32, VReg_128>; 644def : BitConvert <v4f32, v4i32, VReg_128>; 645 646// 128-bit bitcast 647def : BitConvert <v2i64, v4i32, SReg_128>; 648def : BitConvert <v4i32, v2i64, SReg_128>; 649def : BitConvert <v2f64, v4f32, VReg_128>; 650def : BitConvert <v2f64, v4i32, VReg_128>; 651def : BitConvert <v4f32, v2f64, VReg_128>; 652def : BitConvert <v4i32, v2f64, VReg_128>; 653def : BitConvert <v2i64, v2f64, VReg_128>; 654def : BitConvert <v2f64, v2i64, VReg_128>; 655 656// 256-bit bitcast 657def : BitConvert <v8i32, v8f32, SReg_256>; 658def : BitConvert <v8f32, v8i32, SReg_256>; 659def : BitConvert <v8i32, v8f32, VReg_256>; 660def : BitConvert <v8f32, v8i32, VReg_256>; 661 662// 512-bit bitcast 663def : BitConvert <v16i32, v16f32, VReg_512>; 664def : BitConvert <v16f32, v16i32, VReg_512>; 665 666/********** =================== **********/ 667/********** Src & Dst modifiers **********/ 668/********** =================== **********/ 669 670 671// If denormals are not enabled, it only impacts the compare of the 672// inputs. The output result is not flushed. 673class ClampPat<Instruction inst, ValueType vt> : Pat < 674 (vt (AMDGPUclamp 675 (VOP3Mods0Clamp vt:$src0, i32:$src0_modifiers, i32:$omod))), 676 (inst i32:$src0_modifiers, vt:$src0, 677 i32:$src0_modifiers, vt:$src0, DSTCLAMP.ENABLE, $omod) 678>; 679 680def : ClampPat<V_MAX_F32_e64, f32>; 681def : ClampPat<V_MAX_F64, f64>; 682def : ClampPat<V_MAX_F16_e64, f16>; 683 684/********** ================================ **********/ 685/********** Floating point absolute/negative **********/ 686/********** ================================ **********/ 687 688// Prevent expanding both fneg and fabs. 689 690def : Pat < 691 (fneg (fabs f32:$src)), 692 (S_OR_B32 $src, (S_MOV_B32(i32 0x80000000))) // Set sign bit 693>; 694 695// FIXME: Should use S_OR_B32 696def : Pat < 697 (fneg (fabs f64:$src)), 698 (REG_SEQUENCE VReg_64, 699 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 700 sub0, 701 (V_OR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 702 (V_MOV_B32_e32 (i32 0x80000000))), // Set sign bit. 703 sub1) 704>; 705 706def : Pat < 707 (fabs f32:$src), 708 (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x7fffffff))) 709>; 710 711def : Pat < 712 (fneg f32:$src), 713 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x80000000))) 714>; 715 716def : Pat < 717 (fabs f64:$src), 718 (REG_SEQUENCE VReg_64, 719 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 720 sub0, 721 (V_AND_B32_e64 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 722 (V_MOV_B32_e32 (i32 0x7fffffff))), // Set sign bit. 723 sub1) 724>; 725 726def : Pat < 727 (fneg f64:$src), 728 (REG_SEQUENCE VReg_64, 729 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 730 sub0, 731 (V_XOR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 732 (i32 (V_MOV_B32_e32 (i32 0x80000000)))), 733 sub1) 734>; 735 736def : Pat < 737 (fcopysign f16:$src0, f16:$src1), 738 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, $src1) 739>; 740 741def : Pat < 742 (fcopysign f32:$src0, f16:$src1), 743 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), $src0, 744 (V_LSHLREV_B32_e64 (i32 16), $src1)) 745>; 746 747def : Pat < 748 (fcopysign f64:$src0, f16:$src1), 749 (REG_SEQUENCE SReg_64, 750 (i32 (EXTRACT_SUBREG $src0, sub0)), sub0, 751 (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), (i32 (EXTRACT_SUBREG $src0, sub1)), 752 (V_LSHLREV_B32_e64 (i32 16), $src1)), sub1) 753>; 754 755def : Pat < 756 (fcopysign f16:$src0, f32:$src1), 757 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 758 (V_LSHRREV_B32_e64 (i32 16), $src1)) 759>; 760 761def : Pat < 762 (fcopysign f16:$src0, f64:$src1), 763 (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, 764 (V_LSHRREV_B32_e64 (i32 16), (EXTRACT_SUBREG $src1, sub1))) 765>; 766 767def : Pat < 768 (fneg f16:$src), 769 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x00008000))) 770>; 771 772def : Pat < 773 (fabs f16:$src), 774 (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x00007fff))) 775>; 776 777def : Pat < 778 (fneg (fabs f16:$src)), 779 (S_OR_B32 $src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit 780>; 781 782def : Pat < 783 (fneg v2f16:$src), 784 (V_XOR_B32_e64 (S_MOV_B32 (i32 0x80008000)), $src) 785>; 786 787def : Pat < 788 (fabs v2f16:$src), 789 (V_AND_B32_e64 (S_MOV_B32 (i32 0x7fff7fff)), $src) 790>; 791 792// This is really (fneg (fabs v2f16:$src)) 793// 794// fabs is not reported as free because there is modifier for it in 795// VOP3P instructions, so it is turned into the bit op. 796def : Pat < 797 (fneg (v2f16 (bitconvert (and_oneuse i32:$src, 0x7fff7fff)))), 798 (S_OR_B32 (S_MOV_B32 (i32 0x80008000)), $src) // Set sign bit 799>; 800 801/********** ================== **********/ 802/********** Immediate Patterns **********/ 803/********** ================== **********/ 804 805def : Pat < 806 (VGPRImm<(i32 imm)>:$imm), 807 (V_MOV_B32_e32 imm:$imm) 808>; 809 810def : Pat < 811 (VGPRImm<(f32 fpimm)>:$imm), 812 (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm))) 813>; 814 815def : Pat < 816 (i32 imm:$imm), 817 (S_MOV_B32 imm:$imm) 818>; 819 820// FIXME: Workaround for ordering issue with peephole optimizer where 821// a register class copy interferes with immediate folding. Should 822// use s_mov_b32, which can be shrunk to s_movk_i32 823def : Pat < 824 (VGPRImm<(f16 fpimm)>:$imm), 825 (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm))) 826>; 827 828def : Pat < 829 (f32 fpimm:$imm), 830 (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm))) 831>; 832 833def : Pat < 834 (f16 fpimm:$imm), 835 (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm))) 836>; 837 838def : Pat < 839 (i32 frameindex:$fi), 840 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi))) 841>; 842 843def : Pat < 844 (i64 InlineImm<i64>:$imm), 845 (S_MOV_B64 InlineImm<i64>:$imm) 846>; 847 848// XXX - Should this use a s_cmp to set SCC? 849 850// Set to sign-extended 64-bit value (true = -1, false = 0) 851def : Pat < 852 (i1 imm:$imm), 853 (S_MOV_B64 (i64 (as_i64imm $imm))) 854>; 855 856def : Pat < 857 (f64 InlineFPImm<f64>:$imm), 858 (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineFPImm<f64>:$imm))) 859>; 860 861/********** ================== **********/ 862/********** Intrinsic Patterns **********/ 863/********** ================== **********/ 864 865def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>; 866 867def : Pat < 868 (i32 (sext i1:$src0)), 869 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src0) 870>; 871 872class Ext32Pat <SDNode ext> : Pat < 873 (i32 (ext i1:$src0)), 874 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src0) 875>; 876 877def : Ext32Pat <zext>; 878def : Ext32Pat <anyext>; 879 880// The multiplication scales from [0,1] to the unsigned integer range 881def : Pat < 882 (AMDGPUurecip i32:$src0), 883 (V_CVT_U32_F32_e32 884 (V_MUL_F32_e32 (i32 CONST.FP_UINT_MAX_PLUS_1), 885 (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0)))) 886>; 887 888//===----------------------------------------------------------------------===// 889// VOP3 Patterns 890//===----------------------------------------------------------------------===// 891 892def : IMad24Pat<V_MAD_I32_I24>; 893def : UMad24Pat<V_MAD_U32_U24>; 894 895defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>; 896def : ROTRPattern <V_ALIGNBIT_B32>; 897 898/********** ====================== **********/ 899/********** Indirect addressing **********/ 900/********** ====================== **********/ 901 902multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> { 903 // Extract with offset 904 def : Pat< 905 (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))), 906 (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset) 907 >; 908 909 // Insert with offset 910 def : Pat< 911 (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))), 912 (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val) 913 >; 914} 915 916defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">; 917defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">; 918defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">; 919defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">; 920 921defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">; 922defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">; 923defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">; 924defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">; 925 926//===----------------------------------------------------------------------===// 927// SAD Patterns 928//===----------------------------------------------------------------------===// 929 930def : Pat < 931 (add (sub_oneuse (umax i32:$src0, i32:$src1), 932 (umin i32:$src0, i32:$src1)), 933 i32:$src2), 934 (V_SAD_U32 $src0, $src1, $src2) 935>; 936 937def : Pat < 938 (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)), 939 (sub i32:$src0, i32:$src1), 940 (sub i32:$src1, i32:$src0)), 941 i32:$src2), 942 (V_SAD_U32 $src0, $src1, $src2) 943>; 944 945//===----------------------------------------------------------------------===// 946// Conversion Patterns 947//===----------------------------------------------------------------------===// 948 949def : Pat<(i32 (sext_inreg i32:$src, i1)), 950 (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16 951 952// Handle sext_inreg in i64 953def : Pat < 954 (i64 (sext_inreg i64:$src, i1)), 955 (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16 956>; 957 958def : Pat < 959 (i16 (sext_inreg i16:$src, i1)), 960 (S_BFE_I32 $src, (i32 0x00010000)) // 0 | 1 << 16 961>; 962 963def : Pat < 964 (i16 (sext_inreg i16:$src, i8)), 965 (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16 966>; 967 968def : Pat < 969 (i64 (sext_inreg i64:$src, i8)), 970 (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16 971>; 972 973def : Pat < 974 (i64 (sext_inreg i64:$src, i16)), 975 (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16 976>; 977 978def : Pat < 979 (i64 (sext_inreg i64:$src, i32)), 980 (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16 981>; 982 983def : Pat < 984 (i64 (zext i32:$src)), 985 (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1) 986>; 987 988def : Pat < 989 (i64 (anyext i32:$src)), 990 (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1) 991>; 992 993class ZExt_i64_i1_Pat <SDNode ext> : Pat < 994 (i64 (ext i1:$src)), 995 (REG_SEQUENCE VReg_64, 996 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src), sub0, 997 (S_MOV_B32 (i32 0)), sub1) 998>; 999 1000 1001def : ZExt_i64_i1_Pat<zext>; 1002def : ZExt_i64_i1_Pat<anyext>; 1003 1004// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that 1005// REG_SEQUENCE patterns don't support instructions with multiple outputs. 1006def : Pat < 1007 (i64 (sext i32:$src)), 1008 (REG_SEQUENCE SReg_64, $src, sub0, 1009 (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1) 1010>; 1011 1012def : Pat < 1013 (i64 (sext i1:$src)), 1014 (REG_SEQUENCE VReg_64, 1015 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub0, 1016 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub1) 1017>; 1018 1019class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : Pat < 1020 (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))), 1021 (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)) 1022>; 1023 1024def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>; 1025def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>; 1026def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>; 1027def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>; 1028 1029// If we need to perform a logical operation on i1 values, we need to 1030// use vector comparisons since there is only one SCC register. Vector 1031// comparisons still write to a pair of SGPRs, so treat these as 1032// 64-bit comparisons. When legalizing SGPR copies, instructions 1033// resulting in the copies from SCC to these instructions will be 1034// moved to the VALU. 1035def : Pat < 1036 (i1 (and i1:$src0, i1:$src1)), 1037 (S_AND_B64 $src0, $src1) 1038>; 1039 1040def : Pat < 1041 (i1 (or i1:$src0, i1:$src1)), 1042 (S_OR_B64 $src0, $src1) 1043>; 1044 1045def : Pat < 1046 (i1 (xor i1:$src0, i1:$src1)), 1047 (S_XOR_B64 $src0, $src1) 1048>; 1049 1050def : Pat < 1051 (f32 (sint_to_fp i1:$src)), 1052 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_NEG_ONE), $src) 1053>; 1054 1055def : Pat < 1056 (f32 (uint_to_fp i1:$src)), 1057 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_ONE), $src) 1058>; 1059 1060def : Pat < 1061 (f64 (sint_to_fp i1:$src)), 1062 (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src)) 1063>; 1064 1065def : Pat < 1066 (f64 (uint_to_fp i1:$src)), 1067 (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src)) 1068>; 1069 1070//===----------------------------------------------------------------------===// 1071// Miscellaneous Patterns 1072//===----------------------------------------------------------------------===// 1073 1074def : Pat < 1075 (i32 (trunc i64:$a)), 1076 (EXTRACT_SUBREG $a, sub0) 1077>; 1078 1079def : Pat < 1080 (i1 (trunc i32:$a)), 1081 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1082>; 1083 1084def : Pat < 1085 (i1 (trunc i16:$a)), 1086 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 1087>; 1088 1089def : Pat < 1090 (i1 (trunc i64:$a)), 1091 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), 1092 (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1)) 1093>; 1094 1095def : Pat < 1096 (i32 (bswap i32:$a)), 1097 (V_BFI_B32 (S_MOV_B32 (i32 0x00ff00ff)), 1098 (V_ALIGNBIT_B32 $a, $a, (i32 24)), 1099 (V_ALIGNBIT_B32 $a, $a, (i32 8))) 1100>; 1101 1102multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> { 1103 def : Pat < 1104 (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)), 1105 (BFM $a, $b) 1106 >; 1107 1108 def : Pat < 1109 (vt (add (vt (shl 1, vt:$a)), -1)), 1110 (BFM $a, (MOV (i32 0))) 1111 >; 1112} 1113 1114defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>; 1115// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>; 1116defm : BFEPattern <V_BFE_U32, V_BFE_I32, S_MOV_B32>; 1117 1118def : Pat< 1119 (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))), 1120 (V_MUL_F16_e64 0, (i32 CONST.FP16_ONE), $src_mods, $src, 0, 0) 1121>; 1122 1123def : Pat< 1124 (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))), 1125 (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), $src_mods, $src, 0, 0) 1126>; 1127 1128def : Pat< 1129 (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))), 1130 (V_MUL_F64 0, CONST.FP64_ONE, $src_mods, $src, 0, 0) 1131>; 1132 1133def : Pat< 1134 (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))), 1135 (V_PK_MUL_F16 SRCMODS.OP_SEL_1, (i32 CONST.V2FP16_ONE), $src_mods, $src, DSTCLAMP.NONE) 1136>; 1137 1138 1139// Allow integer inputs 1140class ExpPattern<SDPatternOperator node, ValueType vt, Instruction Inst> : Pat< 1141 (node (i8 timm:$tgt), (i8 timm:$en), vt:$src0, vt:$src1, vt:$src2, vt:$src3, (i1 timm:$compr), (i1 timm:$vm)), 1142 (Inst i8:$tgt, vt:$src0, vt:$src1, vt:$src2, vt:$src3, i1:$vm, i1:$compr, i8:$en) 1143>; 1144 1145def : ExpPattern<AMDGPUexport, i32, EXP>; 1146def : ExpPattern<AMDGPUexport_done, i32, EXP_DONE>; 1147 1148def : Pat < 1149 (v2i16 (build_vector i16:$src0, i16:$src1)), 1150 (v2i16 (S_PACK_LL_B32_B16 $src0, $src1)) 1151>; 1152 1153// With multiple uses of the shift, this will duplicate the shift and 1154// increase register pressure. 1155def : Pat < 1156 (v2i16 (build_vector i16:$src0, (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))), 1157 (v2i16 (S_PACK_LH_B32_B16 i16:$src0, i32:$src1)) 1158>; 1159 1160def : Pat < 1161 (v2i16 (build_vector (i16 (trunc (srl_oneuse i32:$src0, (i32 16)))), 1162 (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))), 1163 (v2i16 (S_PACK_HH_B32_B16 $src0, $src1)) 1164>; 1165 1166// TODO: Should source modifiers be matched to v_pack_b32_f16? 1167def : Pat < 1168 (v2f16 (build_vector f16:$src0, f16:$src1)), 1169 (v2f16 (S_PACK_LL_B32_B16 $src0, $src1)) 1170>; 1171 1172// def : Pat < 1173// (v2f16 (scalar_to_vector f16:$src0)), 1174// (COPY $src0) 1175// >; 1176 1177// def : Pat < 1178// (v2i16 (scalar_to_vector i16:$src0)), 1179// (COPY $src0) 1180// >; 1181 1182//===----------------------------------------------------------------------===// 1183// Fract Patterns 1184//===----------------------------------------------------------------------===// 1185 1186let Predicates = [isSI] in { 1187 1188// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is 1189// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient 1190// way to implement it is using V_FRACT_F64. 1191// The workaround for the V_FRACT bug is: 1192// fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999) 1193 1194// Convert floor(x) to (x - fract(x)) 1195def : Pat < 1196 (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))), 1197 (V_ADD_F64 1198 $mods, 1199 $x, 1200 SRCMODS.NEG, 1201 (V_CNDMASK_B64_PSEUDO 1202 (V_MIN_F64 1203 SRCMODS.NONE, 1204 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE), 1205 SRCMODS.NONE, 1206 (V_MOV_B64_PSEUDO 0x3fefffffffffffff), 1207 DSTCLAMP.NONE, DSTOMOD.NONE), 1208 $x, 1209 (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))), 1210 DSTCLAMP.NONE, DSTOMOD.NONE) 1211>; 1212 1213} // End Predicates = [isSI] 1214 1215//============================================================================// 1216// Miscellaneous Optimization Patterns 1217//============================================================================// 1218 1219// Undo sub x, c -> add x, -c canonicalization since c is more likely 1220// an inline immediate than -c. 1221// TODO: Also do for 64-bit. 1222def : Pat< 1223 (add i32:$src0, (i32 NegSubInlineConst32:$src1)), 1224 (S_SUB_I32 $src0, NegSubInlineConst32:$src1) 1225>; 1226 1227def : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64>; 1228 1229def : IntMed3Pat<V_MED3_I32, smax, smax_oneuse, smin_oneuse>; 1230def : IntMed3Pat<V_MED3_U32, umax, umax_oneuse, umin_oneuse>; 1231 1232// This matches 16 permutations of 1233// max(min(x, y), min(max(x, y), z)) 1234class FPMed3Pat<ValueType vt, 1235 Instruction med3Inst> : Pat< 1236 (fmaxnum (fminnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1237 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1238 (fminnum_oneuse (fmaxnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods), 1239 (VOP3Mods_nnan vt:$src1, i32:$src1_mods)), 1240 (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))), 1241 (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE, DSTOMOD.NONE) 1242>; 1243 1244def : FPMed3Pat<f32, V_MED3_F32>; 1245 1246let Predicates = [isGFX9] in { 1247def : FPMed3Pat<f16, V_MED3_F16>; 1248def : IntMed3Pat<V_MED3_I16, smax, smax_oneuse, smin_oneuse, i16>; 1249def : IntMed3Pat<V_MED3_U16, umax, umax_oneuse, umin_oneuse, i16>; 1250} // End Predicates = [isGFX9] 1251 1252//============================================================================// 1253// Assembler aliases 1254//============================================================================// 1255 1256def : MnemonicAlias<"v_add_u32", "v_add_i32">; 1257def : MnemonicAlias<"v_sub_u32", "v_sub_i32">; 1258def : MnemonicAlias<"v_subrev_u32", "v_subrev_i32">; 1259 1260} // End isGCN predicate 1261