23#include "llvm/IR/IntrinsicsNVPTX.h"
34#define DEBUG_TYPE "nvptx-isel"
35#define PASS_NAME "NVPTX DAG->DAG Pattern Instruction Selection"
39 cl::desc(
"Enable reciprocal sqrt optimization"));
46 cl::desc(
"Enable MAD wide optimization"));
75NVPTXDAGToDAGISel::getDivF32Level(
const SDNode *
N)
const {
79bool NVPTXDAGToDAGISel::usePrecSqrtF32(
const SDNode *
N)
const {
83bool NVPTXDAGToDAGISel::useF32FTZ()
const {
84 return Subtarget->getTargetLowering()->useF32FTZ(*
MF);
87bool NVPTXDAGToDAGISel::allowFMA()
const {
88 const NVPTXTargetLowering *TL =
Subtarget->getTargetLowering();
92bool NVPTXDAGToDAGISel::doRsqrtOpt()
const {
return EnableRsqrtOpt; }
94bool NVPTXDAGToDAGISel::doMADWideOpt()
const {
return EnableMADWide; }
98void NVPTXDAGToDAGISel::Select(
SDNode *
N) {
100 if (
N->isMachineOpcode()) {
105 switch (
N->getOpcode()) {
125 if (tryEXTRACT_VECTOR_ELEMENT(
N))
132 SelectSETP_BF16X2(
N);
137 if (tryLoadVector(
N))
148 if (tryStoreVector(
N))
152 if (tryIntrinsicChain(
N))
156 if (tryIntrinsicVoid(
N))
167 if (
N->getOperand(1).getValueType() == MVT::i128) {
168 SelectV2I64toI128(
N);
174 if (
N->getOperand(1).getValueType() == MVT::i128) {
175 SelectI128toV2I64(
N);
182 selectAtomicSwap128(
N);
187 if (tryBF16ArithToFMA(
N))
196#define TCGEN05_LD_OPCODE(SHAPE, NUM) \
197 (enablePack ? NVPTX::TCGEN05_LD_##SHAPE##_##NUM##_PACK \
198 : NVPTX::TCGEN05_LD_##SHAPE##_##NUM)
202 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
204 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
206 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
208 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
210 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
212 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
214 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
216 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
218 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
220 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
222 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
224 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
226 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
228 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
230 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
232 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
234 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
236 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
238 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
240 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
242 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
244 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
246 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
248 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
250 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
252 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
254 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
256 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
258 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128:
260 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
262 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
264 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
266 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
268 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
270 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
272 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
274 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128:
280void NVPTXDAGToDAGISel::SelectTcgen05Ld(
SDNode *
N,
bool hasOffset) {
283 "tcgen05.ld is not supported on this architecture variant");
290 auto OffsetNode =
CurDAG->getTargetConstant(
294 {N->getOperand(2), OffsetNode, N->getOperand(0)}));
299 {N->getOperand(2), N->getOperand(0)}));
303bool NVPTXDAGToDAGISel::tryIntrinsicChain(
SDNode *
N) {
304 unsigned IID =
N->getConstantOperandVal(1);
308 case Intrinsic::nvvm_ldu_global_f:
309 case Intrinsic::nvvm_ldu_global_i:
310 case Intrinsic::nvvm_ldu_global_p:
313 case Intrinsic::nvvm_tcgen05_ld_16x64b_x1:
314 case Intrinsic::nvvm_tcgen05_ld_16x64b_x2:
315 case Intrinsic::nvvm_tcgen05_ld_16x64b_x4:
316 case Intrinsic::nvvm_tcgen05_ld_16x64b_x8:
317 case Intrinsic::nvvm_tcgen05_ld_16x64b_x16:
318 case Intrinsic::nvvm_tcgen05_ld_16x64b_x32:
319 case Intrinsic::nvvm_tcgen05_ld_16x64b_x64:
320 case Intrinsic::nvvm_tcgen05_ld_16x64b_x128:
321 case Intrinsic::nvvm_tcgen05_ld_16x128b_x1:
322 case Intrinsic::nvvm_tcgen05_ld_16x128b_x2:
323 case Intrinsic::nvvm_tcgen05_ld_16x128b_x4:
324 case Intrinsic::nvvm_tcgen05_ld_16x128b_x16:
325 case Intrinsic::nvvm_tcgen05_ld_16x128b_x32:
326 case Intrinsic::nvvm_tcgen05_ld_16x128b_x64:
327 case Intrinsic::nvvm_tcgen05_ld_16x256b_x1:
328 case Intrinsic::nvvm_tcgen05_ld_16x128b_x8:
329 case Intrinsic::nvvm_tcgen05_ld_16x256b_x2:
330 case Intrinsic::nvvm_tcgen05_ld_16x256b_x4:
331 case Intrinsic::nvvm_tcgen05_ld_16x256b_x8:
332 case Intrinsic::nvvm_tcgen05_ld_16x256b_x16:
333 case Intrinsic::nvvm_tcgen05_ld_16x256b_x32:
334 case Intrinsic::nvvm_tcgen05_ld_32x32b_x1:
335 case Intrinsic::nvvm_tcgen05_ld_32x32b_x2:
336 case Intrinsic::nvvm_tcgen05_ld_32x32b_x4:
337 case Intrinsic::nvvm_tcgen05_ld_32x32b_x8:
338 case Intrinsic::nvvm_tcgen05_ld_32x32b_x16:
339 case Intrinsic::nvvm_tcgen05_ld_32x32b_x32:
340 case Intrinsic::nvvm_tcgen05_ld_32x32b_x64:
341 case Intrinsic::nvvm_tcgen05_ld_32x32b_x128: {
346 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x1:
347 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x2:
348 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x4:
349 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x8:
350 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x16:
351 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x32:
352 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x64:
353 case Intrinsic::nvvm_tcgen05_ld_16x32bx2_x128: {
354 SelectTcgen05Ld(
N,
true);
389 return CmpMode::NotANumber;
404 return CurDAG->getTargetConstant(PTXCmpMode, SDLoc(), MVT::i32);
407bool NVPTXDAGToDAGISel::SelectSETP_F16X2(
SDNode *
N) {
410 SDNode *SetP =
CurDAG->getMachineNode(
411 NVPTX::SETP_f16x2rr,
DL, MVT::i1, MVT::i1,
412 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode,
413 CurDAG->getTargetConstant(useF32FTZ() ? 1 : 0,
DL, MVT::i1)});
418bool NVPTXDAGToDAGISel::SelectSETP_BF16X2(
SDNode *
N) {
422 CurDAG->getMachineNode(NVPTX::SETP_bf16x2rr,
DL, MVT::i1, MVT::i1,
423 {
N->getOperand(0),
N->getOperand(1), PTXCmpMode});
428bool NVPTXDAGToDAGISel::tryUNPACK_VECTOR(
SDNode *
N) {
430 MVT EltVT =
N->getSimpleValueType(0);
433 CurDAG->getMachineNode(NVPTX::I64toV2I32, SDLoc(
N), EltVT, EltVT,
Vector);
441bool NVPTXDAGToDAGISel::tryEXTRACT_VECTOR_ELEMENT(
SDNode *
N) {
444 MVT VT =
Vector.getSimpleValueType();
450 Opcode = NVPTX::I32toV2I16;
452 Opcode = NVPTX::I64toV2I32;
458 for (
auto *U :
Vector.getNode()->users()) {
461 if (
U->getOperand(0) !=
Vector)
463 if (
const ConstantSDNode *IdxConst =
465 if (IdxConst->getZExtValue() == 0)
467 else if (IdxConst->getZExtValue() == 1)
483 CurDAG->getMachineNode(Opcode, SDLoc(
N), EltVT, EltVT,
Vector);
484 for (
auto *Node : E0)
486 for (
auto *Node : E1)
513 auto Ordering =
N->getMergedOrdering();
547struct OperationOrderings {
548 NVPTX::Ordering InstructionOrdering, FenceOrdering;
549 OperationOrderings(NVPTX::Ordering IO = NVPTX::Ordering::NotAtomic,
550 NVPTX::Ordering FO = NVPTX::Ordering::NotAtomic)
551 : InstructionOrdering(IO), FenceOrdering(FO) {}
554static OperationOrderings
657 !HasMemoryOrdering) {
659 formatv(
"PTX does not support \"atomic\" for orderings different than"
660 "\"NotAtomic\" or \"Monotonic\" for sm_60 or older, but order "
672 bool AddrGenericOrGlobalOrShared =
677 if (!AddrGenericOrGlobalOrShared)
680 bool UseRelaxedMMIO =
702 formatv(
"PTX only supports Acquire Ordering on reads: {}",
703 N->getOperationName()));
708 formatv(
"PTX only supports Release Ordering on writes: {}",
709 N->getOperationName()));
713 formatv(
"NVPTX does not support AcquireRelease Ordering on "
715 "yet and PTX does not support it on loads or stores: {}",
716 N->getOperationName()));
729 else if (
N->writeMem())
733 formatv(
"NVPTX does not support SequentiallyConsistent Ordering on "
734 "read-modify-writes yet: {}",
735 N->getOperationName()));
736 return OperationOrderings(InstrOrder,
741 formatv(
"NVPTX backend does not support AtomicOrdering \"{}\" yet.",
764 auto S = Scopes[
N->getSyncScopeID()];
787 if (!
T->hasSplitAcquireAndReleaseFences() &&
795 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_sys
796 : NVPTX::INT_MEMBAR_SYS;
798 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_cta
799 : NVPTX::INT_MEMBAR_CTA;
801 return NVPTX::atomic_thread_fence_acquire_cluster;
803 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acquire_gpu
804 : NVPTX::INT_MEMBAR_GL;
808 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
815 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_sys
816 : NVPTX::INT_MEMBAR_SYS;
818 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_cta
819 : NVPTX::INT_MEMBAR_CTA;
821 return NVPTX::atomic_thread_fence_release_cluster;
823 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_release_gpu
824 : NVPTX::INT_MEMBAR_GL;
828 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
835 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_sys
836 : NVPTX::INT_MEMBAR_SYS;
838 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_cta
839 : NVPTX::INT_MEMBAR_CTA;
841 return NVPTX::atomic_thread_fence_acq_rel_cluster;
843 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_acq_rel_gpu
844 : NVPTX::INT_MEMBAR_GL;
848 formatv(
"Unsupported scope \"{}\" for acquire/release/acq_rel fence.",
856 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_sys
857 : NVPTX::INT_MEMBAR_SYS;
859 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_cta
860 : NVPTX::INT_MEMBAR_CTA;
862 return NVPTX::atomic_thread_fence_seq_cst_cluster;
864 return T->hasMemoryOrdering() ? NVPTX::atomic_thread_fence_seq_cst_gpu
865 : NVPTX::INT_MEMBAR_GL;
878 formatv(
"Unsupported \"{}\" ordering and \"{}\" scope for fence.",
879 OrderingToString(O), ScopeToString(S)));
887std::pair<NVPTX::Ordering, NVPTX::Scope>
888NVPTXDAGToDAGISel::insertMemoryInstructionFence(
SDLoc DL,
SDValue &Chain,
890 auto [InstructionOrdering, FenceOrdering] =
892 auto Scope = getOperationScope(
N, InstructionOrdering);
914 formatv(
"Unexpected fence ordering: \"{}\".",
917 return {InstructionOrdering,
Scope};
922static std::optional<unsigned>
924 std::optional<unsigned> Opcode_i32,
925 std::optional<unsigned> Opcode_i64) {
950 (V->getOpcode() ==
ISD::OR && V->getFlags().hasDisjoint());
965 GA->getValueType(0), GA->getOffset(),
966 GA->getTargetFlags());
969 ES->getTargetFlags());
978 APInt AccumulatedOffset(64u, 0);
984 const APInt CI = CN->getAPIntValue().
sext(64);
985 if (!(CI + AccumulatedOffset).isSignedIntN(32))
988 AccumulatedOffset += CI;
1014bool NVPTXDAGToDAGISel::tryLoad(
SDNode *
N) {
1016 assert(
LD->readMem() &&
"Expected load");
1020 if (PlainLoad && PlainLoad->
isIndexed())
1030 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1032 const unsigned FromTypeWidth =
LD->getMemoryVT().getSizeInBits();
1040 uint32_t UsedBytesMask;
1041 switch (
N->getOpcode()) {
1044 UsedBytesMask = UINT32_MAX;
1047 UsedBytesMask =
N->getConstantOperandVal(3);
1054 FromTypeWidth <= 128 &&
"Invalid width for load");
1059 getI32Imm(Scope,
DL),
1060 getI32Imm(CodeAddrSpace,
DL),
1061 getI32Imm(FromType,
DL),
1062 getI32Imm(FromTypeWidth,
DL),
1063 getI32Imm(UsedBytesMask,
DL),
1069 const std::optional<unsigned> Opcode =
1070 pickOpcodeForVT(TargetVT, NVPTX::LD_i16, NVPTX::LD_i32, NVPTX::LD_i64);
1074 SDNode *NVPTXLD =
CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1078 MachineMemOperand *MemRef =
LD->getMemOperand();
1086 switch (
N->getOpcode()) {
1098bool NVPTXDAGToDAGISel::tryLoadVector(
SDNode *
N) {
1106 const MVT EltVT =
LD->getSimpleValueType(0);
1109 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, LD);
1119 const unsigned ExtensionType =
N->getConstantOperandVal(4);
1122 : NVPTX::PTXLdStInstCode::
Untyped;
1125 const uint32_t UsedBytesMask =
N->getConstantOperandVal(3);
1131 getI32Imm(Scope,
DL),
1132 getI32Imm(CodeAddrSpace,
DL),
1133 getI32Imm(FromType,
DL),
1134 getI32Imm(FromTypeWidth,
DL),
1135 getI32Imm(UsedBytesMask,
DL),
1140 std::optional<unsigned> Opcode;
1141 switch (
N->getOpcode()) {
1146 NVPTX::LDV_i32_v2, NVPTX::LDV_i64_v2);
1150 NVPTX::LDV_i32_v4, NVPTX::LDV_i64_v4);
1154 NVPTX::LDV_i32_v8, {});
1160 SDNode *NVPTXLD =
CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1162 MachineMemOperand *MemRef =
LD->getMemOperand();
1169bool NVPTXDAGToDAGISel::tryLDG(
MemSDNode *LD) {
1172 unsigned ExtensionType;
1173 uint32_t UsedBytesMask;
1175 ExtensionType =
Load->getExtensionType();
1176 UsedBytesMask = UINT32_MAX;
1178 ExtensionType =
LD->getConstantOperandVal(4);
1179 UsedBytesMask =
LD->getConstantOperandVal(3);
1183 : NVPTX::PTXLdStInstCode::
Untyped;
1187 assert(!(
LD->getSimpleValueType(0).isVector() &&
1192 getI32Imm(FromTypeWidth,
DL),
1193 getI32Imm(UsedBytesMask,
DL),
1199 std::optional<unsigned> Opcode;
1200 switch (
LD->getOpcode()) {
1205 NVPTX::LD_GLOBAL_NC_i32, NVPTX::LD_GLOBAL_NC_i64);
1208 Opcode =
pickOpcodeForVT(TargetVT, std::nullopt, NVPTX::LD_GLOBAL_NC_i32,
1209 NVPTX::LD_GLOBAL_NC_i64);
1214 NVPTX::LD_GLOBAL_NC_v2i32, NVPTX::LD_GLOBAL_NC_v2i64);
1219 NVPTX::LD_GLOBAL_NC_v4i32, NVPTX::LD_GLOBAL_NC_v4i64);
1223 NVPTX::LD_GLOBAL_NC_v8i32, {});
1229 SDNode *NVPTXLDG =
CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1238 auto ElementBitWidth = TotalWidth / NumElts;
1240 ElementBitWidth <= 128 && TotalWidth <= 256 &&
1241 "Invalid width for load");
1242 return ElementBitWidth;
1245bool NVPTXDAGToDAGISel::tryLDU(
SDNode *
N) {
1260 std::optional<unsigned> Opcode;
1261 switch (
N->getOpcode()) {
1266 NVPTX::LDU_GLOBAL_i32, NVPTX::LDU_GLOBAL_i64);
1270 NVPTX::LDU_GLOBAL_v2i32, NVPTX::LDU_GLOBAL_v2i64);
1274 NVPTX::LDU_GLOBAL_v4i32, {});
1280 SDNode *NVPTXLDU =
CurDAG->getMachineNode(*Opcode,
DL,
LD->getVTList(),
Ops);
1286bool NVPTXDAGToDAGISel::tryStore(
SDNode *
N) {
1288 assert(
ST->writeMem() &&
"Expected store");
1291 assert((PlainStore || AtomicStore) &&
"Expected store");
1294 if (PlainStore && PlainStore->
isIndexed())
1302 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1305 const unsigned ToTypeWidth =
ST->getMemoryVT().getSizeInBits();
1311 "Invalid width for store");
1315 getI32Imm(Ordering,
DL),
1316 getI32Imm(Scope,
DL),
1317 getI32Imm(CodeAddrSpace,
DL),
1318 getI32Imm(ToTypeWidth,
DL),
1323 const std::optional<unsigned> Opcode =
1325 NVPTX::ST_i32, NVPTX::ST_i64);
1329 SDNode *NVPTXST =
CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1334 MachineMemOperand *MemRef =
ST->getMemOperand();
1340bool NVPTXDAGToDAGISel::tryStoreVector(
SDNode *
N) {
1342 const unsigned TotalWidth =
ST->getMemoryVT().getSizeInBits();
1353 const auto [
Ordering,
Scope] = insertMemoryInstructionFence(
DL, Chain, ST);
1358 for (
auto &V :
ST->ops().slice(1, NumElts))
1359 Ops.push_back(selectPossiblyImm(V));
1361 const unsigned ToTypeWidth = TotalWidth / NumElts;
1364 TotalWidth <= 256 &&
"Invalid width for store");
1367 Ops.append({getI32Imm(Ordering,
DL), getI32Imm(Scope,
DL),
1368 getI32Imm(CodeAddrSpace,
DL), getI32Imm(ToTypeWidth,
DL),
Base,
1372 ST->getOperand(1).getSimpleValueType().SimpleTy;
1373 std::optional<unsigned> Opcode;
1374 switch (
ST->getOpcode()) {
1394 SDNode *NVPTXST =
CurDAG->getMachineNode(*Opcode,
DL, MVT::Other,
Ops);
1396 MachineMemOperand *MemRef =
ST->getMemOperand();
1405bool NVPTXDAGToDAGISel::tryBFE(
SDNode *
N) {
1412 bool IsSigned =
false;
1428 uint64_t MaskVal =
Mask->getZExtValue();
1438 Len =
CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1442 Val =
LHS.getNode()->getOperand(0);
1443 Start =
LHS.getNode()->getOperand(1);
1449 int64_t GoodBits =
Start.getValueSizeInBits() - StartVal;
1450 if (NumBits > GoodBits) {
1508 NumBits = NumZeros + NumOnes - ShiftAmt;
1514 if (ShiftAmt < NumZeros) {
1522 Len =
CurDAG->getTargetConstant(NumBits,
DL, MVT::i32);
1538 Val =
LHS->getOperand(0);
1557 if (OuterShiftAmt < InnerShiftAmt) {
1568 Start =
CurDAG->getTargetConstant(OuterShiftAmt - InnerShiftAmt,
DL,
1593 Opc = NVPTX::BFE_S32rii;
1595 Opc = NVPTX::BFE_U32rii;
1599 Opc = NVPTX::BFE_S64rii;
1601 Opc = NVPTX::BFE_U64rii;
1617bool NVPTXDAGToDAGISel::tryBF16ArithToFMA(
SDNode *
N) {
1618 EVT VT =
SDValue(
N, 0).getValueType();
1622 const NVPTXSubtarget *STI = TM.getSubtargetImpl();
1639 auto API = APF.bitcastToAPInt();
1640 API = API.concat(API);
1642 return SDValue(
CurDAG->getMachineNode(NVPTX::MOV_B32_i,
DL, VT, Const),
1646 return SDValue(
CurDAG->getMachineNode(NVPTX::MOV_BF16_i,
DL, VT, Const), 0);
1649 switch (
N->getOpcode()) {
1652 Operands = {N0, GetConstant(1.0), N1};
1656 Operands = {N1, GetConstant(-1.0), N0};
1661 Operands = {N0, N1, GetConstant(-0.0)};
1667 int Opcode = IsVec ? NVPTX::FMA_BF16x2rrr : NVPTX::FMA_BF16rrr;
1668 MachineSDNode *
FMA =
CurDAG->getMachineNode(Opcode,
DL, VT, Operands);
1675 V =
V.getOperand(0);
1678 return CurDAG->getTargetConstant(CN->getAPIntValue(), SDLoc(V),
1681 return CurDAG->getTargetConstantFP(CN->getValueAPF(), SDLoc(V),
1690 std::vector<SDValue> &OutOps) {
1691 switch (ConstraintID) {
1696 OutOps.push_back(
Base);
1697 OutOps.push_back(
Offset);
1704void NVPTXDAGToDAGISel::SelectV2I64toI128(
SDNode *
N) {
1723 NewOps[0] =
N->getOperand(0);
1726 if (
N->getNumOperands() == 5)
1727 NewOps[3] =
N->getOperand(4);
1733void NVPTXDAGToDAGISel::SelectI128toV2I64(
SDNode *
N) {
1750 SDNode *Mov =
CurDAG->getMachineNode(
1751 NVPTX::I128toV2I64,
DL,
1758bool NVPTXDAGToDAGISel::tryFence(
SDNode *
N) {
1761 auto Scope = Scopes[
N->getConstantOperandVal(2)];
1775 SDNode *FenceNode =
CurDAG->getMachineNode(FenceOp,
DL, MVT::Other, Chain);
1791 "NVPTXScopes::operator[]");
1793 auto S = Scopes.find(
ID);
1794 if (S == Scopes.end()) {
1795 auto scopeName = Context->getSyncScopeName(
ID);
1796 assert(scopeName.has_value() &&
"Scope name must exist.");
1800 for (
const auto &Entry : Scopes) {
1801 if (
auto name = Context->getSyncScopeName(Entry.first))
1806 formatv(
"NVPTX backend does not support syncscope \"{0}\" (ID={1}).\n"
1807 "Supported syncscopes are: {2}.",
1808 scopeName.value(),
int(
ID),
1816#define CP_ASYNC_BULK_TENSOR_OPCODE(dir, dim, mode, is_s32, suffix) \
1818 ? NVPTX::CP_ASYNC_BULK_TENSOR_##dir##_##dim##_SHARED32_##mode##suffix \
1819 : NVPTX::CP_ASYNC_BULK_TENSOR_##dir##_##dim##_##mode##suffix)
1821#define GET_CP_ASYNC_BULK_TENSOR_OPCODE_S2G_RED(dim, mode, is_ch, is_s32) \
1822 (is_ch ? (CP_ASYNC_BULK_TENSOR_OPCODE(RED, dim, mode, is_s32, _CH)) \
1823 : (CP_ASYNC_BULK_TENSOR_OPCODE(RED, dim, mode, is_s32, )))
1842 "GetCpAsyncBulkTensorS2GReductionOpcode.");
1863 "GetCpAsyncBulkTensorS2GReductionOpcode.");
1868void NVPTXDAGToDAGISel::SelectCpAsyncBulkTensorReduceCommon(
SDNode *
N,
1875 size_t NumOps =
N->getNumOperands();
1876 size_t NumDims =
NumOps - 6;
1877 bool IsCacheHint =
N->getConstantOperandVal(
NumOps - 1) == 1;
1878 size_t NumArgs = NumDims + (IsCacheHint ? 3 : 2);
1882 Ops.push_back(getI32Imm(RedOp,
DL));
1883 Ops.push_back(
N->getOperand(0));
1888 NumDims, IsShared32, IsCacheHint, IsIm2Col);
1892#define TCGEN05_ST_OPCODE(SHAPE, NUM) \
1893 (enableUnpack ? NVPTX::TCGEN05_ST_##SHAPE##_##NUM##_UNPACK \
1894 : NVPTX::TCGEN05_ST_##SHAPE##_##NUM)
1898 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
1900 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
1902 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
1904 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
1906 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
1908 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
1910 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
1912 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
1914 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
1916 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
1918 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
1920 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
1922 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
1924 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
1926 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
1928 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
1930 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
1932 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
1934 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
1936 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
1938 case Intrinsic::nvvm_tcgen05_st_16x256b_x32:
1940 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
1942 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
1944 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
1946 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
1948 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
1950 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
1952 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
1954 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128:
1956 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
1958 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
1960 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
1962 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
1964 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
1966 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
1968 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
1970 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
1976void NVPTXDAGToDAGISel::SelectTcgen05St(
SDNode *
N,
bool hasOffset) {
1977 if (!
Subtarget->hasTcgen05InstSupport())
1979 "tcgen05.st is not supported on this architecture variant");
1993 for (
unsigned I = hasOffset ? 4 : 3;
I < (
N->getNumOperands() - 1);
I++)
2002 DL,
N->getVTList(), Operands));
2005bool NVPTXDAGToDAGISel::tryIntrinsicVoid(
SDNode *
N) {
2006 unsigned IID =
N->getConstantOperandVal(1);
2008 auto CastTy = [](TMARedTy
Op) {
return static_cast<unsigned>(
Op); };
2012 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_tile_1d:
2013 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_tile_2d:
2014 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_tile_3d:
2015 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_tile_4d:
2016 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_tile_5d:
2017 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::ADD));
2019 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_im2col_3d:
2020 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_im2col_4d:
2021 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_add_im2col_5d:
2022 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::ADD),
2025 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_tile_1d:
2026 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_tile_2d:
2027 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_tile_3d:
2028 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_tile_4d:
2029 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_tile_5d:
2030 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::MIN));
2032 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_im2col_3d:
2033 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_im2col_4d:
2034 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_min_im2col_5d:
2035 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::MIN),
2038 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_tile_1d:
2039 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_tile_2d:
2040 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_tile_3d:
2041 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_tile_4d:
2042 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_tile_5d:
2043 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::MAX));
2045 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_im2col_3d:
2046 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_im2col_4d:
2047 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_max_im2col_5d:
2048 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::MAX),
2051 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_tile_1d:
2052 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_tile_2d:
2053 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_tile_3d:
2054 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_tile_4d:
2055 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_tile_5d:
2056 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::INC));
2058 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_im2col_3d:
2059 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_im2col_4d:
2060 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_inc_im2col_5d:
2061 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::INC),
2064 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_tile_1d:
2065 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_tile_2d:
2066 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_tile_3d:
2067 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_tile_4d:
2068 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_tile_5d:
2069 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::DEC));
2071 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_im2col_3d:
2072 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_im2col_4d:
2073 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_dec_im2col_5d:
2074 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::DEC),
2077 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_tile_1d:
2078 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_tile_2d:
2079 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_tile_3d:
2080 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_tile_4d:
2081 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_tile_5d:
2082 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::AND));
2084 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_im2col_3d:
2085 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_im2col_4d:
2086 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_and_im2col_5d:
2087 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::AND),
2090 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_tile_1d:
2091 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_tile_2d:
2092 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_tile_3d:
2093 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_tile_4d:
2094 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_tile_5d:
2095 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::OR));
2097 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_im2col_3d:
2098 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_im2col_4d:
2099 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_or_im2col_5d:
2100 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::OR),
2103 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_tile_1d:
2104 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_tile_2d:
2105 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_tile_3d:
2106 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_tile_4d:
2107 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_tile_5d:
2108 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::XOR));
2110 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_im2col_3d:
2111 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_im2col_4d:
2112 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_xor_im2col_5d:
2113 SelectCpAsyncBulkTensorReduceCommon(
N, CastTy(TMARedTy::XOR),
2117 case Intrinsic::nvvm_tcgen05_st_16x64b_x1:
2118 case Intrinsic::nvvm_tcgen05_st_16x64b_x2:
2119 case Intrinsic::nvvm_tcgen05_st_16x64b_x4:
2120 case Intrinsic::nvvm_tcgen05_st_16x64b_x8:
2121 case Intrinsic::nvvm_tcgen05_st_16x64b_x16:
2122 case Intrinsic::nvvm_tcgen05_st_16x64b_x32:
2123 case Intrinsic::nvvm_tcgen05_st_16x64b_x64:
2124 case Intrinsic::nvvm_tcgen05_st_16x64b_x128:
2125 case Intrinsic::nvvm_tcgen05_st_32x32b_x1:
2126 case Intrinsic::nvvm_tcgen05_st_32x32b_x2:
2127 case Intrinsic::nvvm_tcgen05_st_32x32b_x4:
2128 case Intrinsic::nvvm_tcgen05_st_32x32b_x8:
2129 case Intrinsic::nvvm_tcgen05_st_32x32b_x16:
2130 case Intrinsic::nvvm_tcgen05_st_32x32b_x32:
2131 case Intrinsic::nvvm_tcgen05_st_32x32b_x64:
2132 case Intrinsic::nvvm_tcgen05_st_32x32b_x128:
2133 case Intrinsic::nvvm_tcgen05_st_16x128b_x1:
2134 case Intrinsic::nvvm_tcgen05_st_16x128b_x2:
2135 case Intrinsic::nvvm_tcgen05_st_16x128b_x4:
2136 case Intrinsic::nvvm_tcgen05_st_16x128b_x8:
2137 case Intrinsic::nvvm_tcgen05_st_16x128b_x16:
2138 case Intrinsic::nvvm_tcgen05_st_16x128b_x32:
2139 case Intrinsic::nvvm_tcgen05_st_16x128b_x64:
2140 case Intrinsic::nvvm_tcgen05_st_16x256b_x1:
2141 case Intrinsic::nvvm_tcgen05_st_16x256b_x2:
2142 case Intrinsic::nvvm_tcgen05_st_16x256b_x4:
2143 case Intrinsic::nvvm_tcgen05_st_16x256b_x8:
2144 case Intrinsic::nvvm_tcgen05_st_16x256b_x16:
2145 case Intrinsic::nvvm_tcgen05_st_16x256b_x32: {
2150 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x1:
2151 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x2:
2152 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x4:
2153 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x8:
2154 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x16:
2155 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x32:
2156 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x64:
2157 case Intrinsic::nvvm_tcgen05_st_16x32bx2_x128: {
2158 SelectTcgen05St(
N,
true);
2164void NVPTXDAGToDAGISel::selectAtomicSwap128(
SDNode *
N) {
2171 Ops.append(
N->op_begin() + 2,
N->op_end());
2173 getI32Imm(getMemOrder(AN), dl),
2174 getI32Imm(getAtomicScope(AN), dl),
2182 ? NVPTX::ATOM_EXCH_B128
2183 : NVPTX::ATOM_CAS_B128;
2185 auto *ATOM =
CurDAG->getMachineNode(Opcode, dl,
N->getVTList(),
Ops);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
static unsigned getStoreVectorNumElts(SDNode *N)
static bool isAddLike(const SDValue V)
static SDValue selectBaseADDR(SDValue N, SelectionDAG *DAG)
static SDValue accumulateOffset(SDValue &Addr, SDLoc DL, SelectionDAG *DAG)
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"))
static unsigned GetCpAsyncBulkTensorS2GReductionOpcode(size_t Dim, bool IsShared32, bool IsCacheHint, bool IsIm2Col)
#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 unsigned int getFenceOp(NVPTX::Ordering O, NVPTX::Scope S, NVPTXSubtarget const *T)
#define GET_CP_ASYNC_BULK_TENSOR_OPCODE_S2G_RED(dim, mode, is_ch, is_s32)
#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)
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.
const SDValue & getVal() const
uint64_t getZExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
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.
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.
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.
NVPTXDAGToDAGISelLegacy(NVPTXTargetMachine &tm, CodeGenOptLevel OptLevel)
bool runOnMachineFunction(MachineFunction &MF) override
NVPTXDAGToDAGISel()=delete
static NVPTX::AddressSpace getAddrSpace(const MemSDNode *N)
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.
static unsigned getFromTypeWidthForLoad(const MemSDNode *Mem)
const NVPTXSubtarget * Subtarget
const NVPTXTargetLowering * getTargetLowering() const override
bool hasNativeBF16Support(int Opcode) const
bool hasRelaxedMMIO() const
bool hasMemoryOrdering() const
NVPTX::DivPrecisionLevel getDivF32Level(const MachineFunction &MF, const SDNode &N) const
bool allowFMA(MachineFunction &MF, CodeGenOptLevel OptLevel) const
bool usePrecSqrtF32(const SDNode *N=nullptr) const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
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
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
SelectionDAGISel(TargetMachine &tm, CodeGenOptLevel OL=CodeGenOptLevel::Default)
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),...
SDValue getTargetFrameIndex(int FI, EVT VT)
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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.
const SDValue & getValue() const
#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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ 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.
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...
This is an optimization pass for GlobalISel generic memory operations.
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,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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...
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.
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.
TypeSize getSizeInBits() const
Return the size of the specified 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.
NVPTX::Scope operator[](SyncScope::ID ID) const