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 void SelectTexSurfHandle(SDNode *
N);
121 bool tryLoad(SDNode *
N);
122 bool tryLoadVector(SDNode *
N);
123 bool tryLDU(SDNode *
N);
124 bool tryLDG(MemSDNode *
N);
125 bool tryStore(SDNode *
N);
126 bool tryStoreVector(SDNode *
N);
127 bool tryFence(SDNode *
N);
128 bool tryBFE(SDNode *
N);
129 bool tryBF16ArithToFMA(SDNode *
N);
130 bool tryConstantFP(SDNode *
N);
131 bool SelectSETP_F16X2(SDNode *
N);
132 bool SelectSETP_BF16X2(SDNode *
N);
133 bool tryUNPACK_VECTOR(SDNode *
N);
134 bool tryEXTRACT_VECTOR_ELEMENT(SDNode *
N);
135 void SelectV2I64toI128(SDNode *
N);
136 void SelectI128toV2I64(SDNode *
N);
137 void SelectCpAsyncBulkTensorReduceCommon(SDNode *
N,
unsigned RedOp,
138 bool IsIm2Col =
false);
139 void SelectTcgen05Ld(SDNode *
N,
bool hasOffset =
false);
140 void SelectTcgen05St(SDNode *
N,
bool hasOffset =
false);
141 void selectAtomicSwap128(SDNode *
N);
143 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
144 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
146 NVPTX::Ordering getMemOrder(
const MemSDNode *
N)
const;
147 NVPTX::Scope getAtomicScope(
const MemSDNode *
N)
const;
149 bool SelectADDR(SDValue Addr, SDValue &
Base, SDValue &
Offset);
150 bool SelectFAbs(SDValue
N, SDValue &Src);
151 SDValue getPTXCmpMode(
const CondCodeSDNode &CondCode);
152 SDValue selectPossiblyImm(SDValue V);
159 NVPTXMemCacheHintOperands
160 getMemCacheHintOperands(
const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
161 const SDLoc &
DL,
bool EmitDiagnostics =
true);
167 std::pair<NVPTX::Ordering, NVPTX::Scope>
168 insertMemoryInstructionFence(SDLoc
DL, SDValue &Chain, MemSDNode *
N);
169 NVPTX::Scope getOperationScope(MemSDNode *
N, NVPTX::Ordering O)
const;
172 static NVPTX::AddressSpace getAddrSpace(
const MemSDNode *
N);
178 explicit NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm,
188 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
194 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
196char NVPTXDAGToDAGISelLegacy::ID = 0;
216NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
217 return Subtarget->getTargetLowering()->getDivF32Level(*MF, *
N);
220bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
221 return Subtarget->getTargetLowering()->usePrecSqrtF32(
N);
224bool NVPTXDAGToDAGISel::useF32FTZ()
const {
225 return Subtarget->getTargetLowering()->useF32FTZ(*MF);
228bool NVPTXDAGToDAGISel::allowFMA()
const {
233bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
235bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
239void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
241 if (
N->isMachineOpcode()) {
246 switch (
N->getOpcode()) {
266 if (tryEXTRACT_VECTOR_ELEMENT(
N))
273 SelectSETP_BF16X2(
N);
278 if (tryLoadVector(
N))
289 if (tryStoreVector(
N))
293 if (tryIntrinsicChain(
N))
297 if (tryIntrinsicVoid(
N))
308 if (
N->getOperand(1).getValueType() == MVT::i128) {
309 SelectV2I64toI128(
N);
315 if (
N->getOperand(1).getValueType() == MVT::i128) {
316 SelectI128toV2I64(
N);
323 selectAtomicSwap128(
N);
328 if (tryBF16ArithToFMA(
N))
337#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
338 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
339 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
343 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
345 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
347 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
349 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
351 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
353 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
355 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
357 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
359 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
361 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
363 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
365 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
367 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
369 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
371 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
373 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
375 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
377 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
379 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
381 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
383 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
385 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
387 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
389 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
391 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
393 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
395 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
397 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
399 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
401 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
403 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
405 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
407 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
409 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
411 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
413 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
415 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
421void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
422 if (!Subtarget->hasTcgen05InstSupport())
424 "tcgen05.ld is not supported on this architecture variant");
431 auto OffsetNode = CurDAG->getTargetConstant(
433 ReplaceNode(
N, CurDAG->getMachineNode(
435 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
438 ReplaceNode(
N, CurDAG->getMachineNode(
440 {N->getOperand(2), N->getOperand(0)}));
444bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
445 unsigned IID =
N->getConstantOperandVal(1);
449 case Intrinsic::nvvm_ldu_global_f:
450 case Intrinsic::nvvm_ldu_global_i:
451 case Intrinsic::nvvm_ldu_global_p:
454 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
455 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
456 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
457 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
458 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
459 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
460 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
461 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
462 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
463 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
464 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
465 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
466 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
467 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
468 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
469 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
470 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
471 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
472 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
473 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
474 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
475 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
476 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
477 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
478 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
479 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
480 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
481 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
482 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
487 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
488 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
489 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
490 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
491 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
492 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
493 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
494 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
495 SelectTcgen05Ld(
N,
true);
530 return CmpMode::NotANumber;
545 return CurDAG->getTargetConstant(PTXCmpMode,
SDLoc(), MVT::i32);
548bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
551 SDNode *SetP = CurDAG->getMachineNode(
552 NVPTX::SETP_f16x2rr,
DL, MVT::i1, MVT::i1,
553 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
554 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
555 ReplaceNode(
N, SetP);
559bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
563 CurDAG->getMachineNode(NVPTX::SETP_bf16x2rr,
DL, MVT::i1, MVT::i1,
564 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
565 ReplaceNode(
N, SetP);
569bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
571 MVT EltVT =
N->getSimpleValueType(0);
574 CurDAG->getMachineNode(NVPTX::I64toV2I32,
SDLoc(
N), EltVT, EltVT,
Vector);
582bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
591 Opcode = NVPTX::I32toV2I16;
593 Opcode = NVPTX::I64toV2I32;
599 for (
auto *U :
Vector.getNode()->users()) {
602 if (
U->getOperand(0) !=
Vector)
606 if (IdxConst->getZExtValue() == 0)
608 else if (IdxConst->getZExtValue() == 1)
624 CurDAG->getMachineNode(Opcode,
SDLoc(
N), EltVT, EltVT,
Vector);
625 for (
auto *Node : E0)
627 for (
auto *Node : E1)
652 if (!Subtarget->hasMemoryOrdering())
682 if (!Subtarget->hasAtomScope()) {
685 CurDAG->getMachineFunction().getFunction(),
686 "NVPTX system scope atomics require sm_60 or later",
695struct OperationOrderings {
696 NVPTX::Ordering InstructionOrdering, FenceOrdering;
697 OperationOrderings(NVPTX::Ordering IO = NVPTX::Ordering::NotAtomic,
698 NVPTX::Ordering FO = NVPTX::Ordering::NotAtomic)
699 : InstructionOrdering(IO), FenceOrdering(FO) {}
702static OperationOrderings
705 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
710 Subtarget->hasFeature(NVPTX::PTX91) &&
804 !IsSupportedLocalVolatile) ||
816 !HasMemoryOrdering) {
818 formatv(
"PTX does not support \"atomic\" for orderings different than"
819 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
829 bool AddrSupportsVolatileOrAtomic =
830 (IsSupportedLocalVolatile ||
835 if (!AddrSupportsVolatileOrAtomic)
838 bool UseRelaxedMMIO =
860 formatv(
"PTX only supports Acquire Ordering on reads: {}",
861 N->getOperationName()));
866 formatv(
"PTX only supports Release Ordering on writes: {}",
867 N->getOperationName()));
871 formatv(
"NVPTX does not support AcquireRelease Ordering on "
873 "yet and PTX does not support it on loads or stores: {}",
874 N->getOperationName()));
887 else if (
N->writeMem())
891 formatv(
"NVPTX does not support SequentiallyConsistent Ordering on "
892 "read-modify-writes yet: {}",
893 N->getOperationName()));
894 return OperationOrderings(InstrOrder,
899 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
922 auto S =
Scopes[
N->getSyncScopeID()];
945 if (!
T->hasSplitAcquireAndReleaseFences() &&
953 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
954 : NVPTX::INT_MEMBAR_SYS;
956 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
957 : NVPTX::INT_MEMBAR_CTA;
959 return NVPTX::atomic_thread_fence_acquire_cluster;
961 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
962 : NVPTX::INT_MEMBAR_GL;
966 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
973 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
974 : NVPTX::INT_MEMBAR_SYS;
976 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
977 : NVPTX::INT_MEMBAR_CTA;
979 return NVPTX::atomic_thread_fence_release_cluster;
981 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
982 : NVPTX::INT_MEMBAR_GL;
986 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
993 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
994 : NVPTX::INT_MEMBAR_SYS;
996 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
997 : NVPTX::INT_MEMBAR_CTA;
999 return NVPTX::atomic_thread_fence_acq_rel_cluster;
1001 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
1002 : NVPTX::INT_MEMBAR_GL;
1006 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1014 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
1015 : NVPTX::INT_MEMBAR_SYS;
1017 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
1018 : NVPTX::INT_MEMBAR_CTA;
1020 return NVPTX::atomic_thread_fence_seq_cst_cluster;
1022 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
1023 : NVPTX::INT_MEMBAR_GL;
1036 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1037 OrderingToString(O), ScopeToString(S)));
1045std::pair<NVPTX::Ordering, NVPTX::Scope>
1046NVPTXDAGToDAGISel::insertMemoryInstructionFence(
SDLoc DL,
SDValue &Chain,
1049 getOperationOrderings(
N, Subtarget);
1067 Chain =
SDValue(CurDAG->getMachineNode(
Op,
DL, MVT::Other, Chain), 0);
1072 formatv(
"Unexpected fence ordering: \"{}\".",
1080static std::optional<unsigned>
1082 std::optional<unsigned> Opcode_i32,
1083 std::optional<unsigned> Opcode_i64) {
1102 return std::nullopt;
1107 return V.getOpcode() ==
ISD::ADD ||
1108 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
1113 N =
N.getOperand(0);
1123 GA->getValueType(0), GA->getOffset(),
1124 GA->getTargetFlags());
1127 ES->getTargetFlags());
1130 if (
N.getOpcode() == NVPTXISD::Symbol)
1131 return N.getOperand(0);
1138 APInt AccumulatedOffset(64u, 0);
1144 const APInt CI = CN->getAPIntValue().
sext(64);
1145 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1148 AccumulatedOffset += CI;
1205template <
typename T>
1208 std::optional<T> (*Parse)(
StringRef),
bool EmitDiagnostics) {
1211 if (EmitDiagnostics)
1213 Twine(
"'") +
Key +
"' expects a string value");
1214 return std::nullopt;
1218 auto Parsed = Parse(ValStr);
1219 if (!Parsed && EmitDiagnostics)
1231 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld ||
1232 Access.Instruction == NVPTXMemCacheHintInstruction::St;
1237 NVPTXMemCacheHintAccess
Access) {
1247 NVPTXMemCacheHintAccess
Access) {
1252 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1255 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1258 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1266 NVPTXMemCacheHintAccess
Access) {
1277 NVPTXMemCacheHintAccess
Access) {
1282NVPTXMemCacheHintOperands NVPTXDAGToDAGISel::getMemCacheHintOperands(
1284 bool EmitDiagnostics) {
1287 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1289 return {getI32Imm(0,
DL), PolicyReg};
1290 if (
Node->getNumOperands() == 0) {
1291 if (EmitDiagnostics)
1293 return {getI32Imm(0,
DL), PolicyReg};
1299 std::optional<uint64_t> CachePolicy;
1301 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1306 if (KeyStr ==
"nvvm.l1_eviction") {
1314 if (KeyStr ==
"nvvm.l2_eviction") {
1322 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1325 if (ParsedPrefetch &&
1331 if (KeyStr ==
"nvvm.l2_cache_hint") {
1334 if (EmitDiagnostics)
1336 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1338 CachePolicy = ValCI->getZExtValue();
1343 if (EmitDiagnostics)
1347 unsigned EvictionAndPrefetchHint =
1350 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1352 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1356 return {getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg};
1359bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1361 assert(
LD->readMem() &&
"Expected load");
1365 if (PlainLoad && PlainLoad->
isIndexed())
1369 const auto CodeAddrSpace = getAddrSpace(LD);
1375 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1377 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1385 uint32_t UsedBytesMask;
1386 switch (
N->getOpcode()) {
1389 UsedBytesMask = UINT32_MAX;
1392 UsedBytesMask =
N->getConstantOperandVal(3);
1399 FromTypeWidth <= 128 &&
"Invalid width for load");
1402 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1404 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1405 1, FromTypeWidth,
LD->isVolatile()},
1410 getI32Imm(Scope,
DL),
1411 getI32Imm(CodeAddrSpace,
DL),
1412 getI32Imm(FromType,
DL),
1413 getI32Imm(FromTypeWidth,
DL),
1414 getI32Imm(UsedBytesMask,
DL),
1417 EvictionAndPrefetchHint,
1422 const std::optional<unsigned> Opcode =
1423 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1427 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1434 ReplaceNode(LD, NVPTXLD);
1439 switch (
N->getOpcode()) {
1451bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1455 const auto CodeAddrSpace = getAddrSpace(LD);
1459 const MVT EltVT =
LD->getSimpleValueType(0);
1462 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1472 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1478 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1482 const auto [EvictionAndPrefetchHint, PolicyReg] =
1483 getMemCacheHintOperands(LD,
1484 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1485 LD->getNumValues() - 1,
1486 FromTypeWidth,
LD->isVolatile()},
1490 getI32Imm(Scope,
DL),
1491 getI32Imm(CodeAddrSpace,
DL),
1492 getI32Imm(FromType,
DL),
1493 getI32Imm(FromTypeWidth,
DL),
1494 getI32Imm(UsedBytesMask,
DL),
1497 EvictionAndPrefetchHint,
1501 std::optional<unsigned> Opcode;
1502 switch (
N->getOpcode()) {
1507 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1511 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1515 NVPTX::LDV_i32_v8, {});
1521 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1526 ReplaceNode(LD, NVPTXLD);
1530bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1533 unsigned ExtensionType;
1534 uint32_t UsedBytesMask;
1536 ExtensionType =
Load->getExtensionType();
1537 UsedBytesMask = UINT32_MAX;
1539 ExtensionType =
LD->getConstantOperandVal(4);
1540 UsedBytesMask =
LD->getConstantOperandVal(3);
1548 assert(!(
LD->getSimpleValueType(0).isVector() &&
1552 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1555 LD->getNumValues() - 1, FromTypeWidth,
LD->isVolatile()},
1558 getI32Imm(FromTypeWidth,
DL),
1559 getI32Imm(UsedBytesMask,
DL),
1562 EvictionAndPrefetchHint,
1567 std::optional<unsigned> Opcode;
1568 switch (
LD->getOpcode()) {
1573 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1576 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1577 NVPTX::LD_GLOBAL_NC_i64);
1582 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1587 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1591 NVPTX::LD_GLOBAL_NC_v8i32, {});
1597 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1599 ReplaceNode(LD, NVPTXLDG);
1603bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1618 std::optional<unsigned> Opcode;
1619 switch (
N->getOpcode()) {
1624 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1628 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1632 NVPTX::LDU_GLOBAL_v4i32, {});
1638 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1640 ReplaceNode(LD, NVPTXLDU);
1644bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1646 assert(
ST->writeMem() &&
"Expected store");
1649 assert((PlainStore || AtomicStore) &&
"Expected store");
1652 if (PlainStore && PlainStore->
isIndexed())
1656 const auto CodeAddrSpace = getAddrSpace(ST);
1660 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1663 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1669 "Invalid width for store");
1674 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1676 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1677 1, ToTypeWidth,
ST->isVolatile()},
1681 getI32Imm(Ordering,
DL),
1682 getI32Imm(Scope,
DL),
1683 getI32Imm(CodeAddrSpace,
DL),
1684 getI32Imm(ToTypeWidth,
DL),
1687 EvictionAndPrefetchHint,
1691 const std::optional<unsigned> Opcode =
1693 NVPTX::ST_i32, NVPTX::ST_i64);
1697 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1704 ReplaceNode(ST, NVPTXST);
1708bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1710 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1713 const auto CodeAddrSpace = getAddrSpace(ST);
1721 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1726 for (
auto &V :
ST->ops().slice(1, NumElts))
1729 const unsigned ToTypeWidth = TotalWidth / NumElts;
1732 TotalWidth <= 256 &&
"Invalid width for store");
1735 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1737 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1738 NumElts, ToTypeWidth,
ST->isVolatile()},
1742 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1743 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1744 Offset, EvictionAndPrefetchHint, PolicyReg, Chain});
1747 ST->getOperand(1).getSimpleValueType().SimpleTy;
1748 std::optional<unsigned> Opcode;
1749 switch (
ST->getOpcode()) {
1769 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1774 ReplaceNode(ST, NVPTXST);
1780bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1787 bool IsSigned =
false;
1813 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1817 Val =
LHS.getNode()->getOperand(0);
1818 Start =
LHS.getNode()->getOperand(1);
1824 int64_t GoodBits =
Start.getValueSizeInBits() - StartVal;
1825 if (NumBits > GoodBits) {
1831 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1883 NumBits = NumZeros + NumOnes - ShiftAmt;
1889 if (ShiftAmt < NumZeros) {
1896 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1897 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1913 Val =
LHS->getOperand(0);
1932 if (OuterShiftAmt < InnerShiftAmt) {
1943 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1968 Opc = NVPTX::BFE_S32rii;
1970 Opc = NVPTX::BFE_U32rii;
1974 Opc = NVPTX::BFE_S64rii;
1976 Opc = NVPTX::BFE_U64rii;
1987 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
1992bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
2014 auto API = APF.bitcastToAPInt();
2015 API = API.concat(API);
2016 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
2017 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
2020 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
2021 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
2024 switch (
N->getOpcode()) {
2027 Operands = {N0, GetConstant(1.0), N1};
2031 Operands = {N1, GetConstant(-1.0), N0};
2036 Operands = {N0, N1, GetConstant(-0.0)};
2042 int Opcode = IsVec ? NVPTX::FMA_BF16x2rrr : NVPTX::FMA_BF16rrr;
2044 ReplaceNode(
N, FMA);
2053 Src =
N.getOperand(0);
2054 else if (CurDAG->computeKnownFPClass(
N,
fcNegative).signBitIsZeroOrNaN())
2058 Src = selectPossiblyImm(Src);
2064 V =
V.getOperand(0);
2067 return CurDAG->getTargetConstant(CN->getAPIntValue(),
SDLoc(V),
2070 return CurDAG->getTargetConstantFP(CN->getValueAPF(),
SDLoc(V),
2077bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2079 std::vector<SDValue> &OutOps) {
2080 switch (ConstraintID) {
2085 OutOps.push_back(
Base);
2086 OutOps.push_back(
Offset);
2093void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
2109 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2112 NewOps[0] =
N->getOperand(0);
2115 if (
N->getNumOperands() == 5)
2116 NewOps[3] =
N->getOperand(4);
2119 ReplaceNode(
N, NewValue.
getNode());
2122void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
2139 SDNode *Mov = CurDAG->getMachineNode(
2140 NVPTX::I128toV2I64,
DL,
2144 ReplaceNode(
N, Mov);
2147bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
2157 CurDAG->RemoveDeadNode(
N);
2164 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2165 ReplaceNode(
N, FenceNode);
2183 "NVPTXScopes::operator[]");
2185 auto S = Scopes.find(ID);
2186 if (S == Scopes.end()) {
2187 auto scopeName =
Context->getSyncScopeName(ID);
2188 assert(scopeName.has_value() &&
"Scope name must exist.");
2192 for (
const auto &Entry : Scopes) {
2198 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2199 "Supported syncscopes are: {2}.",
2200 scopeName.value(),
int(ID),
2206bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2208#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2209 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2210 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2214 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2216 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2218 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2220 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2222 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2224 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2226 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2228 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2230 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2232 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2234 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2236 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2238 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2240 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2242 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2244 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2246 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2248 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2250 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2252 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2254 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2256 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2258 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2260 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2262 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2264 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2266 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2268 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2270 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2272 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2274 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2276 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2278 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2280 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2282 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2284 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2286 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2292void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2295 "tcgen05.st is not supported on this architecture variant");
2305 Operands.push_back(CurDAG->getTargetConstant(
2309 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2321bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2322 unsigned IID =
N->getConstantOperandVal(1);
2326 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2327 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2328 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2329 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2330 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2331 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2332 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2333 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2334 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2335 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2336 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2337 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2338 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2339 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2340 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2341 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2342 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2343 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2344 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2345 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2346 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2347 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2348 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2349 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2350 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2351 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2352 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2353 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2354 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2359 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2360 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2361 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2362 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2363 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2364 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2365 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2366 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2367 SelectTcgen05St(
N,
true);
2373void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2380 Ops.append(
N->op_begin() + 2,
N->op_end());
2381 Ops.append({getI32Imm(getMemOrder(AN), dl), getI32Imm(getAtomicScope(AN), dl),
2382 getI32Imm(getAddrSpace(AN), dl)});
2386 NVPTXMemCacheHintAccess
Access{NVPTXMemCacheHintInstruction::Atom,
2389 const auto [EvictionAndPrefetchHint, CachePolicyReg] =
2390 getMemCacheHintOperands(AN,
Access, dl);
2391 Ops.push_back(EvictionAndPrefetchHint);
2392 Ops.push_back(CachePolicyReg);
2395 Ops.push_back(Chain);
2400 ? NVPTX::ATOM_EXCH_B128
2401 : NVPTX::ATOM_CAS_B128;
2403 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2406 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 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 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)
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)
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...
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)
std::string OrderingToString(Ordering Order)
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.
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.