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_lo, si_ga:$ptr_hi), 362 [(set SReg_64:$dst, 363 (i64 (SIpc_add_rel_offset (tglobaladdr:$ptr_lo), (tglobaladdr:$ptr_hi))))]> { 364 let Defs = [SCC]; 365} 366 367} // End SubtargetPredicate = isGCN 368 369let Predicates = [isGCN] in { 370 371def : Pat< 372 (int_amdgcn_else i64:$src, bb:$target), 373 (SI_ELSE $src, $target, 0) 374>; 375 376def : Pat < 377 (int_AMDGPU_kilp), 378 (SI_KILL 0xbf800000) 379>; 380 381def : Pat < 382 (int_SI_export imm:$en, imm:$vm, imm:$done, imm:$tgt, imm:$compr, 383 f32:$src0, f32:$src1, f32:$src2, f32:$src3), 384 (EXP imm:$en, imm:$tgt, imm:$compr, imm:$done, imm:$vm, 385 $src0, $src1, $src2, $src3) 386>; 387 388//===----------------------------------------------------------------------===// 389// VOP1 Patterns 390//===----------------------------------------------------------------------===// 391 392let Predicates = [UnsafeFPMath] in { 393 394//def : RcpPat<V_RCP_F64_e32, f64>; 395//defm : RsqPat<V_RSQ_F64_e32, f64>; 396//defm : RsqPat<V_RSQ_F32_e32, f32>; 397 398def : RsqPat<V_RSQ_F32_e32, f32>; 399def : RsqPat<V_RSQ_F64_e32, f64>; 400 401// Convert (x - floor(x)) to fract(x) 402def : Pat < 403 (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)), 404 (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))), 405 (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 406>; 407 408// Convert (x + (-floor(x))) to fract(x) 409def : Pat < 410 (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)), 411 (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))), 412 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE) 413>; 414 415} // End Predicates = [UnsafeFPMath] 416 417//===----------------------------------------------------------------------===// 418// VOP2 Patterns 419//===----------------------------------------------------------------------===// 420 421def : Pat < 422 (i32 (add (i32 (ctpop i32:$popcnt)), i32:$val)), 423 (V_BCNT_U32_B32_e64 $popcnt, $val) 424>; 425 426def : Pat < 427 (i32 (select i1:$src0, i32:$src1, i32:$src2)), 428 (V_CNDMASK_B32_e64 $src2, $src1, $src0) 429>; 430 431// Pattern for V_MAC_F32 432def : Pat < 433 (fmad (VOP3NoMods0 f32:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod), 434 (VOP3NoMods f32:$src1, i32:$src1_modifiers), 435 (VOP3NoMods f32:$src2, i32:$src2_modifiers)), 436 (V_MAC_F32_e64 $src0_modifiers, $src0, $src1_modifiers, $src1, 437 $src2_modifiers, $src2, $clamp, $omod) 438>; 439 440/********** ============================================ **********/ 441/********** Extraction, Insertion, Building and Casting **********/ 442/********** ============================================ **********/ 443 444foreach Index = 0-2 in { 445 def Extract_Element_v2i32_#Index : Extract_Element < 446 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 447 >; 448 def Insert_Element_v2i32_#Index : Insert_Element < 449 i32, v2i32, Index, !cast<SubRegIndex>(sub#Index) 450 >; 451 452 def Extract_Element_v2f32_#Index : Extract_Element < 453 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 454 >; 455 def Insert_Element_v2f32_#Index : Insert_Element < 456 f32, v2f32, Index, !cast<SubRegIndex>(sub#Index) 457 >; 458} 459 460foreach Index = 0-3 in { 461 def Extract_Element_v4i32_#Index : Extract_Element < 462 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 463 >; 464 def Insert_Element_v4i32_#Index : Insert_Element < 465 i32, v4i32, Index, !cast<SubRegIndex>(sub#Index) 466 >; 467 468 def Extract_Element_v4f32_#Index : Extract_Element < 469 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 470 >; 471 def Insert_Element_v4f32_#Index : Insert_Element < 472 f32, v4f32, Index, !cast<SubRegIndex>(sub#Index) 473 >; 474} 475 476foreach Index = 0-7 in { 477 def Extract_Element_v8i32_#Index : Extract_Element < 478 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 479 >; 480 def Insert_Element_v8i32_#Index : Insert_Element < 481 i32, v8i32, Index, !cast<SubRegIndex>(sub#Index) 482 >; 483 484 def Extract_Element_v8f32_#Index : Extract_Element < 485 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 486 >; 487 def Insert_Element_v8f32_#Index : Insert_Element < 488 f32, v8f32, Index, !cast<SubRegIndex>(sub#Index) 489 >; 490} 491 492foreach Index = 0-15 in { 493 def Extract_Element_v16i32_#Index : Extract_Element < 494 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 495 >; 496 def Insert_Element_v16i32_#Index : Insert_Element < 497 i32, v16i32, Index, !cast<SubRegIndex>(sub#Index) 498 >; 499 500 def Extract_Element_v16f32_#Index : Extract_Element < 501 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 502 >; 503 def Insert_Element_v16f32_#Index : Insert_Element < 504 f32, v16f32, Index, !cast<SubRegIndex>(sub#Index) 505 >; 506} 507 508// FIXME: Why do only some of these type combinations for SReg and 509// VReg? 510// 32-bit bitcast 511def : BitConvert <i32, f32, VGPR_32>; 512def : BitConvert <f32, i32, VGPR_32>; 513def : BitConvert <i32, f32, SReg_32>; 514def : BitConvert <f32, i32, SReg_32>; 515 516// 64-bit bitcast 517def : BitConvert <i64, f64, VReg_64>; 518def : BitConvert <f64, i64, VReg_64>; 519def : BitConvert <v2i32, v2f32, VReg_64>; 520def : BitConvert <v2f32, v2i32, VReg_64>; 521def : BitConvert <i64, v2i32, VReg_64>; 522def : BitConvert <v2i32, i64, VReg_64>; 523def : BitConvert <i64, v2f32, VReg_64>; 524def : BitConvert <v2f32, i64, VReg_64>; 525def : BitConvert <f64, v2f32, VReg_64>; 526def : BitConvert <v2f32, f64, VReg_64>; 527def : BitConvert <f64, v2i32, VReg_64>; 528def : BitConvert <v2i32, f64, VReg_64>; 529def : BitConvert <v4i32, v4f32, VReg_128>; 530def : BitConvert <v4f32, v4i32, VReg_128>; 531 532// 128-bit bitcast 533def : BitConvert <v2i64, v4i32, SReg_128>; 534def : BitConvert <v4i32, v2i64, SReg_128>; 535def : BitConvert <v2f64, v4f32, VReg_128>; 536def : BitConvert <v2f64, v4i32, VReg_128>; 537def : BitConvert <v4f32, v2f64, VReg_128>; 538def : BitConvert <v4i32, v2f64, VReg_128>; 539def : BitConvert <v2i64, v2f64, VReg_128>; 540def : BitConvert <v2f64, v2i64, VReg_128>; 541 542// 256-bit bitcast 543def : BitConvert <v8i32, v8f32, SReg_256>; 544def : BitConvert <v8f32, v8i32, SReg_256>; 545def : BitConvert <v8i32, v8f32, VReg_256>; 546def : BitConvert <v8f32, v8i32, VReg_256>; 547 548// 512-bit bitcast 549def : BitConvert <v16i32, v16f32, VReg_512>; 550def : BitConvert <v16f32, v16i32, VReg_512>; 551 552/********** =================== **********/ 553/********** Src & Dst modifiers **********/ 554/********** =================== **********/ 555 556def : Pat < 557 (AMDGPUclamp (VOP3Mods0Clamp f32:$src0, i32:$src0_modifiers, i32:$omod), 558 (f32 FP_ZERO), (f32 FP_ONE)), 559 (V_ADD_F32_e64 $src0_modifiers, $src0, 0, 0, 1, $omod) 560>; 561 562/********** ================================ **********/ 563/********** Floating point absolute/negative **********/ 564/********** ================================ **********/ 565 566// Prevent expanding both fneg and fabs. 567 568def : Pat < 569 (fneg (fabs f32:$src)), 570 (S_OR_B32 $src, (S_MOV_B32 0x80000000)) // Set sign bit 571>; 572 573// FIXME: Should use S_OR_B32 574def : Pat < 575 (fneg (fabs f64:$src)), 576 (REG_SEQUENCE VReg_64, 577 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 578 sub0, 579 (V_OR_B32_e32 (EXTRACT_SUBREG f64:$src, sub1), 580 (V_MOV_B32_e32 0x80000000)), // Set sign bit. 581 sub1) 582>; 583 584def : Pat < 585 (fabs f32:$src), 586 (V_AND_B32_e64 $src, (V_MOV_B32_e32 0x7fffffff)) 587>; 588 589def : Pat < 590 (fneg f32:$src), 591 (V_XOR_B32_e32 $src, (V_MOV_B32_e32 0x80000000)) 592>; 593 594def : Pat < 595 (fabs f64:$src), 596 (REG_SEQUENCE VReg_64, 597 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 598 sub0, 599 (V_AND_B32_e64 (EXTRACT_SUBREG f64:$src, sub1), 600 (V_MOV_B32_e32 0x7fffffff)), // Set sign bit. 601 sub1) 602>; 603 604def : Pat < 605 (fneg f64:$src), 606 (REG_SEQUENCE VReg_64, 607 (i32 (EXTRACT_SUBREG f64:$src, sub0)), 608 sub0, 609 (V_XOR_B32_e32 (EXTRACT_SUBREG f64:$src, sub1), 610 (V_MOV_B32_e32 0x80000000)), 611 sub1) 612>; 613 614/********** ================== **********/ 615/********** Immediate Patterns **********/ 616/********** ================== **********/ 617 618def : Pat < 619 (SGPRImm<(i32 imm)>:$imm), 620 (S_MOV_B32 imm:$imm) 621>; 622 623def : Pat < 624 (SGPRImm<(f32 fpimm)>:$imm), 625 (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm))) 626>; 627 628def : Pat < 629 (i32 imm:$imm), 630 (V_MOV_B32_e32 imm:$imm) 631>; 632 633def : Pat < 634 (f32 fpimm:$imm), 635 (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm))) 636>; 637 638def : Pat < 639 (i32 frameindex:$fi), 640 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi))) 641>; 642 643def : Pat < 644 (i64 InlineImm<i64>:$imm), 645 (S_MOV_B64 InlineImm<i64>:$imm) 646>; 647 648// XXX - Should this use a s_cmp to set SCC? 649 650// Set to sign-extended 64-bit value (true = -1, false = 0) 651def : Pat < 652 (i1 imm:$imm), 653 (S_MOV_B64 (i64 (as_i64imm $imm))) 654>; 655 656def : Pat < 657 (f64 InlineFPImm<f64>:$imm), 658 (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineFPImm<f64>:$imm))) 659>; 660 661/********** ================== **********/ 662/********** Intrinsic Patterns **********/ 663/********** ================== **********/ 664 665def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>; 666 667def : Pat < 668 (int_AMDGPU_cube v4f32:$src), 669 (REG_SEQUENCE VReg_128, 670 (V_CUBETC_F32 0 /* src0_modifiers */, (EXTRACT_SUBREG $src, sub0), 671 0 /* src1_modifiers */, (EXTRACT_SUBREG $src, sub1), 672 0 /* src2_modifiers */, (EXTRACT_SUBREG $src, sub2), 673 0 /* clamp */, 0 /* omod */), sub0, 674 (V_CUBESC_F32 0 /* src0_modifiers */, (EXTRACT_SUBREG $src, sub0), 675 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub1), 676 0 /* src2_modifiers */,(EXTRACT_SUBREG $src, sub2), 677 0 /* clamp */, 0 /* omod */), sub1, 678 (V_CUBEMA_F32 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub0), 679 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub1), 680 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub2), 681 0 /* clamp */, 0 /* omod */), sub2, 682 (V_CUBEID_F32 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub0), 683 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub1), 684 0 /* src1_modifiers */,(EXTRACT_SUBREG $src, sub2), 685 0 /* clamp */, 0 /* omod */), sub3) 686>; 687 688def : Pat < 689 (i32 (sext i1:$src0)), 690 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src0) 691>; 692 693class Ext32Pat <SDNode ext> : Pat < 694 (i32 (ext i1:$src0)), 695 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src0) 696>; 697 698def : Ext32Pat <zext>; 699def : Ext32Pat <anyext>; 700 701// The multiplication scales from [0,1] to the unsigned integer range 702def : Pat < 703 (AMDGPUurecip i32:$src0), 704 (V_CVT_U32_F32_e32 705 (V_MUL_F32_e32 CONST.FP_UINT_MAX_PLUS_1, 706 (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0)))) 707>; 708 709//===----------------------------------------------------------------------===// 710// VOP3 Patterns 711//===----------------------------------------------------------------------===// 712 713def : IMad24Pat<V_MAD_I32_I24>; 714def : UMad24Pat<V_MAD_U32_U24>; 715 716defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>; 717def : ROTRPattern <V_ALIGNBIT_B32>; 718 719/********** ====================== **********/ 720/********** Indirect adressing **********/ 721/********** ====================== **********/ 722 723multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> { 724 // Extract with offset 725 def : Pat< 726 (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))), 727 (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset) 728 >; 729 730 // Insert with offset 731 def : Pat< 732 (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))), 733 (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val) 734 >; 735} 736 737defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">; 738defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">; 739defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">; 740defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">; 741 742defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">; 743defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">; 744defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">; 745defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">; 746 747//===----------------------------------------------------------------------===// 748// SAD Patterns 749//===----------------------------------------------------------------------===// 750 751def : Pat < 752 (add (sub_oneuse (umax i32:$src0, i32:$src1), 753 (umin i32:$src0, i32:$src1)), 754 i32:$src2), 755 (V_SAD_U32 $src0, $src1, $src2) 756>; 757 758def : Pat < 759 (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)), 760 (sub i32:$src0, i32:$src1), 761 (sub i32:$src1, i32:$src0)), 762 i32:$src2), 763 (V_SAD_U32 $src0, $src1, $src2) 764>; 765 766//===----------------------------------------------------------------------===// 767// Conversion Patterns 768//===----------------------------------------------------------------------===// 769 770def : Pat<(i32 (sext_inreg i32:$src, i1)), 771 (S_BFE_I32 i32:$src, 65536)>; // 0 | 1 << 16 772 773// Handle sext_inreg in i64 774def : Pat < 775 (i64 (sext_inreg i64:$src, i1)), 776 (S_BFE_I64 i64:$src, 0x10000) // 0 | 1 << 16 777>; 778 779def : Pat < 780 (i64 (sext_inreg i64:$src, i8)), 781 (S_BFE_I64 i64:$src, 0x80000) // 0 | 8 << 16 782>; 783 784def : Pat < 785 (i64 (sext_inreg i64:$src, i16)), 786 (S_BFE_I64 i64:$src, 0x100000) // 0 | 16 << 16 787>; 788 789def : Pat < 790 (i64 (sext_inreg i64:$src, i32)), 791 (S_BFE_I64 i64:$src, 0x200000) // 0 | 32 << 16 792>; 793 794def : Pat < 795 (i64 (zext i32:$src)), 796 (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 0), sub1) 797>; 798 799def : Pat < 800 (i64 (anyext i32:$src)), 801 (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1) 802>; 803 804class ZExt_i64_i1_Pat <SDNode ext> : Pat < 805 (i64 (ext i1:$src)), 806 (REG_SEQUENCE VReg_64, 807 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src), sub0, 808 (S_MOV_B32 0), sub1) 809>; 810 811 812def : ZExt_i64_i1_Pat<zext>; 813def : ZExt_i64_i1_Pat<anyext>; 814 815// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that 816// REG_SEQUENCE patterns don't support instructions with multiple outputs. 817def : Pat < 818 (i64 (sext i32:$src)), 819 (REG_SEQUENCE SReg_64, $src, sub0, 820 (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, 31), SReg_32_XM0)), sub1) 821>; 822 823def : Pat < 824 (i64 (sext i1:$src)), 825 (REG_SEQUENCE VReg_64, 826 (V_CNDMASK_B32_e64 0, -1, $src), sub0, 827 (V_CNDMASK_B32_e64 0, -1, $src), sub1) 828>; 829 830class FPToI1Pat<Instruction Inst, int KOne, ValueType vt, SDPatternOperator fp_to_int> : Pat < 831 (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))), 832 (i1 (Inst 0, KOne, $src0_modifiers, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)) 833>; 834 835def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, f32, fp_to_uint>; 836def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, f32, fp_to_sint>; 837def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, f64, fp_to_uint>; 838def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, f64, fp_to_sint>; 839 840// If we need to perform a logical operation on i1 values, we need to 841// use vector comparisons since there is only one SCC register. Vector 842// comparisions still write to a pair of SGPRs, so treat these as 843// 64-bit comparisons. When legalizing SGPR copies, instructions 844// resulting in the copies from SCC to these instructions will be 845// moved to the VALU. 846def : Pat < 847 (i1 (and i1:$src0, i1:$src1)), 848 (S_AND_B64 $src0, $src1) 849>; 850 851def : Pat < 852 (i1 (or i1:$src0, i1:$src1)), 853 (S_OR_B64 $src0, $src1) 854>; 855 856def : Pat < 857 (i1 (xor i1:$src0, i1:$src1)), 858 (S_XOR_B64 $src0, $src1) 859>; 860 861def : Pat < 862 (f32 (sint_to_fp i1:$src)), 863 (V_CNDMASK_B32_e64 (i32 0), CONST.FP32_NEG_ONE, $src) 864>; 865 866def : Pat < 867 (f32 (uint_to_fp i1:$src)), 868 (V_CNDMASK_B32_e64 (i32 0), CONST.FP32_ONE, $src) 869>; 870 871def : Pat < 872 (f64 (sint_to_fp i1:$src)), 873 (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src)) 874>; 875 876def : Pat < 877 (f64 (uint_to_fp i1:$src)), 878 (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src)) 879>; 880 881//===----------------------------------------------------------------------===// 882// Miscellaneous Patterns 883//===----------------------------------------------------------------------===// 884 885def : Pat < 886 (i32 (trunc i64:$a)), 887 (EXTRACT_SUBREG $a, sub0) 888>; 889 890def : Pat < 891 (i1 (trunc i32:$a)), 892 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), 1) 893>; 894 895def : Pat < 896 (i1 (trunc i64:$a)), 897 (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), 898 (EXTRACT_SUBREG $a, sub0)), 1) 899>; 900 901def : Pat < 902 (i32 (bswap i32:$a)), 903 (V_BFI_B32 (S_MOV_B32 0x00ff00ff), 904 (V_ALIGNBIT_B32 $a, $a, 24), 905 (V_ALIGNBIT_B32 $a, $a, 8)) 906>; 907 908def : Pat < 909 (f32 (select i1:$src2, f32:$src1, f32:$src0)), 910 (V_CNDMASK_B32_e64 $src0, $src1, $src2) 911>; 912 913multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> { 914 def : Pat < 915 (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)), 916 (BFM $a, $b) 917 >; 918 919 def : Pat < 920 (vt (add (vt (shl 1, vt:$a)), -1)), 921 (BFM $a, (MOV 0)) 922 >; 923} 924 925defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>; 926// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>; 927 928def : BFEPattern <V_BFE_U32, S_MOV_B32>; 929 930def : Pat< 931 (fcanonicalize f32:$src), 932 (V_MUL_F32_e64 0, CONST.FP32_ONE, 0, $src, 0, 0) 933>; 934 935def : Pat< 936 (fcanonicalize f64:$src), 937 (V_MUL_F64 0, CONST.FP64_ONE, 0, $src, 0, 0) 938>; 939 940//===----------------------------------------------------------------------===// 941// Fract Patterns 942//===----------------------------------------------------------------------===// 943 944let Predicates = [isSI] in { 945 946// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is 947// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient 948// way to implement it is using V_FRACT_F64. 949// The workaround for the V_FRACT bug is: 950// fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999) 951 952// Convert floor(x) to (x - fract(x)) 953def : Pat < 954 (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))), 955 (V_ADD_F64 956 $mods, 957 $x, 958 SRCMODS.NEG, 959 (V_CNDMASK_B64_PSEUDO 960 (V_MIN_F64 961 SRCMODS.NONE, 962 (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE), 963 SRCMODS.NONE, 964 (V_MOV_B64_PSEUDO 0x3fefffffffffffff), 965 DSTCLAMP.NONE, DSTOMOD.NONE), 966 $x, 967 (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, 3/*NaN*/)), 968 DSTCLAMP.NONE, DSTOMOD.NONE) 969>; 970 971} // End Predicates = [isSI] 972 973//============================================================================// 974// Miscellaneous Optimization Patterns 975//============================================================================// 976 977def : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64>; 978 979def : IntMed3Pat<V_MED3_I32, smax, smax_oneuse, smin_oneuse>; 980def : IntMed3Pat<V_MED3_U32, umax, umax_oneuse, umin_oneuse>; 981 982//============================================================================// 983// Assembler aliases 984//============================================================================// 985 986def : MnemonicAlias<"v_add_u32", "v_add_i32">; 987def : MnemonicAlias<"v_sub_u32", "v_sub_i32">; 988def : MnemonicAlias<"v_subrev_u32", "v_subrev_i32">; 989 990} // End isGCN predicate 991