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