34#include "llvm/IR/IntrinsicsNVPTX.h"
48#define DEBUG_TYPE "nvptx-isel"
49#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
53 cl::desc(
"Enable reciprocal sqrt optimization"));
60 cl::desc(
"Enable MAD wide optimization"));
65 NVPTXScopes() =
default;
72 LLVMContext *Context =
nullptr;
75struct NVPTXMemCacheHintAccess {
76 NVPTX::AddressSpace AddrSpace;
84 const NVPTXTargetMachine &TM;
86 NVPTX::DivPrecisionLevel getDivF32Level(
const SDNode *
N)
const;
87 bool usePrecSqrtF32(
const SDNode *
N)
const;
88 bool useF32FTZ()
const;
89 bool allowFMA()
const;
90 bool doRsqrtOpt()
const;
91 bool doMADWideOpt()
const;
96 NVPTXDAGToDAGISel() =
delete;
98 explicit NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
CodeGenOptLevel OptLevel);
101 const NVPTXSubtarget *Subtarget =
nullptr;
103 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
105 std::vector<SDValue> &OutOps)
override;
109#include "NVPTXGenDAGISel.inc"
111 void Select(SDNode *
N)
override;
112 bool tryIntrinsicChain(SDNode *
N);
113 bool tryIntrinsicVoid(SDNode *
N);
114 void SelectTexSurfHandle(SDNode *
N);
115 bool tryLoad(SDNode *
N);
116 bool tryLoadVector(SDNode *
N);
117 bool tryLDU(SDNode *
N);
118 bool tryLDG(MemSDNode *
N);
119 bool tryStore(SDNode *
N);
120 bool tryStoreVector(SDNode *
N);
121 bool tryFence(SDNode *
N);
122 bool tryBFE(SDNode *
N);
123 bool tryBF16ArithToFMA(SDNode *
N);
124 bool tryConstantFP(SDNode *
N);
125 bool SelectSETP_F16X2(SDNode *
N);
126 bool SelectSETP_BF16X2(SDNode *
N);
127 bool tryUNPACK_VECTOR(SDNode *
N);
128 bool tryEXTRACT_VECTOR_ELEMENT(SDNode *
N);
129 void SelectV2I64toI128(SDNode *
N);
130 void SelectI128toV2I64(SDNode *
N);
131 void SelectCpAsyncBulkTensorReduceCommon(SDNode *
N,
unsigned RedOp,
132 bool IsIm2Col =
false);
133 void SelectTcgen05Ld(SDNode *
N,
bool hasOffset =
false);
134 void SelectTcgen05St(SDNode *
N,
bool hasOffset =
false);
135 void selectAtomicSwap128(SDNode *
N);
137 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
138 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
140 NVPTX::Ordering getMemOrder(
const MemSDNode *
N)
const;
141 NVPTX::Scope getAtomicScope(
const MemSDNode *
N)
const;
144 SDValue getPTXCmpMode(
const CondCodeSDNode &CondCode);
152 std::pair<unsigned, SDValue>
153 getMemCacheHintOperands(
const MemSDNode *
N, NVPTXMemCacheHintAccess
Access,
160 std::pair<NVPTX::Ordering, NVPTX::Scope>
161 insertMemoryInstructionFence(SDLoc
DL,
SDValue &Chain, MemSDNode *
N);
162 NVPTX::Scope getOperationScope(MemSDNode *
N, NVPTX::Ordering O)
const;
165 static NVPTX::AddressSpace getAddrSpace(
const MemSDNode *
N);
171 explicit NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm,
181 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
187 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
189char NVPTXDAGToDAGISelLegacy::ID = 0;
209NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
210 return Subtarget->getTargetLowering()->getDivF32Level(*MF, *
N);
213bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
214 return Subtarget->getTargetLowering()->usePrecSqrtF32(
N);
217bool NVPTXDAGToDAGISel::useF32FTZ()
const {
218 return Subtarget->getTargetLowering()->useF32FTZ(*MF);
221bool NVPTXDAGToDAGISel::allowFMA()
const {
226bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
228bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
232void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
234 if (
N->isMachineOpcode()) {
239 switch (
N->getOpcode()) {
259 if (tryEXTRACT_VECTOR_ELEMENT(
N))
266 SelectSETP_BF16X2(
N);
271 if (tryLoadVector(
N))
282 if (tryStoreVector(
N))
286 if (tryIntrinsicChain(
N))
290 if (tryIntrinsicVoid(
N))
301 if (
N->getOperand(1).getValueType() == MVT::i128) {
302 SelectV2I64toI128(
N);
308 if (
N->getOperand(1).getValueType() == MVT::i128) {
309 SelectI128toV2I64(
N);
316 selectAtomicSwap128(
N);
321 if (tryBF16ArithToFMA(
N))
330#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
331 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
332 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
336 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
338 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
340 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
342 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
344 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
346 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
348 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
350 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
352 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
354 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
356 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
358 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
360 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
362 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
364 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
366 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
368 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
370 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
372 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
374 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
376 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
378 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
380 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
382 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
384 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
386 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
388 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
390 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
392 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
394 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
396 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
398 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
400 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
402 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
404 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
406 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
408 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
414void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
415 if (!Subtarget->hasTcgen05InstSupport())
417 "tcgen05.ld is not supported on this architecture variant");
424 auto OffsetNode = CurDAG->getTargetConstant(
426 ReplaceNode(
N, CurDAG->getMachineNode(
428 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
431 ReplaceNode(
N, CurDAG->getMachineNode(
433 {N->getOperand(2), N->getOperand(0)}));
437bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
438 unsigned IID =
N->getConstantOperandVal(1);
442 case Intrinsic::nvvm_ldu_global_f:
443 case Intrinsic::nvvm_ldu_global_i:
444 case Intrinsic::nvvm_ldu_global_p:
447 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
448 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
449 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
450 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
451 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
452 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
453 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
454 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
455 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
456 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
457 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
458 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
459 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
460 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
461 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
462 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
463 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
464 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
465 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
466 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
467 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
468 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
469 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
470 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
471 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
472 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
473 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
474 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
475 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
480 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
481 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
482 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
483 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
484 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
485 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
486 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
487 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
488 SelectTcgen05Ld(
N,
true);
523 return CmpMode::NotANumber;
538 return CurDAG->getTargetConstant(PTXCmpMode,
SDLoc(), MVT::i32);
541bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
544 SDNode *SetP = CurDAG->getMachineNode(
545 NVPTX::SETP_f16x2rr,
DL, MVT::i1, MVT::i1,
546 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
547 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
548 ReplaceNode(
N, SetP);
552bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
556 CurDAG->getMachineNode(NVPTX::SETP_bf16x2rr,
DL, MVT::i1, MVT::i1,
557 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
558 ReplaceNode(
N, SetP);
562bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
564 MVT EltVT =
N->getSimpleValueType(0);
567 CurDAG->getMachineNode(NVPTX::I64toV2I32,
SDLoc(
N), EltVT, EltVT,
Vector);
575bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
584 Opcode = NVPTX::I32toV2I16;
586 Opcode = NVPTX::I64toV2I32;
592 for (
auto *U :
Vector.getNode()->users()) {
595 if (
U->getOperand(0) !=
Vector)
599 if (IdxConst->getZExtValue() == 0)
601 else if (IdxConst->getZExtValue() == 1)
617 CurDAG->getMachineNode(Opcode,
SDLoc(
N), EltVT, EltVT,
Vector);
618 for (
auto *Node : E0)
620 for (
auto *Node : E1)
645 if (!Subtarget->hasMemoryOrdering())
674 if (!Subtarget->hasAtomScope())
681struct OperationOrderings {
682 NVPTX::Ordering InstructionOrdering, FenceOrdering;
683 OperationOrderings(NVPTX::Ordering IO = NVPTX::Ordering::NotAtomic,
684 NVPTX::Ordering FO = NVPTX::Ordering::NotAtomic)
685 : InstructionOrdering(IO), FenceOrdering(FO) {}
688static OperationOrderings
691 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
791 !HasMemoryOrdering) {
793 formatv(
"PTX does not support \"atomic\" for orderings different than"
794 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
806 bool AddrGenericOrGlobalOrShared =
811 if (!AddrGenericOrGlobalOrShared)
814 bool UseRelaxedMMIO =
836 formatv(
"PTX only supports Acquire Ordering on reads: {}",
837 N->getOperationName()));
842 formatv(
"PTX only supports Release Ordering on writes: {}",
843 N->getOperationName()));
847 formatv(
"NVPTX does not support AcquireRelease Ordering on "
849 "yet and PTX does not support it on loads or stores: {}",
850 N->getOperationName()));
863 else if (
N->writeMem())
867 formatv(
"NVPTX does not support SequentiallyConsistent Ordering on "
868 "read-modify-writes yet: {}",
869 N->getOperationName()));
870 return OperationOrderings(InstrOrder,
875 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
898 auto S =
Scopes[
N->getSyncScopeID()];
921 if (!
T->hasSplitAcquireAndReleaseFences() &&
929 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
930 : NVPTX::INT_MEMBAR_SYS;
932 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
933 : NVPTX::INT_MEMBAR_CTA;
935 return NVPTX::atomic_thread_fence_acquire_cluster;
937 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
938 : NVPTX::INT_MEMBAR_GL;
942 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
949 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
950 : NVPTX::INT_MEMBAR_SYS;
952 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
953 : NVPTX::INT_MEMBAR_CTA;
955 return NVPTX::atomic_thread_fence_release_cluster;
957 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
958 : NVPTX::INT_MEMBAR_GL;
962 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
969 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
970 : NVPTX::INT_MEMBAR_SYS;
972 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
973 : NVPTX::INT_MEMBAR_CTA;
975 return NVPTX::atomic_thread_fence_acq_rel_cluster;
977 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
978 : NVPTX::INT_MEMBAR_GL;
982 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
990 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
991 : NVPTX::INT_MEMBAR_SYS;
993 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
994 : NVPTX::INT_MEMBAR_CTA;
996 return NVPTX::atomic_thread_fence_seq_cst_cluster;
998 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
999 : NVPTX::INT_MEMBAR_GL;
1012 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1013 OrderingToString(O), ScopeToString(S)));
1021std::pair<NVPTX::Ordering, NVPTX::Scope>
1022NVPTXDAGToDAGISel::insertMemoryInstructionFence(
SDLoc DL,
SDValue &Chain,
1025 getOperationOrderings(
N, Subtarget);
1043 Chain =
SDValue(CurDAG->getMachineNode(
Op,
DL, MVT::Other, Chain), 0);
1048 formatv(
"Unexpected fence ordering: \"{}\".",
1056static std::optional<unsigned>
1058 std::optional<unsigned> Opcode_i32,
1059 std::optional<unsigned> Opcode_i64) {
1078 return std::nullopt;
1083 return V.getOpcode() ==
ISD::ADD ||
1084 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
1089 N =
N.getOperand(0);
1099 GA->getValueType(0), GA->getOffset(),
1100 GA->getTargetFlags());
1103 ES->getTargetFlags());
1112 APInt AccumulatedOffset(64u, 0);
1118 const APInt CI = CN->getAPIntValue().
sext(64);
1119 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1122 AccumulatedOffset += CI;
1179template <
typename T>
1180static std::optional<T>
1187 return std::nullopt;
1191 auto Parsed = Parse(ValStr);
1205 NVPTXMemCacheHintAccess
Access) {
1224 NVPTXMemCacheHintAccess
Access) {
1234std::pair<unsigned, SDValue> NVPTXDAGToDAGISel::getMemCacheHintOperands(
1238 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1240 return {0, PolicyReg};
1241 if (
Node->getNumOperands() == 0) {
1243 return {0, PolicyReg};
1249 std::optional<uint64_t> CachePolicy;
1251 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1256 if (KeyStr ==
"nvvm.l1_eviction") {
1264 if (KeyStr ==
"nvvm.l2_eviction") {
1272 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1273 auto ParsedPrefetch =
1275 if (ParsedPrefetch &&
1281 if (KeyStr ==
"nvvm.l2_cache_hint") {
1285 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1288 CachePolicy = ValCI->getZExtValue();
1295 unsigned EvictionAndPrefetchHint =
1298 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1300 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1304 return {EvictionAndPrefetchHint, PolicyReg};
1307bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1309 assert(
LD->readMem() &&
"Expected load");
1313 if (PlainLoad && PlainLoad->
isIndexed())
1317 const auto CodeAddrSpace = getAddrSpace(LD);
1323 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1325 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1333 uint32_t UsedBytesMask;
1334 switch (
N->getOpcode()) {
1337 UsedBytesMask = UINT32_MAX;
1340 UsedBytesMask =
N->getConstantOperandVal(3);
1347 FromTypeWidth <= 128 &&
"Invalid width for load");
1350 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1352 {CodeAddrSpace,
true,
1353 1, FromTypeWidth,
LD->isVolatile()},
1358 getI32Imm(Scope,
DL),
1359 getI32Imm(CodeAddrSpace,
DL),
1360 getI32Imm(FromType,
DL),
1361 getI32Imm(FromTypeWidth,
DL),
1362 getI32Imm(UsedBytesMask,
DL),
1365 getI32Imm(EvictionAndPrefetchHint,
DL),
1370 const std::optional<unsigned> Opcode =
1371 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1375 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1382 ReplaceNode(LD, NVPTXLD);
1387 switch (
N->getOpcode()) {
1399bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1403 const auto CodeAddrSpace = getAddrSpace(LD);
1407 const MVT EltVT =
LD->getSimpleValueType(0);
1410 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1420 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1426 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1430 const auto [EvictionAndPrefetchHint, PolicyReg] =
1431 getMemCacheHintOperands(LD,
1432 {CodeAddrSpace,
true,
1433 LD->getNumValues() - 1,
1434 FromTypeWidth,
LD->isVolatile()},
1438 getI32Imm(Scope,
DL),
1439 getI32Imm(CodeAddrSpace,
DL),
1440 getI32Imm(FromType,
DL),
1441 getI32Imm(FromTypeWidth,
DL),
1442 getI32Imm(UsedBytesMask,
DL),
1445 getI32Imm(EvictionAndPrefetchHint,
DL),
1449 std::optional<unsigned> Opcode;
1450 switch (
N->getOpcode()) {
1455 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1459 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1463 NVPTX::LDV_i32_v8, {});
1469 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1474 ReplaceNode(LD, NVPTXLD);
1478bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1481 unsigned ExtensionType;
1482 uint32_t UsedBytesMask;
1484 ExtensionType =
Load->getExtensionType();
1485 UsedBytesMask = UINT32_MAX;
1487 ExtensionType =
LD->getConstantOperandVal(4);
1488 UsedBytesMask =
LD->getConstantOperandVal(3);
1496 assert(!(
LD->getSimpleValueType(0).isVector() &&
1500 const auto [EvictionAndPrefetchHint, PolicyReg] =
1501 getMemCacheHintOperands(LD,
1503 true,
LD->getNumValues() - 1,
1504 FromTypeWidth,
LD->isVolatile()},
1507 getI32Imm(FromTypeWidth,
DL),
1508 getI32Imm(UsedBytesMask,
DL),
1511 getI32Imm(EvictionAndPrefetchHint,
DL),
1516 std::optional<unsigned> Opcode;
1517 switch (
LD->getOpcode()) {
1522 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1525 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1526 NVPTX::LD_GLOBAL_NC_i64);
1531 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1536 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1540 NVPTX::LD_GLOBAL_NC_v8i32, {});
1546 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1548 ReplaceNode(LD, NVPTXLDG);
1552bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1567 std::optional<unsigned> Opcode;
1568 switch (
N->getOpcode()) {
1573 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1577 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1581 NVPTX::LDU_GLOBAL_v4i32, {});
1587 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1589 ReplaceNode(LD, NVPTXLDU);
1593bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1595 assert(
ST->writeMem() &&
"Expected store");
1598 assert((PlainStore || AtomicStore) &&
"Expected store");
1601 if (PlainStore && PlainStore->
isIndexed())
1605 const auto CodeAddrSpace = getAddrSpace(ST);
1609 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1612 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1618 "Invalid width for store");
1623 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1625 {CodeAddrSpace,
false,
1626 1, ToTypeWidth,
ST->isVolatile()},
1630 getI32Imm(Ordering,
DL),
1631 getI32Imm(Scope,
DL),
1632 getI32Imm(CodeAddrSpace,
DL),
1633 getI32Imm(ToTypeWidth,
DL),
1636 getI32Imm(EvictionAndPrefetchHint,
DL),
1640 const std::optional<unsigned> Opcode =
1642 NVPTX::ST_i32, NVPTX::ST_i64);
1646 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1653 ReplaceNode(ST, NVPTXST);
1657bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1659 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1662 const auto CodeAddrSpace = getAddrSpace(ST);
1670 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1675 for (
auto &V :
ST->ops().slice(1, NumElts))
1678 const unsigned ToTypeWidth = TotalWidth / NumElts;
1681 TotalWidth <= 256 &&
"Invalid width for store");
1684 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1686 {CodeAddrSpace,
false, NumElts,
1687 ToTypeWidth,
ST->isVolatile()},
1691 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1692 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1693 Offset, getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg,
1697 ST->getOperand(1).getSimpleValueType().SimpleTy;
1698 std::optional<unsigned> Opcode;
1699 switch (
ST->getOpcode()) {
1719 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1724 ReplaceNode(ST, NVPTXST);
1730bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1737 bool IsSigned =
false;
1753 uint64_t MaskVal =
Mask->getZExtValue();
1763 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1767 Val =
LHS.getNode()->getOperand(0);
1768 Start =
LHS.getNode()->getOperand(1);
1774 int64_t GoodBits =
Start.getValueSizeInBits() - StartVal;
1775 if (NumBits > GoodBits) {
1781 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1833 NumBits = NumZeros + NumOnes - ShiftAmt;
1839 if (ShiftAmt < NumZeros) {
1846 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1847 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1863 Val =
LHS->getOperand(0);
1882 if (OuterShiftAmt < InnerShiftAmt) {
1893 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1918 Opc = NVPTX::BFE_S32rii;
1920 Opc = NVPTX::BFE_U32rii;
1924 Opc = NVPTX::BFE_S64rii;
1926 Opc = NVPTX::BFE_U64rii;
1937 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
1942bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
1964 auto API = APF.bitcastToAPInt();
1965 API = API.concat(API);
1966 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
1967 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
1970 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
1971 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
1974 switch (
N->getOpcode()) {
1977 Operands = {N0, GetConstant(1.0), N1};
1981 Operands = {N1, GetConstant(-1.0), N0};
1986 Operands = {N0, N1, GetConstant(-0.0)};
1992 int Opcode = IsVec ? NVPTX::FMA_BF16x2rrr : NVPTX::FMA_BF16rrr;
1994 ReplaceNode(
N, FMA);
2000 V =
V.getOperand(0);
2003 return CurDAG->getTargetConstant(CN->getAPIntValue(),
SDLoc(V),
2006 return CurDAG->getTargetConstantFP(CN->getValueAPF(),
SDLoc(V),
2013bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2015 std::vector<SDValue> &OutOps) {
2016 switch (ConstraintID) {
2021 OutOps.push_back(
Base);
2022 OutOps.push_back(
Offset);
2029void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
2045 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2048 NewOps[0] =
N->getOperand(0);
2051 if (
N->getNumOperands() == 5)
2052 NewOps[3] =
N->getOperand(4);
2055 ReplaceNode(
N, NewValue.
getNode());
2058void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
2075 SDNode *Mov = CurDAG->getMachineNode(
2076 NVPTX::I128toV2I64,
DL,
2080 ReplaceNode(
N, Mov);
2083bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
2092 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0),
N->getOperand(0));
2093 CurDAG->RemoveDeadNode(
N);
2100 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2101 ReplaceNode(
N, FenceNode);
2119 "NVPTXScopes::operator[]");
2121 auto S = Scopes.find(ID);
2122 if (S == Scopes.end()) {
2123 auto scopeName =
Context->getSyncScopeName(ID);
2124 assert(scopeName.has_value() &&
"Scope name must exist.");
2128 for (
const auto &Entry : Scopes) {
2134 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2135 "Supported syncscopes are: {2}.",
2136 scopeName.value(),
int(ID),
2142bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2144#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2145 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2146 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2150 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2152 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2154 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2156 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2158 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2160 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2162 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2164 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2166 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2168 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2170 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2172 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2174 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2176 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2178 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2180 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2182 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2184 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2186 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2188 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2190 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2192 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2194 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2196 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2198 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2200 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2202 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2204 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2206 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2208 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2210 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2212 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2214 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2216 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2218 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2220 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2222 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2228void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2231 "tcgen05.st is not supported on this architecture variant");
2241 Operands.push_back(CurDAG->getTargetConstant(
2245 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2257bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2258 unsigned IID =
N->getConstantOperandVal(1);
2262 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2263 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2264 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2265 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2266 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2267 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2268 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2269 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2270 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2271 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2272 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2273 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2274 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2275 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2276 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2277 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2278 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2279 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2280 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2281 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2282 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2283 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2284 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2285 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2286 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2287 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2288 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2289 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2290 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2295 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2296 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2297 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2298 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2299 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2300 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2301 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2302 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2303 SelectTcgen05St(
N,
true);
2309void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2316 Ops.append(
N->op_begin() + 2,
N->op_end());
2318 getI32Imm(getMemOrder(AN), dl),
2319 getI32Imm(getAtomicScope(AN), dl),
2320 getI32Imm(getAddrSpace(AN), dl),
2327 ? NVPTX::ATOM_EXCH_B128
2328 : NVPTX::ATOM_CAS_B128;
2330 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2333 ReplaceNode(
N, ATOM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
loop data Loop Data Prefetch
This file implements a map that provides insertion order iteration.
static NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
static std::optional< T > parseMemCacheHintStringValue(LLVMContext &Ctx, StringRef Key, const Metadata *Value, std::optional< T >(*Parse)(StringRef))
static unsigned getStoreVectorNumElts(SDNode *N)
static bool isAddLike(const SDValue V)
static std::optional< NVPTX::L2Eviction > parseL2Eviction(StringRef Str)
static SDValue selectBaseADDR(SDValue N, SelectionDAG *DAG)
static std::optional< NVPTX::L2Prefetch > parseL2Prefetch(StringRef Str)
static std::optional< NVPTX::L1Eviction > parseL1Eviction(StringRef Str)
static SDValue accumulateOffset(SDValue &Addr, SDLoc DL, SelectionDAG *DAG)
static bool isGlobalOrGeneric(NVPTX::AddressSpace AddrSpace)
static bool isL2PrefetchSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Prefetch Prefetch, NVPTXMemCacheHintAccess Access)
static unsigned getTcgen05StOpcode(unsigned IID, bool enableUnpack)
static std::optional< unsigned > pickOpcodeForVT(MVT::SimpleValueType VT, std::optional< unsigned > Opcode_i16, std::optional< unsigned > Opcode_i32, std::optional< unsigned > Opcode_i64)
static cl::opt< bool > EnableMADWide("nvptx-mad-wide-opt", cl::init(false), cl::Hidden, cl::desc("Enable MAD wide optimization"))
#define TCGEN05_LD_OPCODE(SHAPE, NUM)
static SDValue stripAssertAlign(SDValue N)
static cl::opt< bool > EnableRsqrtOpt("nvptx-rsqrt-approx-opt", cl::init(true), cl::Hidden, cl::desc("Enable reciprocal sqrt optimization"))
static void emitInvalidMemCacheHint(LLVMContext &Ctx, const Twine &Msg)
static unsigned int getFenceOp(NVPTX::Ordering O, NVPTX::Scope S, NVPTXSubtarget const *T)
static bool isL2EvictionSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Eviction Eviction, NVPTXMemCacheHintAccess Access)
#define TCGEN05_ST_OPCODE(SHAPE, NUM)
static std::pair< SDValue, SDValue > selectADDR(SDValue Addr, SelectionDAG *DAG)
static unsigned getTcgen05LdOpcode(unsigned IID, bool enablePack)
static bool canLowerToLDG(const MemSDNode &N, const NVPTXSubtarget &Subtarget, NVPTX::AddressSpace CodeAddrSpace)
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics,...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
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
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.
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.
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.