34#include "llvm/IR/IntrinsicsNVPTX.h"
48#define DEBUG_TYPE "nvptx-isel"
49#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
53 cl::desc(
"Enable reciprocal sqrt optimization"));
60 cl::desc(
"Enable MAD wide optimization"));
65 NVPTXScopes() =
default;
72 LLVMContext *Context =
nullptr;
75struct NVPTXMemCacheHintAccess {
76 NVPTX::AddressSpace AddrSpace;
83 const NVPTXTargetMachine &TM;
85 NVPTX::DivPrecisionLevel getDivF32Level(
const SDNode *
N)
const;
86 bool usePrecSqrtF32(
const SDNode *
N)
const;
87 bool useF32FTZ()
const;
88 bool allowFMA()
const;
89 bool doRsqrtOpt()
const;
90 bool doMADWideOpt()
const;
95 NVPTXDAGToDAGISel() =
delete;
97 explicit NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
CodeGenOptLevel OptLevel);
99 bool runOnMachineFunction(MachineFunction &MF)
override;
100 const NVPTXSubtarget *Subtarget =
nullptr;
102 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
104 std::vector<SDValue> &OutOps)
override;
108#include "NVPTXGenDAGISel.inc"
110 void Select(SDNode *
N)
override;
111 bool tryIntrinsicChain(SDNode *
N);
112 bool tryIntrinsicVoid(SDNode *
N);
113 void SelectTexSurfHandle(SDNode *
N);
114 bool tryLoad(SDNode *
N);
115 bool tryLoadVector(SDNode *
N);
116 bool tryLDU(SDNode *
N);
117 bool tryLDG(MemSDNode *
N);
118 bool tryStore(SDNode *
N);
119 bool tryStoreVector(SDNode *
N);
120 bool tryFence(SDNode *
N);
121 bool tryBFE(SDNode *
N);
122 bool tryBF16ArithToFMA(SDNode *
N);
123 bool tryConstantFP(SDNode *
N);
124 bool SelectSETP_F16X2(SDNode *
N);
125 bool SelectSETP_BF16X2(SDNode *
N);
126 bool tryUNPACK_VECTOR(SDNode *
N);
127 bool tryEXTRACT_VECTOR_ELEMENT(SDNode *
N);
128 void SelectV2I64toI128(SDNode *
N);
129 void SelectI128toV2I64(SDNode *
N);
130 void SelectCpAsyncBulkTensorReduceCommon(SDNode *
N,
unsigned RedOp,
131 bool IsIm2Col =
false);
132 void SelectTcgen05Ld(SDNode *
N,
bool hasOffset =
false);
133 void SelectTcgen05St(SDNode *
N,
bool hasOffset =
false);
134 void selectAtomicSwap128(SDNode *
N);
136 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
137 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
139 NVPTX::Ordering getMemOrder(
const MemSDNode *
N)
const;
140 NVPTX::Scope getAtomicScope(
const MemSDNode *
N)
const;
143 SDValue getPTXCmpMode(
const CondCodeSDNode &CondCode);
151 std::pair<unsigned, SDValue>
152 getMemCacheHintOperands(
const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
159 std::pair<NVPTX::Ordering, NVPTX::Scope>
160 insertMemoryInstructionFence(SDLoc
DL,
SDValue &Chain, MemSDNode *
N);
161 NVPTX::Scope getOperationScope(MemSDNode *
N, NVPTX::Ordering O)
const;
164 static NVPTX::AddressSpace getAddrSpace(
const MemSDNode *
N);
170 explicit NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm,
180 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
186 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
188char NVPTXDAGToDAGISelLegacy::ID = 0;
203NVPTX::DivPrecisionLevel
204NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
208bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
212bool NVPTXDAGToDAGISel::useF32FTZ()
const {
216bool NVPTXDAGToDAGISel::allowFMA()
const {
221bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
223bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
227void NVPTXDAGToDAGISel::Select(SDNode *
N) {
229 if (
N->isMachineOpcode()) {
234 switch (
N->getOpcode()) {
254 if (tryEXTRACT_VECTOR_ELEMENT(
N))
261 SelectSETP_BF16X2(
N);
266 if (tryLoadVector(
N))
277 if (tryStoreVector(
N))
281 if (tryIntrinsicChain(
N))
285 if (tryIntrinsicVoid(
N))
296 if (
N->getOperand(1).getValueType() == MVT::i128) {
297 SelectV2I64toI128(
N);
303 if (
N->getOperand(1).getValueType() == MVT::i128) {
304 SelectI128toV2I64(
N);
311 selectAtomicSwap128(
N);
316 if (tryBF16ArithToFMA(
N))
325#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
326 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
327 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
331 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
333 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
335 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
337 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
339 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
341 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
343 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
345 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
347 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
349 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
351 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
353 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
355 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
357 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
359 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
361 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
363 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
365 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
367 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
369 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
371 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
373 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
375 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
377 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
379 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
381 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
383 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
385 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
387 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
389 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
391 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
393 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
395 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
397 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
399 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
401 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
403 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
409void NVPTXDAGToDAGISel::SelectTcgen05Ld(SDNode *
N,
bool hasOffset) {
412 "tcgen05.ld is not supported on this architecture variant");
419 auto OffsetNode = CurDAG->getTargetConstant(
421 ReplaceNode(
N, CurDAG->getMachineNode(
423 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
426 ReplaceNode(
N, CurDAG->getMachineNode(
428 {N->getOperand(2), N->getOperand(0)}));
432bool NVPTXDAGToDAGISel::tryIntrinsicChain(SDNode *
N) {
433 unsigned IID =
N->getConstantOperandVal(1);
437 case Intrinsic::nvvm_ldu_global_f:
438 case Intrinsic::nvvm_ldu_global_i:
439 case Intrinsic::nvvm_ldu_global_p:
442 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
443 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
444 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
445 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
446 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
447 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
448 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
449 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
450 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
451 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
452 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
453 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
454 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
455 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
456 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
457 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
458 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
459 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
460 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
461 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
462 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
463 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
464 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
465 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
466 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
467 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
468 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
469 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
470 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
475 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
476 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
477 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
478 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
479 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
480 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
481 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
482 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
483 SelectTcgen05Ld(
N,
true);
491SDValue NVPTXDAGToDAGISel::getPTXCmpMode(
const CondCodeSDNode &CondCode) {
518 return CmpMode::NotANumber;
533 return CurDAG->getTargetConstant(PTXCmpMode, SDLoc(), MVT::i32);
536bool NVPTXDAGToDAGISel::SelectSETP_F16X2(SDNode *
N) {
539 SDNode *SetP = CurDAG->getMachineNode(
540 NVPTX::SETP_f16x2rr,
DL, MVT::i1, MVT::i1,
541 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
542 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
543 ReplaceNode(
N, SetP);
547bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(SDNode *
N) {
551 CurDAG->getMachineNode(NVPTX::SETP_bf16x2rr,
DL, MVT::i1, MVT::i1,
552 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
553 ReplaceNode(
N, SetP);
557bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(SDNode *
N) {
559 MVT EltVT =
N->getSimpleValueType(0);
562 CurDAG->getMachineNode(NVPTX::I64toV2I32, SDLoc(
N), EltVT, EltVT,
Vector);
570bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(SDNode *
N) {
573 MVT VT =
Vector.getSimpleValueType();
579 Opcode = NVPTX::I32toV2I16;
581 Opcode = NVPTX::I64toV2I32;
587 for (
auto *U :
Vector.getNode()->users()) {
590 if (
U->getOperand(0) !=
Vector)
592 if (
const ConstantSDNode *IdxConst =
594 if (IdxConst->getZExtValue() == 0)
596 else if (IdxConst->getZExtValue() == 1)
612 CurDAG->getMachineNode(Opcode, SDLoc(
N), EltVT, EltVT,
Vector);
613 for (
auto *Node : E0)
615 for (
auto *Node : E1)
621NVPTX::AddressSpace NVPTXDAGToDAGISel::getAddrSpace(
const MemSDNode *
N) {
623 static_cast<NVPTX::AddressSpace
>(
N->getMemOperand()->getAddrSpace());
625 case NVPTX::AddressSpace::Generic:
626 case NVPTX::AddressSpace::Global:
627 case NVPTX::AddressSpace::Shared:
628 case NVPTX::AddressSpace::Const:
629 case NVPTX::AddressSpace::Local:
630 case NVPTX::AddressSpace::SharedCluster:
631 case NVPTX::AddressSpace::EntryParam:
632 case NVPTX::AddressSpace::DeviceParam:
638NVPTX::Ordering NVPTXDAGToDAGISel::getMemOrder(
const MemSDNode *
N)
const {
641 return NVPTX::Ordering::NotAtomic;
644 case AtomicOrdering::NotAtomic:
645 return NVPTX::Ordering::NotAtomic;
646 case AtomicOrdering::Unordered:
647 case AtomicOrdering::Monotonic:
648 return NVPTX::Ordering::Relaxed;
649 case AtomicOrdering::Acquire:
650 return NVPTX::Ordering::Acquire;
651 case AtomicOrdering::Release:
652 return NVPTX::Ordering::Release;
653 case AtomicOrdering::AcquireRelease:
654 return NVPTX::Ordering::AcquireRelease;
655 case AtomicOrdering::SequentiallyConsistent:
656 return NVPTX::Ordering::SequentiallyConsistent;
668NVPTX::Scope NVPTXDAGToDAGISel::getAtomicScope(
const MemSDNode *
N)
const {
670 return NVPTX::Scope::DefaultDevice;
676struct OperationOrderings {
677 NVPTX::Ordering InstructionOrdering, FenceOrdering;
678 OperationOrderings(NVPTX::Ordering IO = NVPTX::Ordering::NotAtomic,
679 NVPTX::Ordering FO = NVPTX::Ordering::NotAtomic)
680 : InstructionOrdering(IO), FenceOrdering(FO) {}
683static OperationOrderings
684getOperationOrderings(MemSDNode *
N,
const NVPTXSubtarget *Subtarget) {
686 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
774 if (CodeAddrSpace == NVPTX::AddressSpace::Local ||
775 CodeAddrSpace == NVPTX::AddressSpace::Const ||
776 CodeAddrSpace == NVPTX::AddressSpace::EntryParam ||
777 CodeAddrSpace == NVPTX::AddressSpace::DeviceParam) {
778 return NVPTX::Ordering::NotAtomic;
783 if (!(Ordering == AtomicOrdering::NotAtomic ||
784 Ordering == AtomicOrdering::Unordered ||
785 Ordering == AtomicOrdering::Monotonic) &&
786 !HasMemoryOrdering) {
788 formatv(
"PTX does not support \"atomic\" for orderings different than"
789 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
801 bool AddrGenericOrGlobalOrShared =
802 (CodeAddrSpace == NVPTX::AddressSpace::Generic ||
803 CodeAddrSpace == NVPTX::AddressSpace::Global ||
804 CodeAddrSpace == NVPTX::AddressSpace::Shared ||
805 CodeAddrSpace == NVPTX::AddressSpace::SharedCluster);
806 if (!AddrGenericOrGlobalOrShared)
807 return NVPTX::Ordering::NotAtomic;
809 bool UseRelaxedMMIO =
810 HasRelaxedMMIO && CodeAddrSpace == NVPTX::AddressSpace::Global;
813 case AtomicOrdering::NotAtomic:
814 return N->isVolatile() ? NVPTX::Ordering::Volatile
815 : NVPTX::Ordering::NotAtomic;
816 case AtomicOrdering::Unordered:
819 case AtomicOrdering::Monotonic:
821 return UseRelaxedMMIO ? NVPTX::Ordering::RelaxedMMIO
822 : NVPTX::Ordering::Volatile;
824 return HasMemoryOrdering ? NVPTX::Ordering::Relaxed
825 : NVPTX::Ordering::Volatile;
828 case AtomicOrdering::Acquire:
831 formatv(
"PTX only supports Acquire Ordering on reads: {}",
832 N->getOperationName()));
833 return NVPTX::Ordering::Acquire;
834 case AtomicOrdering::Release:
837 formatv(
"PTX only supports Release Ordering on writes: {}",
838 N->getOperationName()));
839 return NVPTX::Ordering::Release;
840 case AtomicOrdering::AcquireRelease: {
842 formatv(
"NVPTX does not support AcquireRelease Ordering on "
844 "yet and PTX does not support it on loads or stores: {}",
845 N->getOperationName()));
847 case AtomicOrdering::SequentiallyConsistent: {
855 NVPTX::Ordering InstrOrder;
857 InstrOrder = NVPTX::Ordering::Acquire;
858 else if (
N->writeMem())
859 InstrOrder = NVPTX::Ordering::Release;
862 formatv(
"NVPTX does not support SequentiallyConsistent Ordering on "
863 "read-modify-writes yet: {}",
864 N->getOperationName()));
865 return OperationOrderings(InstrOrder,
866 NVPTX::Ordering::SequentiallyConsistent);
870 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
876NVPTX::Scope NVPTXDAGToDAGISel::getOperationScope(MemSDNode *
N,
877 NVPTX::Ordering O)
const {
879 case NVPTX::Ordering::NotAtomic:
880 case NVPTX::Ordering::Volatile:
882 return NVPTX::Scope::Thread;
883 case NVPTX::Ordering::RelaxedMMIO:
887 return NVPTX::Scope::System;
888 case NVPTX::Ordering::Relaxed:
889 case NVPTX::Ordering::Acquire:
890 case NVPTX::Ordering::Release:
891 case NVPTX::Ordering::AcquireRelease:
892 case NVPTX::Ordering::SequentiallyConsistent:
893 auto S = Scopes[
N->getSyncScopeID()];
898 return N->isVolatile() ? NVPTX::Scope::System : S;
916 if (!
T->hasSplitAcquireAndReleaseFences() &&
924 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
925 : NVPTX::INT_MEMBAR_SYS;
927 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
928 : NVPTX::INT_MEMBAR_CTA;
930 return NVPTX::atomic_thread_fence_acquire_cluster;
932 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
933 : NVPTX::INT_MEMBAR_GL;
937 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
944 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
945 : NVPTX::INT_MEMBAR_SYS;
947 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
948 : NVPTX::INT_MEMBAR_CTA;
950 return NVPTX::atomic_thread_fence_release_cluster;
952 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
953 : NVPTX::INT_MEMBAR_GL;
957 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
964 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
965 : NVPTX::INT_MEMBAR_SYS;
967 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
968 : NVPTX::INT_MEMBAR_CTA;
970 return NVPTX::atomic_thread_fence_acq_rel_cluster;
972 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
973 : NVPTX::INT_MEMBAR_GL;
977 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
985 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
986 : NVPTX::INT_MEMBAR_SYS;
988 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
989 : NVPTX::INT_MEMBAR_CTA;
991 return NVPTX::atomic_thread_fence_seq_cst_cluster;
993 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
994 : NVPTX::INT_MEMBAR_GL;
1007 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1008 OrderingToString(O), ScopeToString(S)));
1016std::pair<NVPTX::Ordering, NVPTX::Scope>
1017NVPTXDAGToDAGISel::insertMemoryInstructionFence(SDLoc
DL,
SDValue &Chain,
1019 auto [InstructionOrdering, FenceOrdering] =
1020 getOperationOrderings(
N, Subtarget);
1021 auto Scope = getOperationScope(
N, InstructionOrdering);
1027 if (Scope == NVPTX::Scope::Thread &&
1028 InstructionOrdering != NVPTX::Ordering::NotAtomic &&
1029 InstructionOrdering != NVPTX::Ordering::Volatile)
1030 return {NVPTX::Ordering::NotAtomic,
Scope};
1033 switch (NVPTX::Ordering(FenceOrdering)) {
1034 case NVPTX::Ordering::NotAtomic:
1036 case NVPTX::Ordering::SequentiallyConsistent: {
1038 Chain =
SDValue(CurDAG->getMachineNode(
Op,
DL, MVT::Other, Chain), 0);
1043 formatv(
"Unexpected fence ordering: \"{}\".",
1046 return {InstructionOrdering,
Scope};
1051static std::optional<unsigned>
1053 std::optional<unsigned> Opcode_i32,
1054 std::optional<unsigned> Opcode_i64) {
1073 return std::nullopt;
1078 return V.getOpcode() ==
ISD::ADD ||
1079 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
1084 N =
N.getOperand(0);
1094 GA->getValueType(0), GA->getOffset(),
1095 GA->getTargetFlags());
1098 ES->getTargetFlags());
1107 APInt AccumulatedOffset(64u, 0);
1113 const APInt CI = CN->getAPIntValue().
sext(64);
1114 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1117 AccumulatedOffset += CI;
1174template <
typename T>
1175static std::optional<T>
1182 return std::nullopt;
1186 auto Parsed = Parse(ValStr);
1200 NVPTXMemCacheHintAccess
Access) {
1219 NVPTXMemCacheHintAccess
Access) {
1228std::pair<unsigned, SDValue> NVPTXDAGToDAGISel::getMemCacheHintOperands(
1229 const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
const SDLoc &
DL) {
1230 LLVMContext &Ctx = *CurDAG->getContext();
1231 const MDNode *
Node =
N->getMemCacheHint();
1232 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1234 return {0, PolicyReg};
1235 if (
Node->getNumOperands() == 0) {
1237 return {0, PolicyReg};
1240 NVPTX::L1Eviction L1 = NVPTX::L1Eviction::Normal;
1241 NVPTX::L2Eviction L2 = NVPTX::L2Eviction::Normal;
1242 NVPTX::L2Prefetch
Prefetch = NVPTX::L2Prefetch::None;
1243 std::optional<uint64_t> CachePolicy;
1245 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1247 StringRef KeyStr =
Key->getString();
1250 if (KeyStr ==
"nvvm.l1_eviction") {
1258 if (KeyStr ==
"nvvm.l2_eviction") {
1266 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1267 auto ParsedPrefetch =
1269 if (ParsedPrefetch &&
1275 if (KeyStr ==
"nvvm.l2_cache_hint") {
1279 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1282 CachePolicy = ValCI->getZExtValue();
1289 unsigned EvictionAndPrefetchHint =
1290 NVPTX::encodeEvictionAndPrefetchHint(L1, L2,
Prefetch);
1292 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1294 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1298 return {EvictionAndPrefetchHint, PolicyReg};
1301bool NVPTXDAGToDAGISel::tryLoad(SDNode *
N) {
1303 assert(
LD->readMem() &&
"Expected load");
1307 if (PlainLoad && PlainLoad->
isIndexed())
1311 const auto CodeAddrSpace = getAddrSpace(LD);
1317 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1319 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1327 uint32_t UsedBytesMask;
1328 switch (
N->getOpcode()) {
1331 UsedBytesMask = UINT32_MAX;
1334 UsedBytesMask =
N->getConstantOperandVal(3);
1341 FromTypeWidth <= 128 &&
"Invalid width for load");
1344 const auto [EvictionAndPrefetchHint, PolicyReg] =
1345 getMemCacheHintOperands(LD,
1346 {CodeAddrSpace,
true,
1352 getI32Imm(Scope,
DL),
1353 getI32Imm(CodeAddrSpace,
DL),
1354 getI32Imm(FromType,
DL),
1355 getI32Imm(FromTypeWidth,
DL),
1356 getI32Imm(UsedBytesMask,
DL),
1359 getI32Imm(EvictionAndPrefetchHint,
DL),
1364 const std::optional<unsigned> Opcode =
1365 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1369 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1373 MachineMemOperand *MemRef =
LD->getMemOperand();
1376 ReplaceNode(LD, NVPTXLD);
1381 switch (
N->getOpcode()) {
1393bool NVPTXDAGToDAGISel::tryLoadVector(SDNode *
N) {
1397 const auto CodeAddrSpace = getAddrSpace(LD);
1401 const MVT EltVT =
LD->getSimpleValueType(0);
1404 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1414 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1417 : NVPTX::PTXLdStInstCode::
Untyped;
1420 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1424 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1426 {CodeAddrSpace,
true,
1427 LD->getNumValues() - 1, FromTypeWidth},
1431 getI32Imm(Scope,
DL),
1432 getI32Imm(CodeAddrSpace,
DL),
1433 getI32Imm(FromType,
DL),
1434 getI32Imm(FromTypeWidth,
DL),
1435 getI32Imm(UsedBytesMask,
DL),
1438 getI32Imm(EvictionAndPrefetchHint,
DL),
1442 std::optional<unsigned> Opcode;
1443 switch (
N->getOpcode()) {
1448 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1452 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1456 NVPTX::LDV_i32_v8, {});
1462 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1464 MachineMemOperand *MemRef =
LD->getMemOperand();
1467 ReplaceNode(LD, NVPTXLD);
1471bool NVPTXDAGToDAGISel::tryLDG(MemSDNode *LD) {
1474 unsigned ExtensionType;
1475 uint32_t UsedBytesMask;
1477 ExtensionType =
Load->getExtensionType();
1478 UsedBytesMask = UINT32_MAX;
1480 ExtensionType =
LD->getConstantOperandVal(4);
1481 UsedBytesMask =
LD->getConstantOperandVal(3);
1485 : NVPTX::PTXLdStInstCode::
Untyped;
1489 assert(!(
LD->getSimpleValueType(0).isVector() &&
1493 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1495 {NVPTX::AddressSpace::Global,
1496 true,
LD->getNumValues() - 1, FromTypeWidth},
1499 getI32Imm(FromTypeWidth,
DL),
1500 getI32Imm(UsedBytesMask,
DL),
1503 getI32Imm(EvictionAndPrefetchHint,
DL),
1508 std::optional<unsigned> Opcode;
1509 switch (
LD->getOpcode()) {
1514 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1517 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1518 NVPTX::LD_GLOBAL_NC_i64);
1523 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1528 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1532 NVPTX::LD_GLOBAL_NC_v8i32, {});
1538 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1540 ReplaceNode(LD, NVPTXLDG);
1544bool NVPTXDAGToDAGISel::tryLDU(SDNode *
N) {
1559 std::optional<unsigned> Opcode;
1560 switch (
N->getOpcode()) {
1565 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1569 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1573 NVPTX::LDU_GLOBAL_v4i32, {});
1579 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1581 ReplaceNode(LD, NVPTXLDU);
1585bool NVPTXDAGToDAGISel::tryStore(SDNode *
N) {
1587 assert(
ST->writeMem() &&
"Expected store");
1590 assert((PlainStore || AtomicStore) &&
"Expected store");
1593 if (PlainStore && PlainStore->
isIndexed())
1597 const auto CodeAddrSpace = getAddrSpace(ST);
1601 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1604 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1610 "Invalid width for store");
1615 const auto [EvictionAndPrefetchHint, PolicyReg] =
1616 getMemCacheHintOperands(ST,
1617 {CodeAddrSpace,
false,
1622 getI32Imm(Ordering,
DL),
1623 getI32Imm(Scope,
DL),
1624 getI32Imm(CodeAddrSpace,
DL),
1625 getI32Imm(ToTypeWidth,
DL),
1628 getI32Imm(EvictionAndPrefetchHint,
DL),
1632 const std::optional<unsigned> Opcode =
1634 NVPTX::ST_i32, NVPTX::ST_i64);
1638 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1643 MachineMemOperand *MemRef =
ST->getMemOperand();
1645 ReplaceNode(ST, NVPTXST);
1649bool NVPTXDAGToDAGISel::tryStoreVector(SDNode *
N) {
1651 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1654 const auto CodeAddrSpace = getAddrSpace(ST);
1655 if (CodeAddrSpace == NVPTX::AddressSpace::Const) {
1662 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1667 for (
auto &V :
ST->ops().slice(1, NumElts))
1668 Ops.push_back(selectPossiblyImm(V));
1670 const unsigned ToTypeWidth = TotalWidth / NumElts;
1673 TotalWidth <= 256 &&
"Invalid width for store");
1676 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1678 {CodeAddrSpace,
false, NumElts,
1683 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1684 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1685 Offset, getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg,
1689 ST->getOperand(1).getSimpleValueType().SimpleTy;
1690 std::optional<unsigned> Opcode;
1691 switch (
ST->getOpcode()) {
1711 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1713 MachineMemOperand *MemRef =
ST->getMemOperand();
1716 ReplaceNode(ST, NVPTXST);
1722bool NVPTXDAGToDAGISel::tryBFE(SDNode *
N) {
1729 bool IsSigned =
false;
1745 uint64_t MaskVal =
Mask->getZExtValue();
1755 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1759 Val =
LHS.getNode()->getOperand(0);
1760 Start =
LHS.getNode()->getOperand(1);
1766 int64_t GoodBits =
Start.getValueSizeInBits() - StartVal;
1767 if (NumBits > GoodBits) {
1773 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1825 NumBits = NumZeros + NumOnes - ShiftAmt;
1831 if (ShiftAmt < NumZeros) {
1838 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1839 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1855 Val =
LHS->getOperand(0);
1874 if (OuterShiftAmt < InnerShiftAmt) {
1885 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1910 Opc = NVPTX::BFE_S32rii;
1912 Opc = NVPTX::BFE_U32rii;
1916 Opc = NVPTX::BFE_S64rii;
1918 Opc = NVPTX::BFE_U64rii;
1929 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
1934bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(SDNode *
N) {
1935 EVT VT =
SDValue(
N, 0).getValueType();
1953 APF.convert(APFloat::BFloat(), APFloat::rmNearestTiesToEven, &LosesInfo);
1956 auto API = APF.bitcastToAPInt();
1957 API = API.concat(API);
1958 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
1959 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
1962 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
1963 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
1966 switch (
N->getOpcode()) {
1969 Operands = {N0, GetConstant(1.0), N1};
1973 Operands = {N1, GetConstant(-1.0), N0};
1978 Operands = {N0, N1, GetConstant(-0.0)};
1984 int Opcode = IsVec ? NVPTX::FMA_BF16x2rrr : NVPTX::FMA_BF16rrr;
1985 MachineSDNode *
FMA = CurDAG->getMachineNode(Opcode,
DL, VT,
Operands);
1986 ReplaceNode(
N, FMA);
1992 V =
V.getOperand(0);
1995 return CurDAG->getTargetConstant(CN->getAPIntValue(), SDLoc(V),
1998 return CurDAG->getTargetConstantFP(CN->getValueAPF(), SDLoc(V),
2005bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2007 std::vector<SDValue> &OutOps) {
2008 switch (ConstraintID) {
2011 case InlineAsm::ConstraintCode::m: {
2013 OutOps.push_back(
Base);
2014 OutOps.push_back(
Offset);
2021void NVPTXDAGToDAGISel::SelectV2I64toI128(SDNode *
N) {
2037 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2040 NewOps[0] =
N->getOperand(0);
2043 if (
N->getNumOperands() == 5)
2044 NewOps[3] =
N->getOperand(4);
2047 ReplaceNode(
N, NewValue.
getNode());
2050void NVPTXDAGToDAGISel::SelectI128toV2I64(SDNode *
N) {
2067 SDNode *Mov = CurDAG->getMachineNode(
2068 NVPTX::I128toV2I64,
DL,
2072 ReplaceNode(
N, Mov);
2075bool NVPTXDAGToDAGISel::tryFence(SDNode *
N) {
2078 auto Scope = Scopes[
N->getConstantOperandVal(2)];
2083 if (Scope == NVPTX::Scope::Thread) {
2084 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0),
N->getOperand(0));
2085 CurDAG->RemoveDeadNode(
N);
2090 NVPTX::Ordering(
N->getConstantOperandVal(1)), Scope, Subtarget);
2092 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2093 ReplaceNode(
N, FenceNode);
2097NVPTXScopes::NVPTXScopes(LLVMContext &
C,
const Triple &
T) :
Context(&
C) {
2111 "NVPTXScopes::operator[]");
2113 auto S = Scopes.find(ID);
2114 if (S == Scopes.end()) {
2115 auto scopeName =
Context->getSyncScopeName(ID);
2116 assert(scopeName.has_value() &&
"Scope name must exist.");
2120 for (
const auto &Entry : Scopes) {
2126 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2127 "Supported syncscopes are: {2}.",
2128 scopeName.value(),
int(ID),
2134bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2136#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2137 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2138 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2142 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2144 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2146 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2148 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2150 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2152 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2154 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2156 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2158 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2160 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2162 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2164 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2166 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2168 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2170 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2172 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2174 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2176 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2178 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2180 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2182 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2184 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2186 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2188 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2190 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2192 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2194 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2196 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2198 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2200 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2202 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2204 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2206 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2208 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2210 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2212 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2214 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2220void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2223 "tcgen05.st is not supported on this architecture variant");
2233 Operands.push_back(CurDAG->getTargetConstant(
2237 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2249bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2250 unsigned IID =
N->getConstantOperandVal(1);
2254 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2255 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2256 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2257 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2258 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2259 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2260 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2261 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2262 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2263 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2264 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2265 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2266 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2267 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2268 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2269 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2270 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2271 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2272 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2273 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2274 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2275 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2276 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2277 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2278 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2279 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2280 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2281 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2282 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2287 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2288 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2289 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2290 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2291 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2292 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2293 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2294 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2295 SelectTcgen05St(
N,
true);
2301void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2308 Ops.append(
N->op_begin() + 2,
N->op_end());
2310 getI32Imm(getMemOrder(AN), dl),
2311 getI32Imm(getAtomicScope(AN), dl),
2312 getI32Imm(getAddrSpace(AN), dl),
2319 ? NVPTX::ATOM_EXCH_B128
2320 : NVPTX::ATOM_CAS_B128;
2322 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2325 ReplaceNode(
N, ATOM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
loop data Loop Data Prefetch
This file implements a map that provides insertion order iteration.
static NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
static std::optional< T > parseMemCacheHintStringValue(LLVMContext &Ctx, StringRef Key, const Metadata *Value, std::optional< T >(*Parse)(StringRef))
static unsigned getStoreVectorNumElts(SDNode *N)
static bool isAddLike(const SDValue V)
static std::optional< NVPTX::L2Eviction > parseL2Eviction(StringRef Str)
static SDValue selectBaseADDR(SDValue N, SelectionDAG *DAG)
static std::optional< NVPTX::L2Prefetch > parseL2Prefetch(StringRef Str)
static std::optional< NVPTX::L1Eviction > parseL1Eviction(StringRef Str)
static SDValue accumulateOffset(SDValue &Addr, SDLoc DL, SelectionDAG *DAG)
static bool isGlobalOrGeneric(NVPTX::AddressSpace AddrSpace)
static bool isL2PrefetchSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Prefetch Prefetch, NVPTXMemCacheHintAccess Access)
static unsigned getTcgen05StOpcode(unsigned IID, bool enableUnpack)
static std::optional< unsigned > pickOpcodeForVT(MVT::SimpleValueType VT, std::optional< unsigned > Opcode_i16, std::optional< unsigned > Opcode_i32, std::optional< unsigned > Opcode_i64)
static cl::opt< bool > EnableMADWide("nvptx-mad-wide-opt", cl::init(false), cl::Hidden, cl::desc("Enable MAD wide optimization"))
#define TCGEN05_LD_OPCODE(SHAPE, NUM)
static SDValue stripAssertAlign(SDValue N)
static cl::opt< bool > EnableRsqrtOpt("nvptx-rsqrt-approx-opt", cl::init(true), cl::Hidden, cl::desc("Enable reciprocal sqrt optimization"))
static void emitInvalidMemCacheHint(LLVMContext &Ctx, const Twine &Msg)
static unsigned int getFenceOp(NVPTX::Ordering O, NVPTX::Scope S, NVPTXSubtarget const *T)
static bool isL2EvictionSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Eviction Eviction, NVPTXMemCacheHintAccess Access)
#define TCGEN05_ST_OPCODE(SHAPE, NUM)
static std::pair< SDValue, SDValue > selectADDR(SDValue Addr, SelectionDAG *DAG)
static unsigned getTcgen05LdOpcode(unsigned IID, bool enablePack)
static bool canLowerToLDG(const MemSDNode &N, const NVPTXSubtarget &Subtarget, NVPTX::AddressSpace CodeAddrSpace)
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics,...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Class for arbitrary precision integers.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
int64_t getSExtValue() const
Get sign extended value.
const SDValue & getVal() const
uint64_t getZExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool is32BitVector() const
Return true if this is a 32-bit vector type.
MVT getVectorElementType() const
bool is64BitVector() const
Return true if this is a 64-bit vector type.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
This is an abstract virtual class for memory operations.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
bool hasL2Prefetch256B() const
bool hasL2EvictionHint() const
bool hasTcgen05InstSupport() const
bool hasL2Prefetch64B() const
bool hasL2Prefetch128B() const
bool hasNativeBF16Support(unsigned Opcode) const
bool hasL1EvictionHint() const
const NVPTXTargetLowering * getTargetLowering() const override
bool hasRelaxedMMIO() const
bool hasAtomScope() const
bool hasL2CacheHint() const
bool hasMemoryOrdering() const
bool useF32FTZ(const MachineFunction &MF) const
NVPTX::DivPrecisionLevel getDivF32Level(const MachineFunction &MF, const SDNode &N) const
bool allowFMA(MachineFunction &MF, CodeGenOptLevel OptLevel) const
bool usePrecSqrtF32(const SDNode *N=nullptr) const
const NVPTXSubtarget * getSubtargetImpl(const Function &) const override
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const SDValue & getOperand(unsigned Num) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
void push_back(const T &Elt)
const SDValue & getValue() const
Represent a constant reference to a string, i.e.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
const Triple & getTargetTriple() const
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ FADD
Simple binary floating point operators.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
@ ATOMIC_CMP_SWAP_B128
These nodes are used to lower atomic instructions with i128 type.
std::string OrderingToString(Ordering Order)
initializer< Ty > init(const Ty &Val)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
AtomicScope
Target-neutral memory synchronization scopes.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
FunctionPass * createNVPTXISelDag(NVPTXTargetMachine &TM, llvm::CodeGenOptLevel OptLevel)
createNVPTXISelDag - This pass converts a legalized DAG into a NVPTX-specific DAG,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
const char * toIRString(AtomicOrdering ao)
String used by LLVM IR to represent atomic ordering.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
unsigned getFromTypeWidthForLoad(const MemSDNode *Mem)
The bit-width of a single element loaded by Mem, i.e.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A record for a potential prefetch made during the initial scan of the loop.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
A MapVector that performs no allocations if smaller than a certain size.