33#include "llvm/IR/IntrinsicsNVPTX.h"
46#define DEBUG_TYPE "nvptx-isel"
47#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
52 NVPTXScopes() =
default;
62enum class NVPTXMemCacheHintInstruction { Ld, St, Atom };
64struct NVPTXMemCacheHintAccess {
72struct NVPTXMemCacheHintOperands {
73 SDValue EvictionAndPrefetchHint;
81 bool usePrecSqrtF32(
const SDNode *
N)
const;
82 bool useF32FTZ()
const;
83 bool useF16FTZ()
const;
84 bool allowFMA()
const;
85 bool doRsqrtOpt()
const;
86 bool doMADWideOpt()
const;
91 NVPTXDAGToDAGISel() =
delete;
98 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
100 std::vector<SDValue> &OutOps)
override;
104#include "NVPTXGenDAGISel.inc"
107 bool tryIntrinsicChain(
SDNode *
N);
108 bool tryIntrinsicVoid(
SDNode *
N);
114 bool tryStoreVector(
SDNode *
N);
117 bool tryBF16ArithToFMA(
SDNode *
N);
118 bool SelectSETP_F16X2(
SDNode *
N);
119 bool SelectSETP_BF16X2(
SDNode *
N);
120 bool tryUNPACK_VECTOR(
SDNode *
N);
121 bool tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N);
122 void PostprocessISelDAG()
override;
123 void SelectV2I64toI128(
SDNode *
N);
124 void SelectI128toV2I64(
SDNode *
N);
125 void SelectTcgen05Ld(
SDNode *
N,
bool hasOffset =
false);
126 void SelectTcgen05St(
SDNode *
N,
bool hasOffset =
false);
127 void selectAtomicSwap128(
SDNode *
N);
130 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
145 NVPTXMemCacheHintOperands
147 const SDLoc &
DL,
bool EmitDiagnostics =
true);
151 std::pair<NVPTX::Ordering, NVPTX::Scope>
173 return new NVPTXDAGToDAGISelLegacy(TM, OptLevel);
179 ID,
std::make_unique<NVPTXDAGToDAGISel>(tm, OptLevel)) {}
181char NVPTXDAGToDAGISelLegacy::ID = 0;
201NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
205bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
209bool NVPTXDAGToDAGISel::useF16FTZ()
const {
213bool NVPTXDAGToDAGISel::useF32FTZ()
const {
217bool NVPTXDAGToDAGISel::allowFMA()
const {
222bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
226bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
232void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
234 if (
N->isMachineOpcode()) {
239 switch (
N->getOpcode()) {
261 if (tryEXTRACT_VECTOR_ELEMENT(
N))
268 SelectSETP_BF16X2(
N);
273 if (tryLoadVector(
N))
284 if (tryStoreVector(
N))
288 if (tryIntrinsicChain(
N))
292 if (tryIntrinsicVoid(
N))
303 if (
N->getOperand(1).getValueType() == MVT::i128) {
304 SelectV2I64toI128(
N);
310 if (
N->getOperand(1).getValueType() == MVT::i128) {
311 SelectI128toV2I64(
N);
318 selectAtomicSwap128(
N);
323 if (tryBF16ArithToFMA(
N))
332#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
333 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
334 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
338 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
340 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
342 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
344 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
346 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
348 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
350 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
352 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
354 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
356 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
358 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
360 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
362 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
364 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
366 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
368 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
370 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
372 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
374 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
376 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
378 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
380 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
382 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
384 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
386 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
388 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
390 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
392 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
394 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
396 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
398 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
400 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
402 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
404 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
406 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
408 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
410 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
416void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
419 "tcgen05.ld is not supported on this architecture variant");
426 auto OffsetNode = CurDAG->getTargetConstant(
428 ReplaceNode(
N, CurDAG->getMachineNode(
430 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
433 ReplaceNode(
N, CurDAG->getMachineNode(
435 {N->getOperand(2), N->getOperand(0)}));
439bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
440 unsigned IID =
N->getConstantOperandVal(1);
444 case Intrinsic::nvvm_ldu_global_f:
445 case Intrinsic::nvvm_ldu_global_i:
446 case Intrinsic::nvvm_ldu_global_p:
449 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
450 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
451 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
452 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
453 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
454 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
455 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
456 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
457 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
458 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
459 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
460 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
461 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
462 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
463 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
464 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
465 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
466 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
467 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
468 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
469 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
470 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
471 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
472 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
473 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
474 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
475 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
476 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
477 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
482 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
483 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
484 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
485 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
486 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
487 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
488 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
489 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
490 SelectTcgen05Ld(
N,
true);
525 return CmpMode::NotANumber;
540 return CurDAG->getTargetConstant(PTXCmpMode,
SDLoc(), MVT::i32);
543bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
546 SDNode *SetP = CurDAG->getMachineNode(
547 NVPTX::SETP_f16x2,
DL, MVT::i1, MVT::i1,
548 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
549 CurDAG->getTargetConstant(useF16FTZ(),
DL, MVT::i1)});
550 ReplaceNode(
N, SetP);
554bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
558 CurDAG->getMachineNode(NVPTX::SETP_bf16x2,
DL, MVT::i1, MVT::i1,
559 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
560 ReplaceNode(
N, SetP);
564bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
566 MVT EltVT =
N->getSimpleValueType(0);
569 CurDAG->getMachineNode(NVPTX::I64toV2I32,
SDLoc(
N), EltVT, EltVT,
Vector);
577bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
586 Opcode = NVPTX::I32toV2I16;
588 Opcode = NVPTX::I64toV2I32;
594 for (
auto *U :
Vector.getNode()->users()) {
597 if (
U->getOperand(0) !=
Vector)
601 if (IdxConst->getZExtValue() == 0)
603 else if (IdxConst->getZExtValue() == 1)
619 CurDAG->getMachineNode(Opcode,
SDLoc(
N), EltVT, EltVT,
Vector);
620 for (
auto *Node : E0)
622 for (
auto *Node : E1)
629 if (!
N->isMachineOpcode() ||
N->use_empty())
631 switch (
N->getMachineOpcode()) {
634 case NVPTX::CVT_u16_u32:
638 case NVPTX::I32toI16L:
639 case NVPTX::I32toI16L_Sink:
641 case NVPTX::I32toI16H:
642 case NVPTX::I32toI16H_Sink:
670 if (Halves[0].empty() || Halves[1].empty())
675 for (
unsigned Index : {0u, 1u})
684void NVPTXDAGToDAGISel::PostprocessISelDAG() {
mergeI16Unpacks(*CurDAG); }
738 CurDAG->getMachineFunction().getFunction(),
739 "NVPTX system scope atomics require sm_60 or later",
751 auto CodeAddrSpace = NVPTXDAGToDAGISel::getAddrSpace(
N);
753 bool HasMemoryOrdering =
Subtarget->hasMemoryOrdering();
754 bool HasRelaxedMMIO =
Subtarget->hasRelaxedMMIO();
846 return Subtarget->hasLocalVolatile() &&
N->isVolatile()
862 !HasMemoryOrdering) {
864 formatv(
"PTX does not support \"atomic\" for orderings different than"
865 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
875 bool AddrSupportsVolatileOrAtomic =
880 if (!AddrSupportsVolatileOrAtomic)
883 bool UseRelaxedMMIO =
905 formatv(
"PTX only supports Acquire Ordering on reads: {}",
906 N->getOperationName()));
911 formatv(
"PTX only supports Release Ordering on writes: {}",
912 N->getOperationName()));
916 formatv(
"NVPTX does not support AcquireRelease Ordering on "
918 "yet and PTX does not support it on loads or stores: {}",
919 N->getOperationName()));
930 "is emulated in AtomicExpandPass");
934 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
957 auto S =
Scopes[
N->getSyncScopeID()];
980 if (!
T->hasSplitAcquireAndReleaseFences() &&
988 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
989 : NVPTX::INT_MEMBAR_SYS;
991 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
992 : NVPTX::INT_MEMBAR_CTA;
994 return NVPTX::atomic_thread_fence_acquire_cluster;
996 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
997 : NVPTX::INT_MEMBAR_GL;
1001 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1008 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
1009 : NVPTX::INT_MEMBAR_SYS;
1011 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
1012 : NVPTX::INT_MEMBAR_CTA;
1014 return NVPTX::atomic_thread_fence_release_cluster;
1016 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
1017 : NVPTX::INT_MEMBAR_GL;
1021 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1028 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
1029 : NVPTX::INT_MEMBAR_SYS;
1031 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
1032 : NVPTX::INT_MEMBAR_CTA;
1034 return NVPTX::atomic_thread_fence_acq_rel_cluster;
1036 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
1037 : NVPTX::INT_MEMBAR_GL;
1041 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
1049 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
1050 : NVPTX::INT_MEMBAR_SYS;
1052 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
1053 : NVPTX::INT_MEMBAR_CTA;
1055 return NVPTX::atomic_thread_fence_seq_cst_cluster;
1057 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
1058 : NVPTX::INT_MEMBAR_GL;
1071 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
1072 OrderingToString(O), ScopeToString(S)));
1078std::pair<NVPTX::Ordering, NVPTX::Scope>
1079NVPTXDAGToDAGISel::getMemInstOrderingScope(
MemSDNode *
N) {
1088 CurDAG->getMachineFunction().getFunction(),
1089 "NVPTX system scope b128 loads and stores require PTX ISA version 8.4 "
1107static std::optional<unsigned>
1109 std::optional<unsigned> Opcode_i32,
1110 std::optional<unsigned> Opcode_i64) {
1129 return std::nullopt;
1135 (
V->getOpcode() ==
ISD::OR &&
V->getFlags().hasDisjoint());
1140 N =
N.getOperand(0);
1150 GA->getValueType(0), GA->getOffset(),
1151 GA->getTargetFlags());
1154 ES->getTargetFlags());
1157 if (
N.getOpcode() == NVPTXISD::Symbol)
1158 return N.getOperand(0);
1165 APInt AccumulatedOffset(64u, 0);
1171 const APInt CI = CN->getAPIntValue().
sext(64);
1172 if (!(CI + AccumulatedOffset).isSignedIntN(32))
1175 AccumulatedOffset += CI;
1232template <
typename T>
1235 std::optional<T> (*Parse)(
StringRef),
bool EmitDiagnostics) {
1238 if (EmitDiagnostics)
1240 Twine(
"'") +
Key +
"' expects a string value");
1241 return std::nullopt;
1245 auto Parsed = Parse(ValStr);
1246 if (!Parsed && EmitDiagnostics)
1258 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld ||
1259 Access.Instruction == NVPTXMemCacheHintInstruction::St;
1264 NVPTXMemCacheHintAccess
Access) {
1274 NVPTXMemCacheHintAccess
Access) {
1279 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1282 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1285 return Access.Instruction == NVPTXMemCacheHintInstruction::Ld &&
1293 NVPTXMemCacheHintAccess
Access) {
1304 NVPTXMemCacheHintAccess
Access) {
1309NVPTXMemCacheHintOperands NVPTXDAGToDAGISel::getMemCacheHintOperands(
1311 bool EmitDiagnostics) {
1314 SDValue PolicyReg = CurDAG->getRegister(NVPTX::NoRegister, MVT::i64);
1316 return {getI32Imm(0,
DL), PolicyReg};
1317 if (
Node->getNumOperands() == 0) {
1318 if (EmitDiagnostics)
1320 return {getI32Imm(0,
DL), PolicyReg};
1326 std::optional<uint64_t> CachePolicy;
1328 for (
unsigned I = 0;
I + 1 <
Node->getNumOperands();
I += 2) {
1333 if (KeyStr ==
"nvvm.l1_eviction") {
1341 if (KeyStr ==
"nvvm.l2_eviction") {
1349 if (KeyStr ==
"nvvm.l2_prefetch_size") {
1352 if (ParsedPrefetch &&
1358 if (KeyStr ==
"nvvm.l2_cache_hint") {
1361 if (EmitDiagnostics)
1363 Ctx,
"'nvvm.l2_cache_hint' expects an integer value");
1365 CachePolicy = ValCI->getZExtValue();
1370 if (EmitDiagnostics)
1374 unsigned EvictionAndPrefetchHint =
1377 SDValue PolicyConst = CurDAG->getTargetConstant(*CachePolicy,
DL, MVT::i64);
1379 CurDAG->getMachineNode(NVPTX::MOV_B64_i,
DL, MVT::i64, PolicyConst), 0);
1383 return {getI32Imm(EvictionAndPrefetchHint,
DL), PolicyReg};
1386bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1388 assert(
LD->readMem() &&
"Expected load");
1392 if (PlainLoad && PlainLoad->
isIndexed())
1396 const auto CodeAddrSpace = getAddrSpace(LD);
1404 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1412 uint32_t UsedBytesMask;
1413 switch (
N->getOpcode()) {
1417 UsedBytesMask = UINT32_MAX;
1420 UsedBytesMask =
N->getConstantOperandVal(3);
1427 FromTypeWidth <= 128 &&
"Invalid width for load");
1430 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1432 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1433 1, FromTypeWidth,
LD->isVolatile()},
1438 getI32Imm(Scope,
DL),
1439 getI32Imm(CodeAddrSpace,
DL),
1440 getI32Imm(FromType,
DL),
1441 getI32Imm(FromTypeWidth,
DL),
1442 getI32Imm(UsedBytesMask,
DL),
1445 EvictionAndPrefetchHint,
1453 const std::optional<unsigned> Opcode =
1454 IsB128 ? NVPTX::LD_i128
1461 IsB128 ? CurDAG->getVTList(MVT::i128, MVT::Other) :
LD->getVTList();
1462 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL, VTs,
Ops);
1470 SDNode *Unpacked = CurDAG->getMachineNode(
1471 NVPTX::I128toV2I64,
DL, {MVT::i64, MVT::i64},
SDValue(NVPTXLD, 0));
1474 SDValue LoadChain(NVPTXLD, 1);
1477 ReplaceUses(OldResults,
Results, 3);
1478 CurDAG->RemoveDeadNode(LD);
1480 ReplaceNode(LD, NVPTXLD);
1486 switch (
N->getOpcode()) {
1498bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1502 const auto CodeAddrSpace = getAddrSpace(LD);
1506 const MVT EltVT =
LD->getSimpleValueType(0);
1519 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1525 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1529 const auto [EvictionAndPrefetchHint, PolicyReg] =
1530 getMemCacheHintOperands(LD,
1531 {NVPTXMemCacheHintInstruction::Ld, CodeAddrSpace,
1532 LD->getNumValues() - 1,
1533 FromTypeWidth,
LD->isVolatile()},
1537 getI32Imm(Scope,
DL),
1538 getI32Imm(CodeAddrSpace,
DL),
1539 getI32Imm(FromType,
DL),
1540 getI32Imm(FromTypeWidth,
DL),
1541 getI32Imm(UsedBytesMask,
DL),
1544 EvictionAndPrefetchHint,
1548 std::optional<unsigned> Opcode;
1549 switch (
N->getOpcode()) {
1554 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1558 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1562 NVPTX::LDV_i32_v8, {});
1568 SDNode *NVPTXLD = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1573 ReplaceNode(LD, NVPTXLD);
1577bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1580 unsigned ExtensionType;
1581 uint32_t UsedBytesMask;
1583 ExtensionType =
Load->getExtensionType();
1584 UsedBytesMask = UINT32_MAX;
1586 ExtensionType =
LD->getConstantOperandVal(4);
1587 UsedBytesMask =
LD->getConstantOperandVal(3);
1595 assert(!(
LD->getSimpleValueType(0).isVector() &&
1599 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1602 LD->getNumValues() - 1, FromTypeWidth,
LD->isVolatile()},
1605 getI32Imm(FromTypeWidth,
DL),
1606 getI32Imm(UsedBytesMask,
DL),
1609 EvictionAndPrefetchHint,
1614 std::optional<unsigned> Opcode;
1615 switch (
LD->getOpcode()) {
1620 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1623 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1624 NVPTX::LD_GLOBAL_NC_i64);
1629 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1634 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1638 NVPTX::LD_GLOBAL_NC_v8i32, {});
1644 SDNode *NVPTXLDG = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1646 ReplaceNode(LD, NVPTXLDG);
1650bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1665 std::optional<unsigned> Opcode;
1666 switch (
N->getOpcode()) {
1671 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1675 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1679 NVPTX::LDU_GLOBAL_v4i32, {});
1685 SDNode *NVPTXLDU = CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1687 ReplaceNode(LD, NVPTXLDU);
1691bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1693 assert(
ST->writeMem() &&
"Expected store");
1699 assert((PlainStore || AtomicStore || IsB128) &&
"Expected store");
1702 if (PlainStore && PlainStore->
isIndexed())
1706 const auto CodeAddrSpace = getAddrSpace(ST);
1713 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1719 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128,
1720 {selectPossiblyImm(
N->getOperand(2)),
1721 selectPossiblyImm(
N->getOperand(3))});
1728 "Invalid width for store");
1733 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1735 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1736 1, ToTypeWidth,
ST->isVolatile()},
1740 getI32Imm(Ordering,
DL),
1741 getI32Imm(Scope,
DL),
1742 getI32Imm(CodeAddrSpace,
DL),
1743 getI32Imm(ToTypeWidth,
DL),
1746 EvictionAndPrefetchHint,
1750 const std::optional<unsigned> Opcode =
1751 IsB128 ? NVPTX::ST_i128
1753 NVPTX::ST_i16, NVPTX::ST_i32, NVPTX::ST_i64);
1757 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1764 ReplaceNode(ST, NVPTXST);
1768bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1770 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1773 const auto CodeAddrSpace = getAddrSpace(ST);
1786 for (
auto &
V :
ST->ops().slice(1, NumElts))
1789 const unsigned ToTypeWidth = TotalWidth / NumElts;
1792 TotalWidth <= 256 &&
"Invalid width for store");
1795 const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
1797 {NVPTXMemCacheHintInstruction::St, CodeAddrSpace,
1798 NumElts, ToTypeWidth,
ST->isVolatile()},
1802 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1803 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1804 Offset, EvictionAndPrefetchHint, PolicyReg, Chain});
1807 ST->getOperand(1).getSimpleValueType().SimpleTy;
1808 std::optional<unsigned> Opcode;
1809 switch (
ST->getOpcode()) {
1829 SDNode *NVPTXST = CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1834 ReplaceNode(ST, NVPTXST);
1840bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1852 bool IsSigned =
false;
1878 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1882 Val =
LHS.getNode()->getOperand(0);
1883 Start =
LHS.getNode()->getOperand(1);
1890 if (NumBits > GoodBits) {
1896 Start = CurDAG->getTargetConstant(StartVal,
DL, MVT::i32);
1948 NumBits = NumZeros + NumOnes - ShiftAmt;
1954 if (ShiftAmt < NumZeros) {
1961 Start = CurDAG->getTargetConstant(ShiftAmt,
DL, MVT::i32);
1962 Len = CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1978 Val =
LHS->getOperand(0);
1997 if (OuterShiftAmt < InnerShiftAmt) {
2008 Start = CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
2030 unsigned Opc = IsSigned ? NVPTX::BFE_S32 : NVPTX::BFE_U32;
2034 ReplaceNode(
N, CurDAG->getMachineNode(
Opc,
DL,
N->getVTList(),
Ops));
2039bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
2061 auto API = APF.bitcastToAPInt();
2062 API = API.concat(API);
2063 auto Const = CurDAG->getTargetConstant(API,
DL, MVT::i32);
2064 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
2067 auto Const = CurDAG->getTargetConstantFP(APF,
DL, VT);
2068 return SDValue(CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
2071 switch (
N->getOpcode()) {
2074 Operands = {N0, GetConstant(1.0), N1};
2078 Operands = {N1, GetConstant(-1.0), N0};
2083 Operands = {N0, N1, GetConstant(-0.0)};
2089 int Opcode = IsVec ? NVPTX::FMA_BF16x2 : NVPTX::FMA_BF16;
2091 ReplaceNode(
N, FMA);
2100 Src =
N.getOperand(0);
2101 else if (CurDAG->computeKnownFPClass(
N,
fcNegative).signBitIsZeroOrNaN())
2105 Src = selectPossiblyImm(Src);
2114 return CurDAG->getTargetConstant(CN->getAPIntValue(),
SDLoc(
V),
2117 return CurDAG->getTargetConstantFP(CN->getValueAPF(),
SDLoc(
V),
2124bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
2126 std::vector<SDValue> &OutOps) {
2127 switch (ConstraintID) {
2132 OutOps.push_back(
Base);
2133 OutOps.push_back(
Offset);
2140void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
2151 SDValue Lo = selectPossiblyImm(
N->getOperand(2));
2152 SDValue Hi = selectPossiblyImm(
N->getOperand(3));
2156 CurDAG->getMachineNode(NVPTX::V2I64toI128,
DL, MVT::i128, {
Lo,
Hi});
2159 NewOps[0] =
N->getOperand(0);
2162 if (
N->getNumOperands() == 5)
2163 NewOps[3] =
N->getOperand(4);
2166 ReplaceNode(
N, NewValue.
getNode());
2169void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
2186 SDNode *Mov = CurDAG->getMachineNode(
2187 NVPTX::I128toV2I64,
DL,
2191 ReplaceNode(
N, Mov);
2194bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
2203 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0),
N->getOperand(0));
2204 CurDAG->RemoveDeadNode(
N);
2211 SDNode *FenceNode = CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
2212 ReplaceNode(
N, FenceNode);
2230 "NVPTXScopes::operator[]");
2232 auto S = Scopes.find(ID);
2233 if (S == Scopes.end()) {
2234 auto scopeName =
Context->getSyncScopeName(ID);
2235 assert(scopeName.has_value() &&
"Scope name must exist.");
2239 for (
const auto &Entry : Scopes) {
2245 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
2246 "Supported syncscopes are: {2}.",
2247 scopeName.value(),
int(ID),
2253bool NVPTXScopes::empty()
const {
return Scopes.size() == 0; }
2255#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
2256 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
2257 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
2261 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2263 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2265 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2267 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2269 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2271 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2273 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2275 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2277 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2279 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2281 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2283 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2285 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2287 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2289 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2291 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2293 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2295 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2297 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2299 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2301 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
2303 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2305 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2307 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2309 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2311 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2313 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2315 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2317 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
2319 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2321 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2323 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2325 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2327 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2329 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2331 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2333 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2339void NVPTXDAGToDAGISel::SelectTcgen05St(SDNode *
N,
bool hasOffset) {
2340 if (!
Subtarget->hasTcgen05InstSupport())
2342 "tcgen05.st is not supported on this architecture variant");
2352 Operands.push_back(CurDAG->getTargetConstant(
2356 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2368bool NVPTXDAGToDAGISel::tryIntrinsicVoid(SDNode *
N) {
2369 unsigned IID =
N->getConstantOperandVal(1);
2373 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2374 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2375 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2376 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2377 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2378 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2379 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2380 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2381 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2382 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2383 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2384 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2385 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2386 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2387 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2388 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2389 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2390 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2391 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2392 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2393 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2394 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2395 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2396 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2397 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2398 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2399 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2400 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2401 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2406 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2407 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2408 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2409 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2410 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2411 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2412 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2413 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2414 SelectTcgen05St(
N,
true);
2420void NVPTXDAGToDAGISel::selectAtomicSwap128(SDNode *
N) {
2428 Ops.push_back(selectPossiblyImm(Operand));
2429 Ops.append({getI32Imm(getMemOrder(AN), dl), getI32Imm(getAtomicScope(AN), dl),
2430 getI32Imm(getAddrSpace(AN), dl)});
2434 NVPTXMemCacheHintAccess
Access{NVPTXMemCacheHintInstruction::Atom,
2437 const auto [EvictionAndPrefetchHint, CachePolicyReg] =
2438 getMemCacheHintOperands(AN,
Access, dl);
2439 Ops.push_back(EvictionAndPrefetchHint);
2440 Ops.push_back(CachePolicyReg);
2443 Ops.push_back(Chain);
2448 ? NVPTX::ATOM_EXCH_B128
2449 : NVPTX::ATOM_CAS_B128;
2451 auto *ATOM = CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
2454 ReplaceNode(
N, ATOM);
const AArch64Subtarget & Subtarget
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
Function Alias Analysis Results
Atomic ordering constants.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
loop data Loop Data Prefetch
This file implements a map that provides insertion order iteration.
static NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
static unsigned getStoreVectorNumElts(SDNode *N)
static bool isAddLike(const SDValue V)
static std::optional< NVPTX::L2Eviction > parseL2Eviction(StringRef Str)
static SDValue selectBaseADDR(SDValue N, SelectionDAG *DAG)
static std::optional< NVPTX::L2Prefetch > parseL2Prefetch(StringRef Str)
static std::optional< NVPTX::L1Eviction > parseL1Eviction(StringRef Str)
static std::optional< unsigned > getI16ExtractIndex(const SDNode *N)
static void mergeI16Unpacks(SelectionDAG &DAG)
static SDValue accumulateOffset(SDValue &Addr, SDLoc DL, SelectionDAG *DAG)
static bool isGlobalOrGeneric(NVPTX::AddressSpace AddrSpace)
static bool isL2PrefetchSupported(const NVPTXSubtarget &Subtarget, NVPTX::L2Prefetch Prefetch, NVPTXMemCacheHintAccess Access)
static bool isLdOrSt(NVPTXMemCacheHintAccess Access)
static unsigned getTcgen05StOpcode(unsigned IID, bool enableUnpack)
static std::optional< unsigned > pickOpcodeForVT(MVT::SimpleValueType VT, std::optional< unsigned > Opcode_i16, std::optional< unsigned > Opcode_i32, std::optional< unsigned > Opcode_i64)
#define TCGEN05_LD_OPCODE(SHAPE, NUM)
static SDValue stripAssertAlign(SDValue N)
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...
const AArch64Options & getCLOpts() const
const AArch64TargetLowering * getTargetLowering() const override
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 hasNativeBF16Support(unsigned Opcode) const
bool allowFMA(MachineFunction &MF, CodeGenOptLevel OptLevel) const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const SDValue & getOperand(unsigned Num) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
allnodes_const_iterator allnodes_begin() const
allnodes_const_iterator allnodes_end() const
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
ilist< SDNode >::iterator allnodes_iterator
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getValue() const
Represent a constant reference to a string, i.e.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
const Triple & getTargetTriple() const
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Value * getOperand(unsigned i) const
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ FADD
Simple binary floating point operators.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
@ ATOMIC_CMP_SWAP_B128
These nodes are used to lower atomic instructions with i128 type.
unsigned encodeEvictionAndPrefetchHint(L1Eviction L1, L2Eviction L2, L2Prefetch P)
bool isPackedVectorTy(EVT VT)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
AtomicScope
Target-neutral memory synchronization scopes.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
FunctionPass * createNVPTXISelDag(NVPTXTargetMachine &TM, llvm::CodeGenOptLevel OptLevel)
createNVPTXISelDag - This pass converts a legalized DAG into a NVPTX-specific DAG,...
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
const char * toIRString(AtomicOrdering ao)
String used by LLVM IR to represent atomic ordering.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
unsigned getFromTypeWidthForLoad(const MemSDNode *Mem)
The bit-width of a single element loaded by Mem, i.e.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A record for a potential prefetch made during the initial scan of the loop.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
A MapVector that performs no allocations if smaller than a certain size.