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, i32imm:$attrchan, i32imm:$attr), 55 "v_interp_p1_f32 $vdst, $vsrc, $attrchan, $attr", 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, i32imm:$attrchan, i32imm:$attr), 78 "v_interp_p2_f32 $vdst, $vsrc, $attrchan, $attr", 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, i32imm:$attrchan, i32imm:$attr), 88 "v_interp_mov_f32 $vdst, $vsrc, $attrchan, $attr", 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 114let usesCustomInserter = 1, SALU = 1 in { 115def GET_GROUPSTATICSIZE : PseudoInstSI <(outs SReg_32:$sdst), (ins), 116 [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>; 117} // End let usesCustomInserter = 1, SALU = 1 118 119def S_MOV_B64_term : PseudoInstSI<(outs SReg_64:$dst), 120 (ins SSrc_b64:$src0)> { 121 let SALU = 1; 122 let isAsCheapAsAMove = 1; 123 let isTerminator = 1; 124} 125 126def S_XOR_B64_term : PseudoInstSI<(outs SReg_64:$dst), 127 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 128 let SALU = 1; 129 let isAsCheapAsAMove = 1; 130 let isTerminator = 1; 131} 132 133def S_ANDN2_B64_term : PseudoInstSI<(outs SReg_64:$dst), 134 (ins SSrc_b64:$src0, SSrc_b64:$src1)> { 135 let SALU = 1; 136 let isAsCheapAsAMove = 1; 137 let isTerminator = 1; 138} 139 140def WAVE_BARRIER : SPseudoInstSI<(outs), (ins), 141 [(int_amdgcn_wave_barrier)]> { 142 let SchedRW = []; 143 let hasNoSchedulingInfo = 1; 144 let hasSideEffects = 1; 145 let mayLoad = 1; 146 let mayStore = 1; 147 let isBarrier = 1; 148 let isConvergent = 1; 149} 150 151// SI pseudo instructions. These are used by the CFG structurizer pass 152// and should be lowered to ISA instructions prior to codegen. 153 154// Dummy terminator instruction to use after control flow instructions 155// replaced with exec mask operations. 156def SI_MASK_BRANCH : PseudoInstSI < 157 (outs), (ins brtarget:$target)> { 158 let isBranch = 0; 159 let isTerminator = 1; 160 let isBarrier = 0; 161 let Uses = [EXEC]; 162 let SchedRW = []; 163 let hasNoSchedulingInfo = 1; 164} 165 166let isTerminator = 1 in { 167 168def SI_IF: CFPseudoInstSI < 169 (outs SReg_64:$dst), (ins SReg_64:$vcc, brtarget:$target), 170 [(set i64:$dst, (int_amdgcn_if i1:$vcc, bb:$target))], 1, 1> { 171 let Constraints = ""; 172 let Size = 12; 173 let mayLoad = 1; 174 let mayStore = 1; 175 let hasSideEffects = 1; 176} 177 178def SI_ELSE : CFPseudoInstSI < 179 (outs SReg_64:$dst), (ins SReg_64:$src, brtarget:$target, i1imm:$execfix), [], 1, 1> { 180 let Constraints = "$src = $dst"; 181 let Size = 12; 182 let mayStore = 1; 183 let mayLoad = 1; 184 let hasSideEffects = 1; 185} 186 187def SI_LOOP : CFPseudoInstSI < 188 (outs), (ins SReg_64:$saved, brtarget:$target), 189 [(int_amdgcn_loop i64:$saved, bb:$target)], 1, 1> { 190 let Size = 8; 191 let isBranch = 1; 192 let hasSideEffects = 1; 193 let mayLoad = 1; 194 let mayStore = 1; 195} 196 197} // End isBranch = 1, isTerminator = 1 198 199def SI_END_CF : CFPseudoInstSI < 200 (outs), (ins SReg_64:$saved), 201 [(int_amdgcn_end_cf i64:$saved)], 1, 1> { 202 let Size = 4; 203 let isAsCheapAsAMove = 1; 204 let isReMaterializable = 1; 205 let mayLoad = 1; 206 let mayStore = 1; 207 let hasSideEffects = 1; 208} 209 210def SI_BREAK : CFPseudoInstSI < 211 (outs SReg_64:$dst), (ins SReg_64:$src), 212 [(set i64:$dst, (int_amdgcn_break i64:$src))], 1> { 213 let Size = 4; 214 let isAsCheapAsAMove = 1; 215 let isReMaterializable = 1; 216} 217 218def SI_IF_BREAK : CFPseudoInstSI < 219 (outs SReg_64:$dst), (ins SReg_64:$vcc, SReg_64:$src), 220 [(set i64:$dst, (int_amdgcn_if_break i1:$vcc, i64:$src))]> { 221 let Size = 4; 222 let isAsCheapAsAMove = 1; 223 let isReMaterializable = 1; 224} 225 226def SI_ELSE_BREAK : CFPseudoInstSI < 227 (outs SReg_64:$dst), (ins SReg_64:$src0, SReg_64:$src1), 228 [(set i64:$dst, (int_amdgcn_else_break i64:$src0, i64:$src1))]> { 229 let Size = 4; 230 let isAsCheapAsAMove = 1; 231 let isReMaterializable = 1; 232} 233 234let Uses = [EXEC], Defs = [EXEC,VCC] in { 235def SI_KILL : PseudoInstSI < 236 (outs), (ins VSrc_b32:$src), 237 [(AMDGPUkill i32:$src)]> { 238 let isConvergent = 1; 239 let usesCustomInserter = 1; 240} 241 242def SI_KILL_TERMINATOR : SPseudoInstSI < 243 (outs), (ins VSrc_b32:$src)> { 244 let isTerminator = 1; 245} 246 247} // End Uses = [EXEC], Defs = [EXEC,VCC] 248 249 250def SI_PS_LIVE : PseudoInstSI < 251 (outs SReg_64:$dst), (ins), 252 [(set i1:$dst, (int_amdgcn_ps_live))]> { 253 let SALU = 1; 254} 255 256// Used as an isel pseudo to directly emit initialization with an 257// s_mov_b32 rather than a copy of another initialized 258// register. MachineCSE skips copies, and we don't want to have to 259// fold operands before it runs. 260def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> { 261 let Defs = [M0]; 262 let usesCustomInserter = 1; 263 let isAsCheapAsAMove = 1; 264 let isReMaterializable = 1; 265} 266 267def SI_RETURN : SPseudoInstSI < 268 (outs), (ins variable_ops), [(AMDGPUreturn)]> { 269 let isTerminator = 1; 270 let isBarrier = 1; 271 let isReturn = 1; 272 let hasSideEffects = 1; 273 let hasNoSchedulingInfo = 1; 274 let DisableWQM = 1; 275} 276 277let Defs = [M0, EXEC], 278 UseNamedOperandTable = 1 in { 279 280class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI < 281 (outs VGPR_32:$vdst), 282 (ins rc:$src, VS_32:$idx, i32imm:$offset)> { 283 let usesCustomInserter = 1; 284} 285 286class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI < 287 (outs rc:$vdst), 288 (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> { 289 let Constraints = "$src = $vdst"; 290 let usesCustomInserter = 1; 291} 292 293// TODO: We can support indirect SGPR access. 294def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>; 295def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>; 296def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>; 297def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>; 298def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>; 299 300def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>; 301def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>; 302def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>; 303def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>; 304def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>; 305 306} // End Uses = [EXEC], Defs = [M0, EXEC] 307 308multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> { 309 let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in { 310 def _SAVE : PseudoInstSI < 311 (outs), 312 (ins sgpr_class:$data, i32imm:$addr)> { 313 let mayStore = 1; 314 let mayLoad = 0; 315 } 316 317 def _RESTORE : PseudoInstSI < 318 (outs sgpr_class:$data), 319 (ins i32imm:$addr)> { 320 let mayStore = 0; 321 let mayLoad = 1; 322 } 323 } // End UseNamedOperandTable = 1 324} 325 326// You cannot use M0 as the output of v_readlane_b32 instructions or 327// use it in the sdata operand of SMEM instructions. We still need to 328// be able to spill the physical register m0, so allow it for 329// SI_SPILL_32_* instructions. 330defm SI_SPILL_S32 : SI_SPILL_SGPR <SReg_32>; 331defm SI_SPILL_S64 : SI_SPILL_SGPR <SReg_64>; 332defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>; 333defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>; 334defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>; 335 336multiclass SI_SPILL_VGPR <RegisterClass vgpr_class> { 337 let UseNamedOperandTable = 1, VGPRSpill = 1, 338 SchedRW = [WriteVMEM] in { 339 def _SAVE : VPseudoInstSI < 340 (outs), 341 (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc, 342 SReg_32:$soffset, i32imm:$offset)> { 343 let mayStore = 1; 344 let mayLoad = 0; 345 // (2 * 4) + (8 * num_subregs) bytes maximum 346 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 347 } 348 349 def _RESTORE : VPseudoInstSI < 350 (outs vgpr_class:$vdata), 351 (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset, 352 i32imm:$offset)> { 353 let mayStore = 0; 354 let mayLoad = 1; 355 356 // (2 * 4) + (8 * num_subregs) bytes maximum 357 let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8); 358 } 359 } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM] 360} 361 362defm SI_SPILL_V32 : SI_SPILL_VGPR <VGPR_32>; 363defm SI_SPILL_V64 : SI_SPILL_VGPR <VReg_64>; 364defm SI_SPILL_V96 : SI_SPILL_VGPR <VReg_96>; 365defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>; 366defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>; 367defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>; 368 369def SI_PC_ADD_REL_OFFSET : SPseudoInstSI < 370 (outs SReg_64:$dst), 371 (ins si_ga:$ptr_lo, si_ga:$ptr_hi), 372 [(set SReg_64:$dst, 373 (i64 (SIpc_add_rel_offset (tglobaladdr:$ptr_lo), (tglobaladdr:$ptr_hi))))]> { 374 let Defs = [SCC]; 375} 376 377} // End SubtargetPredicate = isGCN 378 379let Predicates = [isGCN] in { 380 381def : Pat< 382 (int_amdgcn_else i64:$src, bb:$target), 383 (SI_ELSE $src, $target, 0) 384>; 385 386def : Pat < 387 (int_AMDGPU_kilp), 388 (SI_KILL (i32 0xbf800000)) 389>; 390 391//===----------------------------------------------------------------------===// 392// VOP1 Patterns 393//===----------------------------------------------------------------------===// 394 395let Predicates = [UnsafeFPMath] in { 396 397//def : RcpPat<V_RCP_F64_e32, f64>; 398//defm : RsqPat<V_RSQ_F64_e32, f64>; 399//defm : RsqPat<V_RSQ_F32_e32, f32>; 400 401def : RsqPat<V_RSQ_F32_e32, f32>; 402def : RsqPat<V_RSQ_F64_e32, f64>; 403 404// Convert (x - floor(x)) to fract(x) 405def : Pat < 406 (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)), 407 (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))), 408 (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 409>; 410 411// Convert (x + (-floor(x))) to fract(x) 412def : Pat < 413 (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)), 414 (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))), 415 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 416>; 417 418} // End Predicates = [UnsafeFPMath] 419 420def : Pat < 421 (f32 (fpextend f16:$src)), 422 (V_CVT_F32_F16_e32 $src) 423>; 424 425def : Pat < 426 (f64 (fpextend f16:$src)), 427 (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src)) 428>; 429 430def : Pat < 431 (f16 (fpround f32:$src)), 432 (V_CVT_F16_F32_e32 $src) 433>; 434 435def : Pat < 436 (f16 (fpround f64:$src)), 437 (V_CVT_F16_F32_e32 (V_CVT_F32_F64_e32 $src)) 438>; 439 440def : Pat < 441 (i32 (fp_to_sint f16:$src)), 442 (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 $src)) 443>; 444 445def : Pat < 446 (i32 (fp_to_uint f16:$src)), 447 (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 $src)) 448>; 449 450def : Pat < 451 (f16 (sint_to_fp i32:$src)), 452 (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 $src)) 453>; 454 455def : Pat < 456 (f16 (uint_to_fp i32:$src)), 457 (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 $src)) 458>; 459 460//===----------------------------------------------------------------------===// 461// VOP2 Patterns 462//===----------------------------------------------------------------------===// 463 464multiclass FMADPat <ValueType vt, Instruction inst> { 465 def : Pat < 466 (vt (fmad (VOP3NoMods0 vt:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod), 467 (VOP3NoMods vt:$src1, i32:$src1_modifiers), 468 (VOP3NoMods vt:$src2, i32:$src2_modifiers))), 469 (inst $src0_modifiers, $src0, $src1_modifiers, $src1, 470 $src2_modifiers, $src2, $clamp, $omod) 471 >; 472} 473 474defm : FMADPat <f16, V_MAC_F16_e64>; 475defm : FMADPat <f32, V_MAC_F32_e64>; 476 477multiclass SelectPat <ValueType vt, Instruction inst> { 478 def : Pat < 479 (vt (select i1:$src0, vt:$src1, vt:$src2)), 480 (inst $src2, $src1, $src0) 481 >; 482} 483 484defm : SelectPat <i16, V_CNDMASK_B32_e64>; 485defm : SelectPat <i32, V_CNDMASK_B32_e64>; 486defm : SelectPat <f16, V_CNDMASK_B32_e64>; 487defm : SelectPat <f32, V_CNDMASK_B32_e64>; 488 489def : Pat < 490 (i32 (add (i32 (ctpop i32:$popcnt)), i32:$val)), 491 (V_BCNT_U32_B32_e64 $popcnt, $val) 492>; 493 494/********** ============================================ **********/ 495/********** Extraction, Insertion, Building and Casting **********/ 496/********** ============================================ **********/ 497 498foreach Index = 0-2 in { 499 def Extract_Element_v2i32_#Index : Extract_Element < 500 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 501 >; 502 def Insert_Element_v2i32_#Index : Insert_Element < 503 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 504 >; 505 506 def Extract_Element_v2f32_#Index : Extract_Element < 507 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 508 >; 509 def Insert_Element_v2f32_#Index : Insert_Element < 510 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 511 >; 512} 513 514foreach Index = 0-3 in { 515 def Extract_Element_v4i32_#Index : Extract_Element < 516 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 517 >; 518 def Insert_Element_v4i32_#Index : Insert_Element < 519 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 520 >; 521 522 def Extract_Element_v4f32_#Index : Extract_Element < 523 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 524 >; 525 def Insert_Element_v4f32_#Index : Insert_Element < 526 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 527 >; 528} 529 530foreach Index = 0-7 in { 531 def Extract_Element_v8i32_#Index : Extract_Element < 532 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 533 >; 534 def Insert_Element_v8i32_#Index : Insert_Element < 535 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 536 >; 537 538 def Extract_Element_v8f32_#Index : Extract_Element < 539 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 540 >; 541 def Insert_Element_v8f32_#Index : Insert_Element < 542 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 543 >; 544} 545 546foreach Index = 0-15 in { 547 def Extract_Element_v16i32_#Index : Extract_Element < 548 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 549 >; 550 def Insert_Element_v16i32_#Index : Insert_Element < 551 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 552 >; 553 554 def Extract_Element_v16f32_#Index : Extract_Element < 555 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 556 >; 557 def Insert_Element_v16f32_#Index : Insert_Element < 558 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 559 >; 560} 561 562// FIXME: Why do only some of these type combinations for SReg and 563// VReg? 564// 16-bit bitcast 565def : BitConvert <i16, f16, VGPR_32>; 566def : BitConvert <f16, i16, VGPR_32>; 567def : BitConvert <i16, f16, SReg_32>; 568def : BitConvert <f16, i16, SReg_32>; 569 570// 32-bit bitcast 571def : BitConvert <i32, f32, VGPR_32>; 572def : BitConvert <f32, i32, VGPR_32>; 573def : BitConvert <i32, f32, SReg_32>; 574def : BitConvert <f32, i32, SReg_32>; 575 576// 64-bit bitcast 577def : BitConvert <i64, f64, VReg_64>; 578def : BitConvert <f64, i64, VReg_64>; 579def : BitConvert <v2i32, v2f32, VReg_64>; 580def : BitConvert <v2f32, v2i32, VReg_64>; 581def : BitConvert <i64, v2i32, VReg_64>; 582def : BitConvert <v2i32, i64, VReg_64>; 583def : BitConvert <i64, v2f32, VReg_64>; 584def : BitConvert <v2f32, i64, VReg_64>; 585def : BitConvert <f64, v2f32, VReg_64>; 586def : BitConvert <v2f32, f64, VReg_64>; 587def : BitConvert <f64, v2i32, VReg_64>; 588def : BitConvert <v2i32, f64, VReg_64>; 589def : BitConvert <v4i32, v4f32, VReg_128>; 590def : BitConvert <v4f32, v4i32, VReg_128>; 591 592// 128-bit bitcast 593def : BitConvert <v2i64, v4i32, SReg_128>; 594def : BitConvert <v4i32, v2i64, SReg_128>; 595def : BitConvert <v2f64, v4f32, VReg_128>; 596def : BitConvert <v2f64, v4i32, VReg_128>; 597def : BitConvert <v4f32, v2f64, VReg_128>; 598def : BitConvert <v4i32, v2f64, VReg_128>; 599def : BitConvert <v2i64, v2f64, VReg_128>; 600def : BitConvert <v2f64, v2i64, VReg_128>; 601 602// 256-bit bitcast 603def : BitConvert <v8i32, v8f32, SReg_256>; 604def : BitConvert <v8f32, v8i32, SReg_256>; 605def : BitConvert <v8i32, v8f32, VReg_256>; 606def : BitConvert <v8f32, v8i32, VReg_256>; 607 608// 512-bit bitcast 609def : BitConvert <v16i32, v16f32, VReg_512>; 610def : BitConvert <v16f32, v16i32, VReg_512>; 611 612/********** =================== **********/ 613/********** Src & Dst modifiers **********/ 614/********** =================== **********/ 615 616def : Pat < 617 (AMDGPUclamp (VOP3Mods0Clamp f32:$src0, i32:$src0_modifiers, i32:$omod), 618 (f32 FP_ZERO), (f32 FP_ONE)), 619 (V_ADD_F32_e64 $src0_modifiers, $src0, 0, (i32 0), 1, $omod) 620>; 621 622/********** ================================ **********/ 623/********** Floating point absolute/negative **********/ 624/********** ================================ **********/ 625 626// Prevent expanding both fneg and fabs. 627 628def : Pat < 629 (fneg (fabs f32:$src)), 630 (S_OR_B32 $src, (S_MOV_B32(i32 0x80000000))) // Set sign bit 631>; 632 633// FIXME: Should use S_OR_B32 634def : Pat < 635 (fneg (fabs f64:$src)), 636 (REG_SEQUENCE VReg_64, 637 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 638 sub0, 639 (V_OR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 640 (V_MOV_B32_e32 (i32 0x80000000))), // Set sign bit. 641 sub1) 642>; 643 644def : Pat < 645 (fabs f32:$src), 646 (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x7fffffff))) 647>; 648 649def : Pat < 650 (fneg f32:$src), 651 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x80000000))) 652>; 653 654def : Pat < 655 (fabs f64:$src), 656 (REG_SEQUENCE VReg_64, 657 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 658 sub0, 659 (V_AND_B32_e64 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 660 (V_MOV_B32_e32 (i32 0x7fffffff))), // Set sign bit. 661 sub1) 662>; 663 664def : Pat < 665 (fneg f64:$src), 666 (REG_SEQUENCE VReg_64, 667 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 668 sub0, 669 (V_XOR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)), 670 (i32 (V_MOV_B32_e32 (i32 0x80000000)))), 671 sub1) 672>; 673 674def : Pat < 675 (fneg f16:$src), 676 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x00008000))) 677>; 678 679def : Pat < 680 (fabs f16:$src), 681 (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x00007fff))) 682>; 683 684def : Pat < 685 (fneg (fabs f16:$src)), 686 (S_OR_B32 $src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit 687>; 688 689/********** ================== **********/ 690/********** Immediate Patterns **********/ 691/********** ================== **********/ 692 693def : Pat < 694 (VGPRImm<(i32 imm)>:$imm), 695 (V_MOV_B32_e32 imm:$imm) 696>; 697 698def : Pat < 699 (VGPRImm<(f32 fpimm)>:$imm), 700 (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm))) 701>; 702 703def : Pat < 704 (i32 imm:$imm), 705 (S_MOV_B32 imm:$imm) 706>; 707 708// FIXME: Workaround for ordering issue with peephole optimizer where 709// a register class copy interferes with immediate folding. Should 710// use s_mov_b32, which can be shrunk to s_movk_i32 711def : Pat < 712 (VGPRImm<(f16 fpimm)>:$imm), 713 (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm))) 714>; 715 716def : Pat < 717 (f32 fpimm:$imm), 718 (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm))) 719>; 720 721def : Pat < 722 (f16 fpimm:$imm), 723 (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm))) 724>; 725 726def : Pat < 727 (i32 frameindex:$fi), 728 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi))) 729>; 730 731def : Pat < 732 (i64 InlineImm<i64>:$imm), 733 (S_MOV_B64 InlineImm<i64>:$imm) 734>; 735 736// XXX - Should this use a s_cmp to set SCC? 737 738// Set to sign-extended 64-bit value (true = -1, false = 0) 739def : Pat < 740 (i1 imm:$imm), 741 (S_MOV_B64 (i64 (as_i64imm $imm))) 742>; 743 744def : Pat < 745 (f64 InlineFPImm<f64>:$imm), 746 (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineFPImm<f64>:$imm))) 747>; 748 749/********** ================== **********/ 750/********** Intrinsic Patterns **********/ 751/********** ================== **********/ 752 753def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>; 754 755def : Pat < 756 (int_AMDGPU_cube v4f32:$src), 757 (REG_SEQUENCE VReg_128, 758 (V_CUBETC_F32 0 /* src0_modifiers */, (f32 (EXTRACT_SUBREG $src, sub0)), 759 0 /* src1_modifiers */, (f32 (EXTRACT_SUBREG $src, sub1)), 760 0 /* src2_modifiers */, (f32 (EXTRACT_SUBREG $src, sub2)), 761 0 /* clamp */, 0 /* omod */), sub0, 762 (V_CUBESC_F32 0 /* src0_modifiers */, (f32 (EXTRACT_SUBREG $src, sub0)), 763 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub1)), 764 0 /* src2_modifiers */,(f32 (EXTRACT_SUBREG $src, sub2)), 765 0 /* clamp */, 0 /* omod */), sub1, 766 (V_CUBEMA_F32 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub0)), 767 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub1)), 768 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub2)), 769 0 /* clamp */, 0 /* omod */), sub2, 770 (V_CUBEID_F32 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub0)), 771 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub1)), 772 0 /* src1_modifiers */,(f32 (EXTRACT_SUBREG $src, sub2)), 773 0 /* clamp */, 0 /* omod */), sub3) 774>; 775 776def : Pat < 777 (i32 (sext i1:$src0)), 778 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src0) 779>; 780 781class Ext32Pat <SDNode ext> : Pat < 782 (i32 (ext i1:$src0)), 783 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src0) 784>; 785 786def : Ext32Pat <zext>; 787def : Ext32Pat <anyext>; 788 789// The multiplication scales from [0,1] to the unsigned integer range 790def : Pat < 791 (AMDGPUurecip i32:$src0), 792 (V_CVT_U32_F32_e32 793 (V_MUL_F32_e32 (i32 CONST.FP_UINT_MAX_PLUS_1), 794 (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0)))) 795>; 796 797//===----------------------------------------------------------------------===// 798// VOP3 Patterns 799//===----------------------------------------------------------------------===// 800 801def : IMad24Pat<V_MAD_I32_I24>; 802def : UMad24Pat<V_MAD_U32_U24>; 803 804defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>; 805def : ROTRPattern <V_ALIGNBIT_B32>; 806 807/********** ====================== **********/ 808/********** Indirect addressing **********/ 809/********** ====================== **********/ 810 811multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> { 812 // Extract with offset 813 def : Pat< 814 (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))), 815 (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset) 816 >; 817 818 // Insert with offset 819 def : Pat< 820 (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))), 821 (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val) 822 >; 823} 824 825defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">; 826defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">; 827defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">; 828defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">; 829 830defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">; 831defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">; 832defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">; 833defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">; 834 835//===----------------------------------------------------------------------===// 836// SAD Patterns 837//===----------------------------------------------------------------------===// 838 839def : Pat < 840 (add (sub_oneuse (umax i32:$src0, i32:$src1), 841 (umin i32:$src0, i32:$src1)), 842 i32:$src2), 843 (V_SAD_U32 $src0, $src1, $src2) 844>; 845 846def : Pat < 847 (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)), 848 (sub i32:$src0, i32:$src1), 849 (sub i32:$src1, i32:$src0)), 850 i32:$src2), 851 (V_SAD_U32 $src0, $src1, $src2) 852>; 853 854//===----------------------------------------------------------------------===// 855// Conversion Patterns 856//===----------------------------------------------------------------------===// 857 858def : Pat<(i32 (sext_inreg i32:$src, i1)), 859 (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16 860 861// Handle sext_inreg in i64 862def : Pat < 863 (i64 (sext_inreg i64:$src, i1)), 864 (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16 865>; 866 867def : Pat < 868 (i16 (sext_inreg i16:$src, i8)), 869 (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16 870>; 871 872def : Pat < 873 (i64 (sext_inreg i64:$src, i8)), 874 (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16 875>; 876 877def : Pat < 878 (i64 (sext_inreg i64:$src, i16)), 879 (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16 880>; 881 882def : Pat < 883 (i64 (sext_inreg i64:$src, i32)), 884 (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16 885>; 886 887def : Pat < 888 (i64 (zext i32:$src)), 889 (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1) 890>; 891 892def : Pat < 893 (i64 (anyext i32:$src)), 894 (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1) 895>; 896 897class ZExt_i64_i1_Pat <SDNode ext> : Pat < 898 (i64 (ext i1:$src)), 899 (REG_SEQUENCE VReg_64, 900 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src), sub0, 901 (S_MOV_B32 (i32 0)), sub1) 902>; 903 904 905def : ZExt_i64_i1_Pat<zext>; 906def : ZExt_i64_i1_Pat<anyext>; 907 908// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that 909// REG_SEQUENCE patterns don't support instructions with multiple outputs. 910def : Pat < 911 (i64 (sext i32:$src)), 912 (REG_SEQUENCE SReg_64, $src, sub0, 913 (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1) 914>; 915 916def : Pat < 917 (i64 (sext i1:$src)), 918 (REG_SEQUENCE VReg_64, 919 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub0, 920 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub1) 921>; 922 923class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : Pat < 924 (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))), 925 (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)) 926>; 927 928def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>; 929def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>; 930def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>; 931def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>; 932 933// If we need to perform a logical operation on i1 values, we need to 934// use vector comparisons since there is only one SCC register. Vector 935// comparisons still write to a pair of SGPRs, so treat these as 936// 64-bit comparisons. When legalizing SGPR copies, instructions 937// resulting in the copies from SCC to these instructions will be 938// moved to the VALU. 939def : Pat < 940 (i1 (and i1:$src0, i1:$src1)), 941 (S_AND_B64 $src0, $src1) 942>; 943 944def : Pat < 945 (i1 (or i1:$src0, i1:$src1)), 946 (S_OR_B64 $src0, $src1) 947>; 948 949def : Pat < 950 (i1 (xor i1:$src0, i1:$src1)), 951 (S_XOR_B64 $src0, $src1) 952>; 953 954def : Pat < 955 (f32 (sint_to_fp i1:$src)), 956 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_NEG_ONE), $src) 957>; 958 959def : Pat < 960 (f32 (uint_to_fp i1:$src)), 961 (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_ONE), $src) 962>; 963 964def : Pat < 965 (f64 (sint_to_fp i1:$src)), 966 (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src)) 967>; 968 969def : Pat < 970 (f64 (uint_to_fp i1:$src)), 971 (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src)) 972>; 973 974//===----------------------------------------------------------------------===// 975// Miscellaneous Patterns 976//===----------------------------------------------------------------------===// 977 978def : Pat < 979 (i32 (trunc i64:$a)), 980 (EXTRACT_SUBREG $a, sub0) 981>; 982 983def : Pat < 984 (i1 (trunc i32:$a)), 985 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1)) 986>; 987 988def : Pat < 989 (i1 (trunc i64:$a)), 990 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), 991 (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1)) 992>; 993 994def : Pat < 995 (i32 (bswap i32:$a)), 996 (V_BFI_B32 (S_MOV_B32 (i32 0x00ff00ff)), 997 (V_ALIGNBIT_B32 $a, $a, (i32 24)), 998 (V_ALIGNBIT_B32 $a, $a, (i32 8))) 999>; 1000 1001multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> { 1002 def : Pat < 1003 (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)), 1004 (BFM $a, $b) 1005 >; 1006 1007 def : Pat < 1008 (vt (add (vt (shl 1, vt:$a)), -1)), 1009 (BFM $a, (MOV (i32 0))) 1010 >; 1011} 1012 1013defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>; 1014// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>; 1015 1016def : BFEPattern <V_BFE_U32, S_MOV_B32>; 1017 1018def : Pat< 1019 (fcanonicalize f32:$src), 1020 (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), 0, $src, 0, 0) 1021>; 1022 1023def : Pat< 1024 (fcanonicalize f64:$src), 1025 (V_MUL_F64 0, CONST.FP64_ONE, 0, $src, 0, 0) 1026>; 1027 1028//===----------------------------------------------------------------------===// 1029// Fract Patterns 1030//===----------------------------------------------------------------------===// 1031 1032let Predicates = [isSI] in { 1033 1034// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is 1035// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient 1036// way to implement it is using V_FRACT_F64. 1037// The workaround for the V_FRACT bug is: 1038// fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999) 1039 1040// Convert floor(x) to (x - fract(x)) 1041def : Pat < 1042 (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))), 1043 (V_ADD_F64 1044 $mods, 1045 $x, 1046 SRCMODS.NEG, 1047 (V_CNDMASK_B64_PSEUDO 1048 (V_MIN_F64 1049 SRCMODS.NONE, 1050 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE), 1051 SRCMODS.NONE, 1052 (V_MOV_B64_PSEUDO 0x3fefffffffffffff), 1053 DSTCLAMP.NONE, DSTOMOD.NONE), 1054 $x, 1055 (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))), 1056 DSTCLAMP.NONE, DSTOMOD.NONE) 1057>; 1058 1059} // End Predicates = [isSI] 1060 1061//============================================================================// 1062// Miscellaneous Optimization Patterns 1063//============================================================================// 1064 1065def : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64>; 1066 1067def : IntMed3Pat<V_MED3_I32, smax, smax_oneuse, smin_oneuse>; 1068def : IntMed3Pat<V_MED3_U32, umax, umax_oneuse, umin_oneuse>; 1069 1070//============================================================================// 1071// Assembler aliases 1072//============================================================================// 1073 1074def : MnemonicAlias<"v_add_u32", "v_add_i32">; 1075def : MnemonicAlias<"v_sub_u32", "v_sub_i32">; 1076def : MnemonicAlias<"v_subrev_u32", "v_subrev_i32">; 1077 1078} // End isGCN predicate 1079