33#include "llvm/IR/IntrinsicsNVPTX.h"
46#define DEBUG_TYPE "nvptx-isel"
47#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
51 cl::desc(
"Enable reciprocal sqrt optimization"));
58 cl::desc(
"Enable MAD wide optimization"));
63 NVPTXScopes() =
default;
70 LLVMContext *Context =
nullptr;
73enum class NVPTXMemCacheHintInstruction { Ld, St, Atom };
75struct NVPTXMemCacheHintAccess {
76 NVPTXMemCacheHintInstruction Instruction;
77 NVPTX::AddressSpace AddrSpace;
83struct NVPTXMemCacheHintOperands {
84 SDValue EvictionAndPrefetchHint;
89 const NVPTXTargetMachine &TM;
91 NVPTX::DivPrecisionLevel getDivF32Level(
const SDNode *
N)
const;
92 bool usePrecSqrtF32(
const SDNode *
N)
const;
93 bool useF32FTZ()
const;
94 bool allowFMA()
const;
95 bool doRsqrtOpt()
const;
96 bool doMADWideOpt()
const;
101 NVPTXDAGToDAGISel() =
delete;
103 explicit NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
CodeGenOptLevel OptLevel);
106 const NVPTXSubtarget *Subtarget =
nullptr;
108 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
110 std::vector<SDValue> &OutOps)
override;
114#include "NVPTXGenDAGISel.inc"
116 void Select(SDNode *
N)
override;
117 bool tryIntrinsicChain(SDNode *
N);
118 bool tryIntrinsicVoid(SDNode *
N);
119 void SelectTexSurfHandle(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 tryConstantFP(SDNode *
N);
130 bool SelectSETP_F16X2(SDNode *
N);
131 bool SelectSETP_BF16X2(SDNode *
N);
132 bool tryUNPACK_VECTOR(SDNode *
N);
133 bool tryEXTRACT_VECTOR_ELEMENT(SDNode *
N);
134 void SelectV2I64toI128(SDNode *
N);
135 void SelectI128toV2I64(SDNode *
N);
136 void SelectCpAsyncBulkTensorReduceCommon(SDNode *
N,
unsigned RedOp,
137 bool IsIm2Col =
false);
138 void SelectTcgen05Ld(SDNode *
N,
bool hasOffset =
false);
139 void SelectTcgen05St(SDNode *
N,
bool hasOffset =
false);
140 void selectAtomicSwap128(SDNode *
N);
142 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
143 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
145 NVPTX::Ordering getMemOrder(
const MemSDNode *
N)
const;
146 NVPTX::Scope getAtomicScope(
const MemSDNode *
N)
const;
149 SDValue getPTXCmpMode(
const CondCodeSDNode &CondCode);
157 NVPTXMemCacheHintOperands
158 getMemCacheHintOperands(
const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
159 const SDLoc &
DL,
bool EmitDiagnostics =
true);
165 std::pair<NVPTX::Ordering, NVPTX::Scope>
166 insertMemoryInstructionFence(SDLoc
DL,
SDValue &Chain, MemSDNode *
N);
167 NVPTX::Scope getOperationScope(MemSDNode *
N, NVPTX::Ordering O)
const;
170 static NVPTX::AddressSpace getAddrSpace(
const MemSDNode *
N);
176 explicit NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm,
186 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
192 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
194char NVPTXDAGToDAGISelLegacy::ID = 0;
214NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
215 return Subtarget->getTargetLowering()->getDivF32Level(*MF, *
N);
218bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
219 return Subtarget->getTargetLowering()->usePrecSqrtF32(
N);
222bool NVPTXDAGToDAGISel::useF32FTZ()
const {
223 return Subtarget->getTargetLowering()->useF32FTZ(*MF);
226bool NVPTXDAGToDAGISel::allowFMA()
const {
231bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
233bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
237void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
239 if (
N->isMachineOpcode()) {
244 switch (
N->getOpcode()) {
264 if (tryEXTRACT_VECTOR_ELEMENT(
N))
271 SelectSETP_BF16X2(
N);
276 if (tryLoadVector(
N))
287 if (tryStoreVector(
N))
291 if (tryIntrinsicChain(
N))
295 if (tryIntrinsicVoid(
N))
306 if (
N->getOperand(1).getValueType() == MVT::i128) {
307 SelectV2I64toI128(
N);
313 if (
N->getOperand(1).getValueType() == MVT::i128) {
314 SelectI128toV2I64(
N);
321 selectAtomicSwap128(
N);
326 if (tryBF16ArithToFMA(
N))
335#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
336 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
337 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
341 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
343 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
345 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
347 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
349 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
351 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
353 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
355 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
357 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
359 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
361 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
363 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
365 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
367 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
369 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
371 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
373 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
375 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
377 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
379 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
381 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
383 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
385 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
387 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
389 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
391 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
393 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
395 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
397 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
399 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
401 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
403 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
405 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
407 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
409 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
411 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
413 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
419void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
420 if (!Subtarget->hasTcgen05InstSupport())
422 "tcgen05.ld is not supported on this architecture variant");
429 auto OffsetNode = CurDAG->getTargetConstant(
431 ReplaceNode(
N, CurDAG->getMachineNode(
433 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
436 ReplaceNode(
N, CurDAG->getMachineNode(
438 {N->getOperand(2), N->getOperand(0)}));
442bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
443 unsigned IID =
N->getConstantOperandVal(1);
447 case Intrinsic::nvvm_ldu_global_f:
448 case Intrinsic::nvvm_ldu_global_i:
449 case Intrinsic::nvvm_ldu_global_p:
452 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
453 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
454 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
455 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
456 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
457 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
458 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
459 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
460 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
461 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
462 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
463 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
464 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
465 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
466 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
467 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
468 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
469 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
470 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
471 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
472 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
473 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
474 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
475 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
476 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
477 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
478 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
479 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
480 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
485 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
486 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
487 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
488 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
489 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
490 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
491 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
492 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
493 SelectTcgen05Ld(
N,
true);
528 return CmpMode::NotANumber;
543 return CurDAG->getTargetConstant(PTXCmpMode,
SDLoc(), MVT::i32);
546bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
549 SDNode *SetP = CurDAG->getMachineNode(
550 NVPTX::SETP_f16x2rr,
DL, MVT::i1, MVT::i1,
551 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
552 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
553 ReplaceNode(
N, SetP);
557bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
561 CurDAG->getMachineNode(NVPTX::SETP_bf16x2rr,
DL, MVT::i1, MVT::i1,
562 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
563 ReplaceNode(
N, SetP);
567bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
569 MVT EltVT =
N->getSimpleValueType(0);
572 CurDAG->getMachineNode(NVPTX::I64toV2I32,
SDLoc(
N), EltVT, EltVT,
Vector);
580bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
589 Opcode = NVPTX::I32toV2I16;
591 Opcode = NVPTX::I64toV2I32;
597 for (
auto *U :
Vector.getNode()->users()) {
600 if (
U->getOperand(0) !=
Vector)
604 if (IdxConst->getZExtValue() == 0)
606 else if (IdxConst->getZExtValue() == 1)
622 CurDAG->getMachineNode(Opcode,
SDLoc(
N), EltVT, EltVT,
Vector);
623 for (
auto *Node : E0)
625 for (
auto *Node : E1)
650 if (!Subtarget->hasMemoryOrdering())
680 if (!Subtarget->hasAtomScope()) {
683 CurDAG->getMachineFunction().getFunction(),
684 "NVPTX system scope atomics require sm_60 or later",
693struct OperationOrderings {
694 NVPTX::Ordering InstructionOrdering, FenceOrdering;
695 OperationOrderings(NVPTX::Ordering IO = NVPTX::Ordering::NotAtomic,
696 NVPTX::Ordering FO = NVPTX::Ordering::NotAtomic)
697 : InstructionOrdering(IO), FenceOrdering(FO) {}
700static OperationOrderings
703 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
708 Subtarget->hasFeature(NVPTX::PTX91) &&
802 !IsSupportedLocalVolatile) ||
814 !HasMemoryOrdering) {
816 formatv(
"PTX does not support \"atomic\" for orderings different than"
817 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
827 bool AddrSupportsVolatileOrAtomic =
828 (IsSupportedLocalVolatile ||
833 if (!AddrSupportsVolatileOrAtomic)
836 bool UseRelaxedMMIO =
858 formatv(
"PTX only supports Acquire Ordering on reads: {}",
859 N->getOperationName()));
864 formatv(
"PTX only supports Release Ordering on writes: {}",
865 N->getOperationName()));
869 formatv(
"NVPTX does not support AcquireRelease Ordering on "
871 "yet and PTX does not support it on loads or stores: {}",
872 N->getOperationName()));
885 else if (
N->writeMem())
889 formatv(
"NVPTX does not support SequentiallyConsistent Ordering on "
890 "read-modify-writes yet: {}",
891 N->getOperationName()));
892 return OperationOrderings(InstrOrder,
897 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
920 auto S =
Scopes[
N->getSyncScopeID()];
943 if (!
T->hasSplitAcquireAndReleaseFences() &&
951 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
952 : NVPTX::INT_MEMBAR_SYS;
954 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
955 : NVPTX::INT_MEMBAR_CTA;
957 return NVPTX::atomic_thread_fence_acquire_cluster;
959 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
960 : NVPTX::INT_MEMBAR_GL;
964 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
971 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
972 : NVPTX::INT_MEMBAR_SYS;
974 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
975 : NVPTX::INT_MEMBAR_CTA;
977 return NVPTX::atomic_thread_fence_release_cluster;
979 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
980 : NVPTX::INT_MEMBAR_GL;
984 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
991 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
992 : NVPTX::INT_MEMBAR_SYS;
994 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
995 : NVPTX::INT_MEMBAR_CTA;
997 return NVPTX::atomic_thread_fence_acq_rel_cluster;
999 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
1000 : NVPTX::INT_MEMBAR_GL;
1004 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1012 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
1013 : NVPTX::INT_MEMBAR_SYS;
1015 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
1016 : NVPTX::INT_MEMBAR_CTA;
1018 return NVPTX::atomic_thread_fence_seq_cst_cluster;
1020 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
1021 : NVPTX::INT_MEMBAR_GL;
1034 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1035 OrderingToString(O), ScopeToString(S)));
1043std::pair<NVPTX::Ordering, NVPTX::Scope>
1044NVPTXDAGToDAGISel::insertMemoryInstructionFence(
SDLoc DL,
SDValue &Chain,
1047 getOperationOrderings(
N, Subtarget);
1065 Chain =
SDValue(CurDAG->getMachineNode(
Op,
DL, MVT::Other, Chain), 0);
1070 formatv(
"Unexpected fence ordering: \"{}\".",
1078static std::optional<unsigned>
1080 std::optional<unsigned> Opcode_i32,
1081 std::optional<unsigned> Opcode_i64) {
1100 return std::nullopt;
1105 return V.getOpcode() ==
ISD::ADD ||
1106 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
1111 N =
N.getOperand(0);
1121 GA->getValueType(0), GA->getOffset(),
1122 GA->getTargetFlags());
1125 ES->getTargetFlags());
1128 if (
N.getOpcode() == NVPTXISD::Symbol)
1129 return N.getOperand(0);
1136 APInt AccumulatedOffset(64u, 0);
1142 const APInt CI = CN->getAPIntValue().
sext(64);
1143 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1146 AccumulatedOffset += CI;
1203template <
typename T>
1206 std::optional<T> (*Parse)(
StringRef),
bool EmitDiagnostics) {
1209 if (EmitDiagnostics)
1211 Twine(
"'") +
Key +
"' expects a string value");
1212 return std::nullopt;
1216 auto Parsed = Parse(ValStr);
1217 if (!Parsed && EmitDiagnostics)
1229 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld ||
1230 Access.Instruction == NVPTXMemCacheHintInstruction::St;
1235 NVPTXMemCacheHintAccess
Access) {
1245 NVPTXMemCacheHintAccess
Access) {
1250 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1253 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1256 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1264 NVPTXMemCacheHintAccess
Access) {
1275 NVPTXMemCacheHintAccess
Access) {
1280NVPTXMemCacheHintOperands NVPTXDAGToDAGISel::getMemCacheHintOperands(
1282 bool EmitDiagnostics) {
1285 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1287 return {getI32Imm(0,
DL), PolicyReg};
1288 if (
Node->getNumOperands() == 0) {
1289 if (EmitDiagnostics)
1291 return {getI32Imm(0,
DL), PolicyReg};
1297 std::optional<uint64_t> CachePolicy;
1299 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1304 if (KeyStr ==
"nvvm.l1_eviction") {
1312 if (KeyStr ==
"nvvm.l2_eviction") {
1320 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1323 if (ParsedPrefetch &&
1329 if (KeyStr ==
"nvvm.l2_cache_hint") {
1332 if (EmitDiagnostics)
1334 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1336 CachePolicy = ValCI->getZExtValue();
1341 if (EmitDiagnostics)
1345 unsigned EvictionAndPrefetchHint =
1348 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1350 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1354 return {getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg};
1357bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1359 assert(
LD->readMem() &&
"Expected load");
1363 if (PlainLoad && PlainLoad->
isIndexed())
1367 const auto CodeAddrSpace = getAddrSpace(LD);
1373 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1375 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1383 uint32_t UsedBytesMask;
1384 switch (
N->getOpcode()) {
1387 UsedBytesMask = UINT32_MAX;
1390 UsedBytesMask =
N->getConstantOperandVal(3);
1397 FromTypeWidth <= 128 &&
"Invalid width for load");
1400 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1402 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1403 1, FromTypeWidth,
LD->isVolatile()},
1408 getI32Imm(Scope,
DL),
1409 getI32Imm(CodeAddrSpace,
DL),
1410 getI32Imm(FromType,
DL),
1411 getI32Imm(FromTypeWidth,
DL),
1412 getI32Imm(UsedBytesMask,
DL),
1415 EvictionAndPrefetchHint,
1420 const std::optional<unsigned> Opcode =
1421 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1425 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1432 ReplaceNode(LD, NVPTXLD);
1437 switch (
N->getOpcode()) {
1449bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1453 const auto CodeAddrSpace = getAddrSpace(LD);
1457 const MVT EltVT =
LD->getSimpleValueType(0);
1460 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1470 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1476 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1480 const auto [EvictionAndPrefetchHint, PolicyReg] =
1481 getMemCacheHintOperands(LD,
1482 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1483 LD->getNumValues() - 1,
1484 FromTypeWidth,
LD->isVolatile()},
1488 getI32Imm(Scope,
DL),
1489 getI32Imm(CodeAddrSpace,
DL),
1490 getI32Imm(FromType,
DL),
1491 getI32Imm(FromTypeWidth,
DL),
1492 getI32Imm(UsedBytesMask,
DL),
1495 EvictionAndPrefetchHint,
1499 std::optional<unsigned> Opcode;
1500 switch (
N->getOpcode()) {
1505 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1509 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1513 NVPTX::LDV_i32_v8, {});
1519 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1524 ReplaceNode(LD, NVPTXLD);
1528bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1531 unsigned ExtensionType;
1532 uint32_t UsedBytesMask;
1534 ExtensionType =
Load->getExtensionType();
1535 UsedBytesMask = UINT32_MAX;
1537 ExtensionType =
LD->getConstantOperandVal(4);
1538 UsedBytesMask =
LD->getConstantOperandVal(3);
1546 assert(!(
LD->getSimpleValueType(0).isVector() &&
1550 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1553 LD->getNumValues() - 1, FromTypeWidth,
LD->isVolatile()},
1556 getI32Imm(FromTypeWidth,
DL),
1557 getI32Imm(UsedBytesMask,
DL),
1560 EvictionAndPrefetchHint,
1565 std::optional<unsigned> Opcode;
1566 switch (
LD->getOpcode()) {
1571 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1574 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1575 NVPTX::LD_GLOBAL_NC_i64);
1580 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1585 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1589 NVPTX::LD_GLOBAL_NC_v8i32, {});
1595 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1597 ReplaceNode(LD, NVPTXLDG);
1601bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1616 std::optional<unsigned> Opcode;
1617 switch (
N->getOpcode()) {
1622 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1626 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1630 NVPTX::LDU_GLOBAL_v4i32, {});
1636 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1638 ReplaceNode(LD, NVPTXLDU);
1642bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1644 assert(
ST->writeMem() &&
"Expected store");
1647 assert((PlainStore || AtomicStore) &&
"Expected store");
1650 if (PlainStore && PlainStore->
isIndexed())
1654 const auto CodeAddrSpace = getAddrSpace(ST);
1658 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1661 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1667 "Invalid width for store");
1672 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1674 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1675 1, ToTypeWidth,
ST->isVolatile()},
1679 getI32Imm(Ordering,
DL),
1680 getI32Imm(Scope,
DL),
1681 getI32Imm(CodeAddrSpace,
DL),
1682 getI32Imm(ToTypeWidth,
DL),
1685 EvictionAndPrefetchHint,
1689 const std::optional<unsigned> Opcode =
1691 NVPTX::ST_i32, NVPTX::ST_i64);
1695 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1702 ReplaceNode(ST, NVPTXST);
1706bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1708 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1711 const auto CodeAddrSpace = getAddrSpace(ST);
1719 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1724 for (
auto &V :
ST->ops().slice(1, NumElts))
1727 const unsigned ToTypeWidth = TotalWidth / NumElts;
1730 TotalWidth <= 256 &&
"Invalid width for store");
1733 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1735 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1736 NumElts, ToTypeWidth,
ST->isVolatile()},
1740 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1741 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1742 Offset, EvictionAndPrefetchHint, PolicyReg, Chain});
1745 ST->getOperand(1).getSimpleValueType().SimpleTy;
1746 std::optional<unsigned> Opcode;
1747 switch (
ST->getOpcode()) {
1767 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1772 ReplaceNode(ST, NVPTXST);
1778bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1785 bool IsSigned =
false;
1811 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1815 Val =
LHS.getNode()->getOperand(0);
1816 Start =
LHS.getNode()->getOperand(1);
1822 int64_t GoodBits =
Start.getValueSizeInBits() - StartVal;
1823 if (NumBits > GoodBits) {
1829 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1881 NumBits = NumZeros + NumOnes - ShiftAmt;
1887 if (ShiftAmt < NumZeros) {
1894 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1895 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1911 Val =
LHS->getOperand(0);
1930 if (OuterShiftAmt < InnerShiftAmt) {
1941 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1966 Opc = NVPTX::BFE_S32rii;
1968 Opc = NVPTX::BFE_U32rii;
1972 Opc = NVPTX::BFE_S64rii;
1974 Opc = NVPTX::BFE_U64rii;
1985 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
1990bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
2012 auto API = APF.bitcastToAPInt();
2013 API = API.concat(API);
2014 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
2015 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
2018 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
2019 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
2022 switch (
N->getOpcode()) {
2025 Operands = {N0, GetConstant(1.0), N1};
2029 Operands = {N1, GetConstant(-1.0), N0};
2034 Operands = {N0, N1, GetConstant(-0.0)};
2040 int Opcode = IsVec ? NVPTX::FMA_BF16x2rrr : NVPTX::FMA_BF16rrr;
2042 ReplaceNode(
N, FMA);
2048 V =
V.getOperand(0);
2051 return CurDAG->getTargetConstant(CN->getAPIntValue(),
SDLoc(V),
2054 return CurDAG->getTargetConstantFP(CN->getValueAPF(),
SDLoc(V),
2061bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2063 std::vector<SDValue> &OutOps) {
2064 switch (ConstraintID) {
2069 OutOps.push_back(
Base);
2070 OutOps.push_back(
Offset);
2077void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
2093 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2096 NewOps[0] =
N->getOperand(0);
2099 if (
N->getNumOperands() == 5)
2100 NewOps[3] =
N->getOperand(4);
2103 ReplaceNode(
N, NewValue.
getNode());
2106void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
2123 SDNode *Mov = CurDAG->getMachineNode(
2124 NVPTX::I128toV2I64,
DL,
2128 ReplaceNode(
N, Mov);
2131bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
2140 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0),
N->getOperand(0));
2141 CurDAG->RemoveDeadNode(
N);
2148 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2149 ReplaceNode(
N, FenceNode);
2167 "NVPTXScopes::operator[]");
2169 auto S = Scopes.find(ID);
2170 if (S == Scopes.end()) {
2171 auto scopeName =
Context->getSyncScopeName(ID);
2172 assert(scopeName.has_value() &&
"Scope name must exist.");
2176 for (
const auto &Entry : Scopes) {
2182 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2183 "Supported syncscopes are: {2}.",
2184 scopeName.value(),
int(ID),
2190bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2192#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2193 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2194 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2198 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2200 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2202 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2204 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2206 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2208 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2210 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2212 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2214 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2216 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2218 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2220 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2222 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2224 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2226 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2228 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2230 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2232 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2234 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2236 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2238 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2240 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2242 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2244 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2246 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2248 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2250 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2252 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2254 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2256 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2258 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2260 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2262 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2264 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2266 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2268 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2270 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2276void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2279 "tcgen05.st is not supported on this architecture variant");
2289 Operands.push_back(CurDAG->getTargetConstant(
2293 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2305bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2306 unsigned IID =
N->getConstantOperandVal(1);
2310 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2311 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2312 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2313 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2314 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2315 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2316 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2317 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2318 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2319 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2320 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2321 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2322 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2323 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2324 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2325 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2326 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2327 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2328 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2329 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2330 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2331 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2332 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2333 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2334 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2335 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2336 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2337 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2338 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2343 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2344 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2345 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2346 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2347 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2348 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2349 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2350 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2351 SelectTcgen05St(
N,
true);
2357void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2364 Ops.append(
N->op_begin() + 2,
N->op_end());
2365 Ops.append({getI32Imm(getMemOrder(AN), dl), getI32Imm(getAtomicScope(AN), dl),
2366 getI32Imm(getAddrSpace(AN), dl)});
2370 NVPTXMemCacheHintAccess
Access{NVPTXMemCacheHintInstruction::Atom,
2373 const auto [EvictionAndPrefetchHint, CachePolicyReg] =
2374 getMemCacheHintOperands(AN,
Access, dl);
2375 Ops.push_back(EvictionAndPrefetchHint);
2376 Ops.push_back(CachePolicyReg);
2379 Ops.push_back(Chain);
2384 ? NVPTX::ATOM_EXCH_B128
2385 : NVPTX::ATOM_CAS_B128;
2387 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2390 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.