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