1//===-- AMDGPUInstructions.td - Common instruction defs ---*- tablegen -*-===// 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// 10// This file contains instruction defs that are common to all hw codegen 11// targets. 12// 13//===----------------------------------------------------------------------===// 14 15class AMDGPUInst <dag outs, dag ins, string asm = "", 16 list<dag> pattern = []> : Instruction { 17 field bit isRegisterLoad = 0; 18 field bit isRegisterStore = 0; 19 20 let Namespace = "AMDGPU"; 21 let OutOperandList = outs; 22 let InOperandList = ins; 23 let AsmString = asm; 24 let Pattern = pattern; 25 let Itinerary = NullALU; 26 27 // SoftFail is a field the disassembler can use to provide a way for 28 // instructions to not match without killing the whole decode process. It is 29 // mainly used for ARM, but Tablegen expects this field to exist or it fails 30 // to build the decode table. 31 field bits<64> SoftFail = 0; 32 33 let DecoderNamespace = Namespace; 34 35 let TSFlags{63} = isRegisterLoad; 36 let TSFlags{62} = isRegisterStore; 37} 38 39class AMDGPUShaderInst <dag outs, dag ins, string asm = "", 40 list<dag> pattern = []> : AMDGPUInst<outs, ins, asm, pattern> { 41 42 field bits<32> Inst = 0xffffffff; 43} 44 45def FP16Denormals : Predicate<"Subtarget.hasFP16Denormals()">; 46def FP32Denormals : Predicate<"Subtarget.hasFP32Denormals()">; 47def FP64Denormals : Predicate<"Subtarget.hasFP64Denormals()">; 48def UnsafeFPMath : Predicate<"TM.Options.UnsafeFPMath">; 49 50def InstFlag : OperandWithDefaultOps <i32, (ops (i32 0))>; 51def ADDRIndirect : ComplexPattern<iPTR, 2, "SelectADDRIndirect", [], []>; 52 53def u16ImmTarget : AsmOperandClass { 54 let Name = "U16Imm"; 55 let RenderMethod = "addImmOperands"; 56} 57 58def s16ImmTarget : AsmOperandClass { 59 let Name = "S16Imm"; 60 let RenderMethod = "addImmOperands"; 61} 62 63let OperandType = "OPERAND_IMMEDIATE" in { 64 65def u32imm : Operand<i32> { 66 let PrintMethod = "printU32ImmOperand"; 67} 68 69def u16imm : Operand<i16> { 70 let PrintMethod = "printU16ImmOperand"; 71 let ParserMatchClass = u16ImmTarget; 72} 73 74def s16imm : Operand<i16> { 75 let PrintMethod = "printU16ImmOperand"; 76 let ParserMatchClass = s16ImmTarget; 77} 78 79def u8imm : Operand<i8> { 80 let PrintMethod = "printU8ImmOperand"; 81} 82 83} // End OperandType = "OPERAND_IMMEDIATE" 84 85//===--------------------------------------------------------------------===// 86// Custom Operands 87//===--------------------------------------------------------------------===// 88def brtarget : Operand<OtherVT>; 89 90//===----------------------------------------------------------------------===// 91// Misc. PatFrags 92//===----------------------------------------------------------------------===// 93 94class HasOneUseUnaryOp<SDPatternOperator op> : PatFrag< 95 (ops node:$src0), 96 (op $src0), 97 [{ return N->hasOneUse(); }] 98>; 99 100class HasOneUseBinOp<SDPatternOperator op> : PatFrag< 101 (ops node:$src0, node:$src1), 102 (op $src0, $src1), 103 [{ return N->hasOneUse(); }] 104>; 105 106class HasOneUseTernaryOp<SDPatternOperator op> : PatFrag< 107 (ops node:$src0, node:$src1, node:$src2), 108 (op $src0, $src1, $src2), 109 [{ return N->hasOneUse(); }] 110>; 111 112def trunc_oneuse : HasOneUseUnaryOp<trunc>; 113 114let Properties = [SDNPCommutative, SDNPAssociative] in { 115def smax_oneuse : HasOneUseBinOp<smax>; 116def smin_oneuse : HasOneUseBinOp<smin>; 117def umax_oneuse : HasOneUseBinOp<umax>; 118def umin_oneuse : HasOneUseBinOp<umin>; 119def fminnum_oneuse : HasOneUseBinOp<fminnum>; 120def fmaxnum_oneuse : HasOneUseBinOp<fmaxnum>; 121def and_oneuse : HasOneUseBinOp<and>; 122def or_oneuse : HasOneUseBinOp<or>; 123def xor_oneuse : HasOneUseBinOp<xor>; 124} // Properties = [SDNPCommutative, SDNPAssociative] 125 126def sub_oneuse : HasOneUseBinOp<sub>; 127 128def srl_oneuse : HasOneUseBinOp<srl>; 129def shl_oneuse : HasOneUseBinOp<shl>; 130 131def select_oneuse : HasOneUseTernaryOp<select>; 132 133//===----------------------------------------------------------------------===// 134// PatLeafs for floating-point comparisons 135//===----------------------------------------------------------------------===// 136 137def COND_OEQ : PatLeaf < 138 (cond), 139 [{return N->get() == ISD::SETOEQ || N->get() == ISD::SETEQ;}] 140>; 141 142def COND_ONE : PatLeaf < 143 (cond), 144 [{return N->get() == ISD::SETONE || N->get() == ISD::SETNE;}] 145>; 146 147def COND_OGT : PatLeaf < 148 (cond), 149 [{return N->get() == ISD::SETOGT || N->get() == ISD::SETGT;}] 150>; 151 152def COND_OGE : PatLeaf < 153 (cond), 154 [{return N->get() == ISD::SETOGE || N->get() == ISD::SETGE;}] 155>; 156 157def COND_OLT : PatLeaf < 158 (cond), 159 [{return N->get() == ISD::SETOLT || N->get() == ISD::SETLT;}] 160>; 161 162def COND_OLE : PatLeaf < 163 (cond), 164 [{return N->get() == ISD::SETOLE || N->get() == ISD::SETLE;}] 165>; 166 167 168def COND_O : PatLeaf <(cond), [{return N->get() == ISD::SETO;}]>; 169def COND_UO : PatLeaf <(cond), [{return N->get() == ISD::SETUO;}]>; 170 171//===----------------------------------------------------------------------===// 172// PatLeafs for unsigned / unordered comparisons 173//===----------------------------------------------------------------------===// 174 175def COND_UEQ : PatLeaf <(cond), [{return N->get() == ISD::SETUEQ;}]>; 176def COND_UNE : PatLeaf <(cond), [{return N->get() == ISD::SETUNE;}]>; 177def COND_UGT : PatLeaf <(cond), [{return N->get() == ISD::SETUGT;}]>; 178def COND_UGE : PatLeaf <(cond), [{return N->get() == ISD::SETUGE;}]>; 179def COND_ULT : PatLeaf <(cond), [{return N->get() == ISD::SETULT;}]>; 180def COND_ULE : PatLeaf <(cond), [{return N->get() == ISD::SETULE;}]>; 181 182// XXX - For some reason R600 version is preferring to use unordered 183// for setne? 184def COND_UNE_NE : PatLeaf < 185 (cond), 186 [{return N->get() == ISD::SETUNE || N->get() == ISD::SETNE;}] 187>; 188 189//===----------------------------------------------------------------------===// 190// PatLeafs for signed comparisons 191//===----------------------------------------------------------------------===// 192 193def COND_SGT : PatLeaf <(cond), [{return N->get() == ISD::SETGT;}]>; 194def COND_SGE : PatLeaf <(cond), [{return N->get() == ISD::SETGE;}]>; 195def COND_SLT : PatLeaf <(cond), [{return N->get() == ISD::SETLT;}]>; 196def COND_SLE : PatLeaf <(cond), [{return N->get() == ISD::SETLE;}]>; 197 198//===----------------------------------------------------------------------===// 199// PatLeafs for integer equality 200//===----------------------------------------------------------------------===// 201 202def COND_EQ : PatLeaf < 203 (cond), 204 [{return N->get() == ISD::SETEQ || N->get() == ISD::SETUEQ;}] 205>; 206 207def COND_NE : PatLeaf < 208 (cond), 209 [{return N->get() == ISD::SETNE || N->get() == ISD::SETUNE;}] 210>; 211 212def COND_NULL : PatLeaf < 213 (cond), 214 [{(void)N; return false;}] 215>; 216 217 218//===----------------------------------------------------------------------===// 219// Load/Store Pattern Fragments 220//===----------------------------------------------------------------------===// 221 222class PrivateMemOp <dag ops, dag frag> : PatFrag <ops, frag, [{ 223 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.PRIVATE_ADDRESS; 224}]>; 225 226class PrivateLoad <SDPatternOperator op> : PrivateMemOp < 227 (ops node:$ptr), (op node:$ptr) 228>; 229 230class PrivateStore <SDPatternOperator op> : PrivateMemOp < 231 (ops node:$value, node:$ptr), (op node:$value, node:$ptr) 232>; 233 234def load_private : PrivateLoad <load>; 235 236def truncstorei8_private : PrivateStore <truncstorei8>; 237def truncstorei16_private : PrivateStore <truncstorei16>; 238def store_private : PrivateStore <store>; 239 240class GlobalMemOp <dag ops, dag frag> : PatFrag <ops, frag, [{ 241 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS; 242}]>; 243 244// Global address space loads 245class GlobalLoad <SDPatternOperator op> : GlobalMemOp < 246 (ops node:$ptr), (op node:$ptr) 247>; 248 249def global_load : GlobalLoad <load>; 250 251// Global address space stores 252class GlobalStore <SDPatternOperator op> : GlobalMemOp < 253 (ops node:$value, node:$ptr), (op node:$value, node:$ptr) 254>; 255 256def global_store : GlobalStore <store>; 257def global_store_atomic : GlobalStore<atomic_store>; 258 259 260class ConstantMemOp <dag ops, dag frag> : PatFrag <ops, frag, [{ 261 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.CONSTANT_ADDRESS; 262}]>; 263 264// Constant address space loads 265class ConstantLoad <SDPatternOperator op> : ConstantMemOp < 266 (ops node:$ptr), (op node:$ptr) 267>; 268 269def constant_load : ConstantLoad<load>; 270 271class LocalMemOp <dag ops, dag frag> : PatFrag <ops, frag, [{ 272 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS; 273}]>; 274 275// Local address space loads 276class LocalLoad <SDPatternOperator op> : LocalMemOp < 277 (ops node:$ptr), (op node:$ptr) 278>; 279 280class LocalStore <SDPatternOperator op> : LocalMemOp < 281 (ops node:$value, node:$ptr), (op node:$value, node:$ptr) 282>; 283 284class FlatMemOp <dag ops, dag frag> : PatFrag <ops, frag, [{ 285 return cast<MemSDNode>(N)->getAddressSPace() == AMDGPUASI.FLAT_ADDRESS; 286}]>; 287 288class FlatLoad <SDPatternOperator op> : FlatMemOp < 289 (ops node:$ptr), (op node:$ptr) 290>; 291 292class AZExtLoadBase <SDPatternOperator ld_node>: PatFrag<(ops node:$ptr), 293 (ld_node node:$ptr), [{ 294 LoadSDNode *L = cast<LoadSDNode>(N); 295 return L->getExtensionType() == ISD::ZEXTLOAD || 296 L->getExtensionType() == ISD::EXTLOAD; 297}]>; 298 299def az_extload : AZExtLoadBase <unindexedload>; 300 301def az_extloadi8 : PatFrag<(ops node:$ptr), (az_extload node:$ptr), [{ 302 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8; 303}]>; 304 305def az_extloadi8_global : GlobalLoad <az_extloadi8>; 306def sextloadi8_global : GlobalLoad <sextloadi8>; 307 308def az_extloadi8_constant : ConstantLoad <az_extloadi8>; 309def sextloadi8_constant : ConstantLoad <sextloadi8>; 310 311def az_extloadi8_local : LocalLoad <az_extloadi8>; 312def sextloadi8_local : LocalLoad <sextloadi8>; 313 314def extloadi8_private : PrivateLoad <az_extloadi8>; 315def sextloadi8_private : PrivateLoad <sextloadi8>; 316 317def az_extloadi16 : PatFrag<(ops node:$ptr), (az_extload node:$ptr), [{ 318 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16; 319}]>; 320 321def az_extloadi16_global : GlobalLoad <az_extloadi16>; 322def sextloadi16_global : GlobalLoad <sextloadi16>; 323 324def az_extloadi16_constant : ConstantLoad <az_extloadi16>; 325def sextloadi16_constant : ConstantLoad <sextloadi16>; 326 327def az_extloadi16_local : LocalLoad <az_extloadi16>; 328def sextloadi16_local : LocalLoad <sextloadi16>; 329 330def extloadi16_private : PrivateLoad <az_extloadi16>; 331def sextloadi16_private : PrivateLoad <sextloadi16>; 332 333def az_extloadi32 : PatFrag<(ops node:$ptr), (az_extload node:$ptr), [{ 334 return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i32; 335}]>; 336 337def az_extloadi32_global : GlobalLoad <az_extloadi32>; 338 339def az_extloadi32_flat : FlatLoad <az_extloadi32>; 340 341def az_extloadi32_constant : ConstantLoad <az_extloadi32>; 342 343def truncstorei8_global : GlobalStore <truncstorei8>; 344def truncstorei16_global : GlobalStore <truncstorei16>; 345 346def local_store : LocalStore <store>; 347def truncstorei8_local : LocalStore <truncstorei8>; 348def truncstorei16_local : LocalStore <truncstorei16>; 349 350def local_load : LocalLoad <load>; 351 352class Aligned8Bytes <dag ops, dag frag> : PatFrag <ops, frag, [{ 353 return cast<MemSDNode>(N)->getAlignment() % 8 == 0; 354}]>; 355 356def local_load_aligned8bytes : Aligned8Bytes < 357 (ops node:$ptr), (local_load node:$ptr) 358>; 359 360def local_store_aligned8bytes : Aligned8Bytes < 361 (ops node:$val, node:$ptr), (local_store node:$val, node:$ptr) 362>; 363 364class local_binary_atomic_op<SDNode atomic_op> : 365 PatFrag<(ops node:$ptr, node:$value), 366 (atomic_op node:$ptr, node:$value), [{ 367 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS; 368}]>; 369 370 371def atomic_swap_local : local_binary_atomic_op<atomic_swap>; 372def atomic_load_add_local : local_binary_atomic_op<atomic_load_add>; 373def atomic_load_sub_local : local_binary_atomic_op<atomic_load_sub>; 374def atomic_load_and_local : local_binary_atomic_op<atomic_load_and>; 375def atomic_load_or_local : local_binary_atomic_op<atomic_load_or>; 376def atomic_load_xor_local : local_binary_atomic_op<atomic_load_xor>; 377def atomic_load_nand_local : local_binary_atomic_op<atomic_load_nand>; 378def atomic_load_min_local : local_binary_atomic_op<atomic_load_min>; 379def atomic_load_max_local : local_binary_atomic_op<atomic_load_max>; 380def atomic_load_umin_local : local_binary_atomic_op<atomic_load_umin>; 381def atomic_load_umax_local : local_binary_atomic_op<atomic_load_umax>; 382 383def mskor_global : PatFrag<(ops node:$val, node:$ptr), 384 (AMDGPUstore_mskor node:$val, node:$ptr), [{ 385 return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS; 386}]>; 387 388multiclass AtomicCmpSwapLocal <SDNode cmp_swap_node> { 389 390 def _32_local : PatFrag < 391 (ops node:$ptr, node:$cmp, node:$swap), 392 (cmp_swap_node node:$ptr, node:$cmp, node:$swap), [{ 393 AtomicSDNode *AN = cast<AtomicSDNode>(N); 394 return AN->getMemoryVT() == MVT::i32 && 395 AN->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS; 396 }]>; 397 398 def _64_local : PatFrag< 399 (ops node:$ptr, node:$cmp, node:$swap), 400 (cmp_swap_node node:$ptr, node:$cmp, node:$swap), [{ 401 AtomicSDNode *AN = cast<AtomicSDNode>(N); 402 return AN->getMemoryVT() == MVT::i64 && 403 AN->getAddressSpace() == AMDGPUASI.LOCAL_ADDRESS; 404 }]>; 405} 406 407defm atomic_cmp_swap : AtomicCmpSwapLocal <atomic_cmp_swap>; 408 409multiclass global_binary_atomic_op<SDNode atomic_op> { 410 def "" : PatFrag< 411 (ops node:$ptr, node:$value), 412 (atomic_op node:$ptr, node:$value), 413 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS;}]>; 414 415 def _noret : PatFrag< 416 (ops node:$ptr, node:$value), 417 (atomic_op node:$ptr, node:$value), 418 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS && (SDValue(N, 0).use_empty());}]>; 419 420 def _ret : PatFrag< 421 (ops node:$ptr, node:$value), 422 (atomic_op node:$ptr, node:$value), 423 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS && (!SDValue(N, 0).use_empty());}]>; 424} 425 426defm atomic_swap_global : global_binary_atomic_op<atomic_swap>; 427defm atomic_add_global : global_binary_atomic_op<atomic_load_add>; 428defm atomic_and_global : global_binary_atomic_op<atomic_load_and>; 429defm atomic_max_global : global_binary_atomic_op<atomic_load_max>; 430defm atomic_min_global : global_binary_atomic_op<atomic_load_min>; 431defm atomic_or_global : global_binary_atomic_op<atomic_load_or>; 432defm atomic_sub_global : global_binary_atomic_op<atomic_load_sub>; 433defm atomic_umax_global : global_binary_atomic_op<atomic_load_umax>; 434defm atomic_umin_global : global_binary_atomic_op<atomic_load_umin>; 435defm atomic_xor_global : global_binary_atomic_op<atomic_load_xor>; 436 437//legacy 438def AMDGPUatomic_cmp_swap_global : PatFrag< 439 (ops node:$ptr, node:$value), 440 (AMDGPUatomic_cmp_swap node:$ptr, node:$value), 441 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS;}]>; 442 443def atomic_cmp_swap_global : PatFrag< 444 (ops node:$ptr, node:$cmp, node:$value), 445 (atomic_cmp_swap node:$ptr, node:$cmp, node:$value), 446 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS;}]>; 447 448def atomic_cmp_swap_global_noret : PatFrag< 449 (ops node:$ptr, node:$cmp, node:$value), 450 (atomic_cmp_swap node:$ptr, node:$cmp, node:$value), 451 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS && (SDValue(N, 0).use_empty());}]>; 452 453def atomic_cmp_swap_global_ret : PatFrag< 454 (ops node:$ptr, node:$cmp, node:$value), 455 (atomic_cmp_swap node:$ptr, node:$cmp, node:$value), 456 [{return cast<MemSDNode>(N)->getAddressSpace() == AMDGPUASI.GLOBAL_ADDRESS && (!SDValue(N, 0).use_empty());}]>; 457 458//===----------------------------------------------------------------------===// 459// Misc Pattern Fragments 460//===----------------------------------------------------------------------===// 461 462class Constants { 463int TWO_PI = 0x40c90fdb; 464int PI = 0x40490fdb; 465int TWO_PI_INV = 0x3e22f983; 466int FP_UINT_MAX_PLUS_1 = 0x4f800000; // 1 << 32 in floating point encoding 467int FP16_ONE = 0x3C00; 468int V2FP16_ONE = 0x3C003C00; 469int FP32_ONE = 0x3f800000; 470int FP32_NEG_ONE = 0xbf800000; 471int FP64_ONE = 0x3ff0000000000000; 472int FP64_NEG_ONE = 0xbff0000000000000; 473} 474def CONST : Constants; 475 476def FP_ZERO : PatLeaf < 477 (fpimm), 478 [{return N->getValueAPF().isZero();}] 479>; 480 481def FP_ONE : PatLeaf < 482 (fpimm), 483 [{return N->isExactlyValue(1.0);}] 484>; 485 486def FP_HALF : PatLeaf < 487 (fpimm), 488 [{return N->isExactlyValue(0.5);}] 489>; 490 491let isCodeGenOnly = 1, isPseudo = 1 in { 492 493let usesCustomInserter = 1 in { 494 495class CLAMP <RegisterClass rc> : AMDGPUShaderInst < 496 (outs rc:$dst), 497 (ins rc:$src0), 498 "CLAMP $dst, $src0", 499 [(set f32:$dst, (AMDGPUclamp f32:$src0))] 500>; 501 502class FABS <RegisterClass rc> : AMDGPUShaderInst < 503 (outs rc:$dst), 504 (ins rc:$src0), 505 "FABS $dst, $src0", 506 [(set f32:$dst, (fabs f32:$src0))] 507>; 508 509class FNEG <RegisterClass rc> : AMDGPUShaderInst < 510 (outs rc:$dst), 511 (ins rc:$src0), 512 "FNEG $dst, $src0", 513 [(set f32:$dst, (fneg f32:$src0))] 514>; 515 516} // usesCustomInserter = 1 517 518multiclass RegisterLoadStore <RegisterClass dstClass, Operand addrClass, 519 ComplexPattern addrPat> { 520let UseNamedOperandTable = 1 in { 521 522 def RegisterLoad : AMDGPUShaderInst < 523 (outs dstClass:$dst), 524 (ins addrClass:$addr, i32imm:$chan), 525 "RegisterLoad $dst, $addr", 526 [(set i32:$dst, (AMDGPUregister_load addrPat:$addr, (i32 timm:$chan)))] 527 > { 528 let isRegisterLoad = 1; 529 } 530 531 def RegisterStore : AMDGPUShaderInst < 532 (outs), 533 (ins dstClass:$val, addrClass:$addr, i32imm:$chan), 534 "RegisterStore $val, $addr", 535 [(AMDGPUregister_store i32:$val, addrPat:$addr, (i32 timm:$chan))] 536 > { 537 let isRegisterStore = 1; 538 } 539} 540} 541 542} // End isCodeGenOnly = 1, isPseudo = 1 543 544/* Generic helper patterns for intrinsics */ 545/* -------------------------------------- */ 546 547class POW_Common <AMDGPUInst log_ieee, AMDGPUInst exp_ieee, AMDGPUInst mul> 548 : Pat < 549 (fpow f32:$src0, f32:$src1), 550 (exp_ieee (mul f32:$src1, (log_ieee f32:$src0))) 551>; 552 553/* Other helper patterns */ 554/* --------------------- */ 555 556/* Extract element pattern */ 557class Extract_Element <ValueType sub_type, ValueType vec_type, int sub_idx, 558 SubRegIndex sub_reg> 559 : Pat< 560 (sub_type (extractelt vec_type:$src, sub_idx)), 561 (EXTRACT_SUBREG $src, sub_reg) 562>; 563 564/* Insert element pattern */ 565class Insert_Element <ValueType elem_type, ValueType vec_type, 566 int sub_idx, SubRegIndex sub_reg> 567 : Pat < 568 (insertelt vec_type:$vec, elem_type:$elem, sub_idx), 569 (INSERT_SUBREG $vec, $elem, sub_reg) 570>; 571 572// XXX: Convert to new syntax and use COPY_TO_REG, once the DFAPacketizer 573// can handle COPY instructions. 574// bitconvert pattern 575class BitConvert <ValueType dt, ValueType st, RegisterClass rc> : Pat < 576 (dt (bitconvert (st rc:$src0))), 577 (dt rc:$src0) 578>; 579 580// XXX: Convert to new syntax and use COPY_TO_REG, once the DFAPacketizer 581// can handle COPY instructions. 582class DwordAddrPat<ValueType vt, RegisterClass rc> : Pat < 583 (vt (AMDGPUdwordaddr (vt rc:$addr))), 584 (vt rc:$addr) 585>; 586 587// BFI_INT patterns 588 589multiclass BFIPatterns <Instruction BFI_INT, 590 Instruction LoadImm32, 591 RegisterClass RC64> { 592 // Definition from ISA doc: 593 // (y & x) | (z & ~x) 594 def : Pat < 595 (or (and i32:$y, i32:$x), (and i32:$z, (not i32:$x))), 596 (BFI_INT $x, $y, $z) 597 >; 598 599 // SHA-256 Ch function 600 // z ^ (x & (y ^ z)) 601 def : Pat < 602 (xor i32:$z, (and i32:$x, (xor i32:$y, i32:$z))), 603 (BFI_INT $x, $y, $z) 604 >; 605 606 def : Pat < 607 (fcopysign f32:$src0, f32:$src1), 608 (BFI_INT (LoadImm32 (i32 0x7fffffff)), $src0, $src1) 609 >; 610 611 def : Pat < 612 (f32 (fcopysign f32:$src0, f64:$src1)), 613 (BFI_INT (LoadImm32 (i32 0x7fffffff)), $src0, 614 (i32 (EXTRACT_SUBREG $src1, sub1))) 615 >; 616 617 def : Pat < 618 (f64 (fcopysign f64:$src0, f64:$src1)), 619 (REG_SEQUENCE RC64, 620 (i32 (EXTRACT_SUBREG $src0, sub0)), sub0, 621 (BFI_INT (LoadImm32 (i32 0x7fffffff)), 622 (i32 (EXTRACT_SUBREG $src0, sub1)), 623 (i32 (EXTRACT_SUBREG $src1, sub1))), sub1) 624 >; 625 626 def : Pat < 627 (f64 (fcopysign f64:$src0, f32:$src1)), 628 (REG_SEQUENCE RC64, 629 (i32 (EXTRACT_SUBREG $src0, sub0)), sub0, 630 (BFI_INT (LoadImm32 (i32 0x7fffffff)), 631 (i32 (EXTRACT_SUBREG $src0, sub1)), 632 $src1), sub1) 633 >; 634} 635 636// SHA-256 Ma patterns 637 638// ((x & z) | (y & (x | z))) -> BFI_INT (XOR x, y), z, y 639class SHA256MaPattern <Instruction BFI_INT, Instruction XOR> : Pat < 640 (or (and i32:$x, i32:$z), (and i32:$y, (or i32:$x, i32:$z))), 641 (BFI_INT (XOR i32:$x, i32:$y), i32:$z, i32:$y) 642>; 643 644// Bitfield extract patterns 645 646def IMMZeroBasedBitfieldMask : PatLeaf <(imm), [{ 647 return isMask_32(N->getZExtValue()); 648}]>; 649 650def IMMPopCount : SDNodeXForm<imm, [{ 651 return CurDAG->getTargetConstant(countPopulation(N->getZExtValue()), SDLoc(N), 652 MVT::i32); 653}]>; 654 655multiclass BFEPattern <Instruction UBFE, Instruction SBFE, Instruction MOV> { 656 def : Pat < 657 (i32 (and (i32 (srl i32:$src, i32:$rshift)), IMMZeroBasedBitfieldMask:$mask)), 658 (UBFE $src, $rshift, (MOV (i32 (IMMPopCount $mask)))) 659 >; 660 661 def : Pat < 662 (srl (shl_oneuse i32:$src, (sub 32, i32:$width)), (sub 32, i32:$width)), 663 (UBFE $src, (i32 0), $width) 664 >; 665 666 def : Pat < 667 (sra (shl_oneuse i32:$src, (sub 32, i32:$width)), (sub 32, i32:$width)), 668 (SBFE $src, (i32 0), $width) 669 >; 670} 671 672// rotr pattern 673class ROTRPattern <Instruction BIT_ALIGN> : Pat < 674 (rotr i32:$src0, i32:$src1), 675 (BIT_ALIGN $src0, $src0, $src1) 676>; 677 678// This matches 16 permutations of 679// max(min(x, y), min(max(x, y), z)) 680class IntMed3Pat<Instruction med3Inst, 681 SDPatternOperator max, 682 SDPatternOperator max_oneuse, 683 SDPatternOperator min_oneuse, 684 ValueType vt = i32> : Pat< 685 (max (min_oneuse vt:$src0, vt:$src1), 686 (min_oneuse (max_oneuse vt:$src0, vt:$src1), vt:$src2)), 687 (med3Inst $src0, $src1, $src2) 688>; 689 690// Special conversion patterns 691 692def cvt_rpi_i32_f32 : PatFrag < 693 (ops node:$src), 694 (fp_to_sint (ffloor (fadd $src, FP_HALF))), 695 [{ (void) N; return TM.Options.NoNaNsFPMath; }] 696>; 697 698def cvt_flr_i32_f32 : PatFrag < 699 (ops node:$src), 700 (fp_to_sint (ffloor $src)), 701 [{ (void)N; return TM.Options.NoNaNsFPMath; }] 702>; 703 704class IMad24Pat<Instruction Inst> : Pat < 705 (add (AMDGPUmul_i24 i32:$src0, i32:$src1), i32:$src2), 706 (Inst $src0, $src1, $src2) 707>; 708 709class UMad24Pat<Instruction Inst> : Pat < 710 (add (AMDGPUmul_u24 i32:$src0, i32:$src1), i32:$src2), 711 (Inst $src0, $src1, $src2) 712>; 713 714class RcpPat<Instruction RcpInst, ValueType vt> : Pat < 715 (fdiv FP_ONE, vt:$src), 716 (RcpInst $src) 717>; 718 719class RsqPat<Instruction RsqInst, ValueType vt> : Pat < 720 (AMDGPUrcp (fsqrt vt:$src)), 721 (RsqInst $src) 722>; 723 724include "R600Instructions.td" 725include "R700Instructions.td" 726include "EvergreenInstructions.td" 727include "CaymanInstructions.td" 728 729include "SIInstrInfo.td" 730 731