33#include "llvm/IR/IntrinsicsNVPTX.h"
47#define DEBUG_TYPE "nvptx-isel"
48#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
52 cl::desc(
"Enable reciprocal sqrt optimization"));
59 cl::desc(
"Enable MAD wide optimization"));
64 NVPTXScopes() =
default;
71 LLVMContext *Context =
nullptr;
74enum class NVPTXMemCacheHintInstruction { Ld, St, Atom };
76struct NVPTXMemCacheHintAccess {
77 NVPTXMemCacheHintInstruction Instruction;
78 NVPTX::AddressSpace AddrSpace;
84struct NVPTXMemCacheHintOperands {
85 SDValue EvictionAndPrefetchHint;
86 SDValue CachePolicyReg;
90 const NVPTXTargetMachine &TM;
92 NVPTX::DivPrecisionLevel getDivF32Level(
const SDNode *
N)
const;
93 bool usePrecSqrtF32(
const SDNode *
N)
const;
94 bool useF32FTZ()
const;
95 bool allowFMA()
const;
96 bool doRsqrtOpt()
const;
97 bool doMADWideOpt()
const;
102 NVPTXDAGToDAGISel() =
delete;
104 explicit NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
CodeGenOptLevel OptLevel);
107 const NVPTXSubtarget *Subtarget =
nullptr;
109 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
111 std::vector<SDValue> &OutOps)
override;
115#include "NVPTXGenDAGISel.inc"
117 void Select(SDNode *
N)
override;
118 bool tryIntrinsicChain(SDNode *
N);
119 bool tryIntrinsicVoid(SDNode *
N);
120 bool tryLoad(SDNode *
N);
121 bool tryLoadVector(SDNode *
N);
122 bool tryLDU(SDNode *
N);
123 bool tryLDG(MemSDNode *
N);
124 bool tryStore(SDNode *
N);
125 bool tryStoreVector(SDNode *
N);
126 bool tryFence(SDNode *
N);
127 bool tryBFE(SDNode *
N);
128 bool tryBF16ArithToFMA(SDNode *
N);
129 bool SelectSETP_F16X2(SDNode *
N);
130 bool SelectSETP_BF16X2(SDNode *
N);
131 bool tryUNPACK_VECTOR(SDNode *
N);
132 bool tryEXTRACT_VECTOR_ELEMENT(SDNode *
N);
133 void PostprocessISelDAG()
override;
134 void SelectV2I64toI128(SDNode *
N);
135 void SelectI128toV2I64(SDNode *
N);
136 void SelectTcgen05Ld(SDNode *
N,
bool hasOffset =
false);
137 void SelectTcgen05St(SDNode *
N,
bool hasOffset =
false);
138 void selectAtomicSwap128(SDNode *
N);
140 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
141 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
143 NVPTX::Ordering getMemOrder(
const MemSDNode *
N)
const;
144 NVPTX::Scope getAtomicScope(
const MemSDNode *
N)
const;
146 bool SelectADDR(SDValue Addr, SDValue &
Base, SDValue &
Offset);
147 bool SelectFAbs(SDValue
N, SDValue &Src);
148 SDValue getPTXCmpMode(
const CondCodeSDNode &CondCode);
149 SDValue selectPossiblyImm(SDValue V);
156 NVPTXMemCacheHintOperands
157 getMemCacheHintOperands(
const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
158 const SDLoc &
DL,
bool EmitDiagnostics =
true);
162 std::pair<NVPTX::Ordering, NVPTX::Scope>
163 getMemInstOrderingScope(MemSDNode *
N);
165 NVPTX::Scope getOperationScope(MemSDNode *
N, NVPTX::Ordering O)
const;
168 static NVPTX::AddressSpace getAddrSpace(
const MemSDNode *
N);
174 explicit NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm,
184 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
190 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
192char NVPTXDAGToDAGISelLegacy::ID = 0;
212NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
213 return Subtarget->getTargetLowering()->getDivF32Level(*MF, *
N);
216bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
217 return Subtarget->getTargetLowering()->usePrecSqrtF32(
N);
220bool NVPTXDAGToDAGISel::useF32FTZ()
const {
221 return Subtarget->getTargetLowering()->useF32FTZ(*MF);
224bool NVPTXDAGToDAGISel::allowFMA()
const {
229bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
231bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
235void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
237 if (
N->isMachineOpcode()) {
242 switch (
N->getOpcode()) {
262 if (tryEXTRACT_VECTOR_ELEMENT(
N))
269 SelectSETP_BF16X2(
N);
274 if (tryLoadVector(
N))
285 if (tryStoreVector(
N))
289 if (tryIntrinsicChain(
N))
293 if (tryIntrinsicVoid(
N))
304 if (
N->getOperand(1).getValueType() == MVT::i128) {
305 SelectV2I64toI128(
N);
311 if (
N->getOperand(1).getValueType() == MVT::i128) {
312 SelectI128toV2I64(
N);
319 selectAtomicSwap128(
N);
324 if (tryBF16ArithToFMA(
N))
333#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
334 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
335 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
339 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
341 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
343 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
345 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
347 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
349 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
351 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
353 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
355 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
357 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
359 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
361 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
363 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
365 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
367 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
369 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
371 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
373 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
375 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
377 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
379 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
381 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
383 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
385 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
387 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
389 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
391 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
393 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
395 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
397 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
399 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
401 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
403 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
405 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
407 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
409 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
411 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
417void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
418 if (!Subtarget->hasTcgen05InstSupport())
420 "tcgen05.ld is not supported on this architecture variant");
427 auto OffsetNode = CurDAG->getTargetConstant(
429 ReplaceNode(
N, CurDAG->getMachineNode(
431 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
434 ReplaceNode(
N, CurDAG->getMachineNode(
436 {N->getOperand(2), N->getOperand(0)}));
440bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
441 unsigned IID =
N->getConstantOperandVal(1);
445 case Intrinsic::nvvm_ldu_global_f:
446 case Intrinsic::nvvm_ldu_global_i:
447 case Intrinsic::nvvm_ldu_global_p:
450 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
451 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
452 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
453 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
454 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
455 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
456 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
457 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
458 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
459 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
460 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
461 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
462 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
463 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
464 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
465 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
466 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
467 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
468 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
469 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
470 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
471 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
472 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
473 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
474 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
475 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
476 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
477 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
478 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
483 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
484 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
485 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
486 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
487 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
488 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
489 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
490 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
491 SelectTcgen05Ld(
N,
true);
526 return CmpMode::NotANumber;
541 return CurDAG->getTargetConstant(PTXCmpMode,
SDLoc(), MVT::i32);
544bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
547 SDNode *SetP = CurDAG->getMachineNode(
548 NVPTX::SETP_f16x2,
DL, MVT::i1, MVT::i1,
549 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
550 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
551 ReplaceNode(
N, SetP);
555bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
559 CurDAG->getMachineNode(NVPTX::SETP_bf16x2,
DL, MVT::i1, MVT::i1,
560 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
561 ReplaceNode(
N, SetP);
565bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
567 MVT EltVT =
N->getSimpleValueType(0);
570 CurDAG->getMachineNode(NVPTX::I64toV2I32,
SDLoc(
N), EltVT, EltVT,
Vector);
578bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
587 Opcode = NVPTX::I32toV2I16;
589 Opcode = NVPTX::I64toV2I32;
595 for (
auto *U :
Vector.getNode()->users()) {
598 if (
U->getOperand(0) !=
Vector)
602 if (IdxConst->getZExtValue() == 0)
604 else if (IdxConst->getZExtValue() == 1)
620 CurDAG->getMachineNode(Opcode,
SDLoc(
N), EltVT, EltVT,
Vector);
621 for (
auto *Node : E0)
623 for (
auto *Node : E1)
630 if (!
N->isMachineOpcode() ||
N->use_empty())
632 switch (
N->getMachineOpcode()) {
635 case NVPTX::CVT_u16_u32:
639 case NVPTX::I32toI16L:
640 case NVPTX::I32toI16L_Sink:
642 case NVPTX::I32toI16H:
643 case NVPTX::I32toI16H_Sink:
671 if (Halves[0].empty() || Halves[1].empty())
676 for (
unsigned Index : {0u, 1u})
677 for (
SDValue V : Halves[Index])
685void NVPTXDAGToDAGISel::PostprocessISelDAG() {
mergeI16Unpacks(*CurDAG); }
706 if (!Subtarget->hasMemoryOrdering())
736 if (!Subtarget->hasAtomScope()) {
739 CurDAG->getMachineFunction().getFunction(),
740 "NVPTX system scope atomics require sm_60 or later",
752 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
863 !HasMemoryOrdering) {
865 formatv(
"PTX does not support \"atomic\" for orderings different than"
866 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
876 bool AddrSupportsVolatileOrAtomic =
881 if (!AddrSupportsVolatileOrAtomic)
884 bool UseRelaxedMMIO =
906 formatv(
"PTX only supports Acquire Ordering on reads: {}",
907 N->getOperationName()));
912 formatv(
"PTX only supports Release Ordering on writes: {}",
913 N->getOperationName()));
917 formatv(
"NVPTX does not support AcquireRelease Ordering on "
919 "yet and PTX does not support it on loads or stores: {}",
920 N->getOperationName()));
931 "is emulated in AtomicExpandPass");
935 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
958 auto S =
Scopes[
N->getSyncScopeID()];
981 if (!
T->hasSplitAcquireAndReleaseFences() &&
989 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
990 : NVPTX::INT_MEMBAR_SYS;
992 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
993 : NVPTX::INT_MEMBAR_CTA;
995 return NVPTX::atomic_thread_fence_acquire_cluster;
997 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
998 : NVPTX::INT_MEMBAR_GL;
1002 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1009 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
1010 : NVPTX::INT_MEMBAR_SYS;
1012 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
1013 : NVPTX::INT_MEMBAR_CTA;
1015 return NVPTX::atomic_thread_fence_release_cluster;
1017 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
1018 : NVPTX::INT_MEMBAR_GL;
1022 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1029 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
1030 : NVPTX::INT_MEMBAR_SYS;
1032 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
1033 : NVPTX::INT_MEMBAR_CTA;
1035 return NVPTX::atomic_thread_fence_acq_rel_cluster;
1037 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
1038 : NVPTX::INT_MEMBAR_GL;
1042 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1050 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
1051 : NVPTX::INT_MEMBAR_SYS;
1053 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
1054 : NVPTX::INT_MEMBAR_CTA;
1056 return NVPTX::atomic_thread_fence_seq_cst_cluster;
1058 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
1059 : NVPTX::INT_MEMBAR_GL;
1072 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1073 OrderingToString(O), ScopeToString(S)));
1079std::pair<NVPTX::Ordering, NVPTX::Scope>
1080NVPTXDAGToDAGISel::getMemInstOrderingScope(
MemSDNode *
N) {
1098static std::optional<unsigned>
1100 std::optional<unsigned> Opcode_i32,
1101 std::optional<unsigned> Opcode_i64) {
1120 return std::nullopt;
1125 return V.getOpcode() ==
ISD::ADD ||
1126 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
1131 N =
N.getOperand(0);
1141 GA->getValueType(0), GA->getOffset(),
1142 GA->getTargetFlags());
1145 ES->getTargetFlags());
1148 if (
N.getOpcode() == NVPTXISD::Symbol)
1149 return N.getOperand(0);
1156 APInt AccumulatedOffset(64u, 0);
1162 const APInt CI = CN->getAPIntValue().
sext(64);
1163 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1166 AccumulatedOffset += CI;
1223template <
typename T>
1226 std::optional<T> (*Parse)(
StringRef),
bool EmitDiagnostics) {
1229 if (EmitDiagnostics)
1231 Twine(
"'") +
Key +
"' expects a string value");
1232 return std::nullopt;
1236 auto Parsed = Parse(ValStr);
1237 if (!Parsed && EmitDiagnostics)
1249 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld ||
1250 Access.Instruction == NVPTXMemCacheHintInstruction::St;
1255 NVPTXMemCacheHintAccess
Access) {
1265 NVPTXMemCacheHintAccess
Access) {
1270 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1273 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1276 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1284 NVPTXMemCacheHintAccess
Access) {
1295 NVPTXMemCacheHintAccess
Access) {
1300NVPTXMemCacheHintOperands NVPTXDAGToDAGISel::getMemCacheHintOperands(
1302 bool EmitDiagnostics) {
1305 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1307 return {getI32Imm(0,
DL), PolicyReg};
1308 if (
Node->getNumOperands() == 0) {
1309 if (EmitDiagnostics)
1311 return {getI32Imm(0,
DL), PolicyReg};
1317 std::optional<uint64_t> CachePolicy;
1319 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1324 if (KeyStr ==
"nvvm.l1_eviction") {
1332 if (KeyStr ==
"nvvm.l2_eviction") {
1340 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1343 if (ParsedPrefetch &&
1349 if (KeyStr ==
"nvvm.l2_cache_hint") {
1352 if (EmitDiagnostics)
1354 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1356 CachePolicy = ValCI->getZExtValue();
1361 if (EmitDiagnostics)
1365 unsigned EvictionAndPrefetchHint =
1368 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1370 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1374 return {getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg};
1377bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1379 assert(
LD->readMem() &&
"Expected load");
1383 if (PlainLoad && PlainLoad->
isIndexed())
1387 const auto CodeAddrSpace = getAddrSpace(LD);
1395 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1403 uint32_t UsedBytesMask;
1404 switch (
N->getOpcode()) {
1407 UsedBytesMask = UINT32_MAX;
1410 UsedBytesMask =
N->getConstantOperandVal(3);
1417 FromTypeWidth <= 128 &&
"Invalid width for load");
1420 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1422 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1423 1, FromTypeWidth,
LD->isVolatile()},
1428 getI32Imm(Scope,
DL),
1429 getI32Imm(CodeAddrSpace,
DL),
1430 getI32Imm(FromType,
DL),
1431 getI32Imm(FromTypeWidth,
DL),
1432 getI32Imm(UsedBytesMask,
DL),
1435 EvictionAndPrefetchHint,
1440 const std::optional<unsigned> Opcode =
1441 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1445 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1452 ReplaceNode(LD, NVPTXLD);
1457 switch (
N->getOpcode()) {
1469bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1473 const auto CodeAddrSpace = getAddrSpace(LD);
1477 const MVT EltVT =
LD->getSimpleValueType(0);
1490 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1496 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1500 const auto [EvictionAndPrefetchHint, PolicyReg] =
1501 getMemCacheHintOperands(LD,
1502 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1503 LD->getNumValues() - 1,
1504 FromTypeWidth,
LD->isVolatile()},
1508 getI32Imm(Scope,
DL),
1509 getI32Imm(CodeAddrSpace,
DL),
1510 getI32Imm(FromType,
DL),
1511 getI32Imm(FromTypeWidth,
DL),
1512 getI32Imm(UsedBytesMask,
DL),
1515 EvictionAndPrefetchHint,
1519 std::optional<unsigned> Opcode;
1520 switch (
N->getOpcode()) {
1525 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1529 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1533 NVPTX::LDV_i32_v8, {});
1539 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1544 ReplaceNode(LD, NVPTXLD);
1548bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1551 unsigned ExtensionType;
1552 uint32_t UsedBytesMask;
1554 ExtensionType =
Load->getExtensionType();
1555 UsedBytesMask = UINT32_MAX;
1557 ExtensionType =
LD->getConstantOperandVal(4);
1558 UsedBytesMask =
LD->getConstantOperandVal(3);
1566 assert(!(
LD->getSimpleValueType(0).isVector() &&
1570 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1573 LD->getNumValues() - 1, FromTypeWidth,
LD->isVolatile()},
1576 getI32Imm(FromTypeWidth,
DL),
1577 getI32Imm(UsedBytesMask,
DL),
1580 EvictionAndPrefetchHint,
1585 std::optional<unsigned> Opcode;
1586 switch (
LD->getOpcode()) {
1591 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1594 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1595 NVPTX::LD_GLOBAL_NC_i64);
1600 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1605 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1609 NVPTX::LD_GLOBAL_NC_v8i32, {});
1615 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1617 ReplaceNode(LD, NVPTXLDG);
1621bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1636 std::optional<unsigned> Opcode;
1637 switch (
N->getOpcode()) {
1642 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1646 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1650 NVPTX::LDU_GLOBAL_v4i32, {});
1656 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1658 ReplaceNode(LD, NVPTXLDU);
1662bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1664 assert(
ST->writeMem() &&
"Expected store");
1667 assert((PlainStore || AtomicStore) &&
"Expected store");
1670 if (PlainStore && PlainStore->
isIndexed())
1674 const auto CodeAddrSpace = getAddrSpace(ST);
1681 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1687 "Invalid width for store");
1692 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1694 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1695 1, ToTypeWidth,
ST->isVolatile()},
1699 getI32Imm(Ordering,
DL),
1700 getI32Imm(Scope,
DL),
1701 getI32Imm(CodeAddrSpace,
DL),
1702 getI32Imm(ToTypeWidth,
DL),
1705 EvictionAndPrefetchHint,
1709 const std::optional<unsigned> Opcode =
1711 NVPTX::ST_i32, NVPTX::ST_i64);
1715 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1722 ReplaceNode(ST, NVPTXST);
1726bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1728 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1731 const auto CodeAddrSpace = getAddrSpace(ST);
1744 for (
auto &V :
ST->ops().slice(1, NumElts))
1747 const unsigned ToTypeWidth = TotalWidth / NumElts;
1750 TotalWidth <= 256 &&
"Invalid width for store");
1753 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1755 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1756 NumElts, ToTypeWidth,
ST->isVolatile()},
1760 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1761 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1762 Offset, EvictionAndPrefetchHint, PolicyReg, Chain});
1765 ST->getOperand(1).getSimpleValueType().SimpleTy;
1766 std::optional<unsigned> Opcode;
1767 switch (
ST->getOpcode()) {
1787 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1792 ReplaceNode(ST, NVPTXST);
1798bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1801 if (Subtarget->hasFeature(NVPTX::SM70))
1810 bool IsSigned =
false;
1836 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1840 Val =
LHS.getNode()->getOperand(0);
1841 Start =
LHS.getNode()->getOperand(1);
1848 if (NumBits > GoodBits) {
1854 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1906 NumBits = NumZeros + NumOnes - ShiftAmt;
1912 if (ShiftAmt < NumZeros) {
1919 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1920 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1936 Val =
LHS->getOperand(0);
1955 if (OuterShiftAmt < InnerShiftAmt) {
1966 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1988 unsigned Opc = IsSigned ? NVPTX::BFE_S32 : NVPTX::BFE_U32;
1992 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
1997bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
2019 auto API = APF.bitcastToAPInt();
2020 API = API.concat(API);
2021 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
2022 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
2025 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
2026 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
2029 switch (
N->getOpcode()) {
2032 Operands = {N0, GetConstant(1.0), N1};
2036 Operands = {N1, GetConstant(-1.0), N0};
2041 Operands = {N0, N1, GetConstant(-0.0)};
2047 int Opcode = IsVec ? NVPTX::FMA_BF16x2 : NVPTX::FMA_BF16;
2049 ReplaceNode(
N, FMA);
2058 Src =
N.getOperand(0);
2059 else if (CurDAG->computeKnownFPClass(
N,
fcNegative).signBitIsZeroOrNaN())
2063 Src = selectPossiblyImm(Src);
2069 V =
V.getOperand(0);
2072 return CurDAG->getTargetConstant(CN->getAPIntValue(),
SDLoc(V),
2075 return CurDAG->getTargetConstantFP(CN->getValueAPF(),
SDLoc(V),
2082bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2084 std::vector<SDValue> &OutOps) {
2085 switch (ConstraintID) {
2090 OutOps.push_back(
Base);
2091 OutOps.push_back(
Offset);
2098void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
2109 SDValue Lo = selectPossiblyImm(
N->getOperand(2));
2110 SDValue Hi = selectPossiblyImm(
N->getOperand(3));
2114 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2117 NewOps[0] =
N->getOperand(0);
2120 if (
N->getNumOperands() == 5)
2121 NewOps[3] =
N->getOperand(4);
2124 ReplaceNode(
N, NewValue.
getNode());
2127void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
2144 SDNode *Mov = CurDAG->getMachineNode(
2145 NVPTX::I128toV2I64,
DL,
2149 ReplaceNode(
N, Mov);
2152bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
2162 CurDAG->RemoveDeadNode(
N);
2169 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2170 ReplaceNode(
N, FenceNode);
2188 "NVPTXScopes::operator[]");
2190 auto S = Scopes.find(ID);
2191 if (S == Scopes.end()) {
2192 auto scopeName =
Context->getSyncScopeName(ID);
2193 assert(scopeName.has_value() &&
"Scope name must exist.");
2197 for (
const auto &Entry : Scopes) {
2203 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2204 "Supported syncscopes are: {2}.",
2205 scopeName.value(),
int(ID),
2211bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2213#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2214 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2215 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2219 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2221 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2223 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2225 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2227 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2229 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2231 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2233 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2235 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2237 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2239 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2241 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2243 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2245 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2247 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2249 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2251 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2253 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2255 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2257 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2259 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2261 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2263 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2265 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2267 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2269 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2271 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2273 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2275 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2277 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2279 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2281 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2283 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2285 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2287 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2289 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2291 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2297void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2300 "tcgen05.st is not supported on this architecture variant");
2310 Operands.push_back(CurDAG->getTargetConstant(
2314 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2326bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2327 unsigned IID =
N->getConstantOperandVal(1);
2331 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2332 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2333 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2334 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2335 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2336 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2337 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2338 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2339 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2340 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2341 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2342 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2343 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2344 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2345 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2346 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2347 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2348 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2349 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2350 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2351 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2352 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2353 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2354 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2355 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2356 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2357 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2358 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2359 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2364 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2365 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2366 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2367 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2368 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2369 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2370 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2371 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2372 SelectTcgen05St(
N,
true);
2378void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2385 for (
const SDValue &Operand :
drop_begin(
N->op_values(), 2))
2386 Ops.push_back(selectPossiblyImm(Operand));
2387 Ops.append({getI32Imm(getMemOrder(AN), dl), getI32Imm(getAtomicScope(AN), dl),
2388 getI32Imm(getAddrSpace(AN), dl)});
2392 NVPTXMemCacheHintAccess
Access{NVPTXMemCacheHintInstruction::Atom,
2395 const auto [EvictionAndPrefetchHint, CachePolicyReg] =
2396 getMemCacheHintOperands(AN,
Access, dl);
2397 Ops.push_back(EvictionAndPrefetchHint);
2398 Ops.push_back(CachePolicyReg);
2401 Ops.push_back(Chain);
2406 ? NVPTX::ATOM_EXCH_B128
2407 : NVPTX::ATOM_CAS_B128;
2409 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2412 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 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 std::optional< unsigned > getI16ExtractIndex(const SDNode *N)
static void mergeI16Unpacks(SelectionDAG &DAG)
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 bool isLdOrSt(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 std::optional< T > parseMemCacheHintStringValue(LLVMContext &Ctx, StringRef Key, const Metadata *Value, std::optional< T >(*Parse)(StringRef), bool EmitDiagnostics)
static bool isL2EvictionSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Eviction Eviction, NVPTXMemCacheHintAccess Access)
#define TCGEN05_ST_OPCODE(SHAPE, NUM)
static bool isL1EvictionSupported(const NVPTXSubtarget &Subtarget, NVPTX::L1Eviction Eviction, NVPTXMemCacheHintAccess Access)
static bool isCachePolicySupported(const NVPTXSubtarget &Subtarget, NVPTXMemCacheHintAccess Access)
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)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static const fltSemantics & BFloat()
static constexpr roundingMode rmNearestTiesToEven
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.
This is an SDNode representing atomic operations.
const SDValue & getVal() const
uint64_t getZExtValue() const
Diagnostic information for unsupported feature in backend.
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.
Record instruction ordering so we can query their relative positions within a 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.
This class is used to represent ISD::LOAD nodes.
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
A description of a memory reference used in the backend.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
NVPTXISelDAGToDAGPass(NVPTXTargetMachine &TM, CodeGenOptLevel OptLevel)
bool hasL2Prefetch256B() const
bool hasL2EvictionHint() const
bool hasTcgen05InstSupport() const
bool hasL2Prefetch64B() const
bool hasL2Prefetch128B() const
bool hasNativeBF16Support(unsigned Opcode) const
bool hasL1EvictionHint() const
bool hasRelaxedMMIO() const
bool hasL2CacheHint() const
bool hasLocalVolatile() const
bool hasMemoryOrdering() const
bool allowFMA(MachineFunction &MF, CodeGenOptLevel OptLevel) const
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
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
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)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
allnodes_const_iterator allnodes_begin() const
allnodes_const_iterator allnodes_end() const
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
ilist< SDNode >::iterator allnodes_iterator
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
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...
Value * getOperand(unsigned i) const
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.
unsigned encodeEvictionAndPrefetchHint(L1Eviction L1, L2Eviction L2, L2Prefetch P)
bool isPackedVectorTy(EVT VT)
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.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
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,...
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.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
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.