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