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