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