46#include "llvm/IR/IntrinsicsAMDGPU.h"
47#include "llvm/IR/IntrinsicsR600.h"
60#define DEBUG_TYPE "si-lower"
66 cl::desc(
"Do not align and prefetch loops"),
70 "amdgpu-use-divergent-register-indexing",
cl::Hidden,
71 cl::desc(
"Use indirect register addressing for divergent indexes"),
89 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
90 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
92 return AMDGPU::SGPR0 +
Reg;
108 TRI->getDefaultVectorSuperClassForBitWidth(32);
114 TRI->getDefaultVectorSuperClassForBitWidth(64);
152 TRI->getDefaultVectorSuperClassForBitWidth(320));
156 TRI->getDefaultVectorSuperClassForBitWidth(352));
160 TRI->getDefaultVectorSuperClassForBitWidth(384));
164 TRI->getDefaultVectorSuperClassForBitWidth(512));
171 TRI->getDefaultVectorSuperClassForBitWidth(1024));
173 if (Subtarget->has16BitInsts()) {
174 if (Subtarget->useRealTrue16Insts()) {
204 TRI->getDefaultVectorSuperClassForBitWidth(1024));
220 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
221 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
222 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
223 MVT::i1, MVT::v32i32},
227 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
228 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
229 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
230 MVT::i1, MVT::v32i32},
248 if (Subtarget->hasBF16PackedInsts()) {
315 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
322 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
323 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
324 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
327 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
328 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
329 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
333 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
334 MVT::v3i16, MVT::v4i16, MVT::Other},
339 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
355 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
356 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
357 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
358 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
359 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
360 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
361 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
362 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
397 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
411 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
425 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
439 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
453 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
468 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
469 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
472 if (Subtarget->hasPkMovB32()) {
493 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
494 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
499 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
503 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
504 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
505 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
506 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
530 if (Subtarget->hasSMemRealTime() ||
535 if (Subtarget->has16BitInsts()) {
545 if (Subtarget->hasMadMacF32Insts())
563 if (Subtarget->hasIntClamp())
566 if (Subtarget->hasAddNoCarryInsts())
572 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
575 {MVT::f64, MVT::f32},
Legal);
579 {MVT::f64, MVT::f32},
Custom);
584 {MVT::f64, MVT::f32},
Legal);
587 if (Subtarget->haveRoundOpsF64())
617 if (Subtarget->has16BitInsts()) {
665 if (!Subtarget->useRealTrue16Insts() ||
666 !Subtarget->d16PreservesUnusedBits()) {
667 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
673 if (!Subtarget->useRealTrue16Insts()) {
674 for (
MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
686 if (Subtarget->hasBF16TransInsts())
702 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
703 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
704 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
739 if (Subtarget->hasVCvtPkIU16F32())
742 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
749 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
849 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
850 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
851 MVT::v32f16, MVT::v32bf16},
853 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
860 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
Custom);
871 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
875 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
880 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
881 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
889 if (Subtarget->hasVOP3PInsts()) {
900 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
903 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
904 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
905 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
908 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
916 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
922 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
932 {MVT::v2f16, MVT::v4f16},
Custom);
938 if (Subtarget->hasBF16PackedInsts()) {
944 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
952 if (Subtarget->hasAnyPackedFP32Ops()) {
956 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
959 if (Subtarget->hasAnyPackedFP64Ops()) {
965 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
967 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
974 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
983 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
988 if (Subtarget->hasAnyPackedU64Ops()) {
992 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
999 if (Subtarget->has16BitInsts()) {
1014 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1015 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1016 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1017 MVT::v32f16, MVT::v32bf16},
1022 if (Subtarget->useVMulU64Inst())
1024 else if (Subtarget->hasScalarSMulU64())
1027 if (Subtarget->hasMad64_32())
1030 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1036 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1038 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
1041 if (Subtarget->hasMinimum3Maximum3F32())
1044 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1048 if (!Subtarget->hasMinimum3Maximum3F16())
1054 if (Subtarget->hasVOP3PInsts()) {
1057 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1061 if (Subtarget->useMinMaxI64Insts())
1066 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1067 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1072 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1073 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1074 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1075 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1090 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1095 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1096 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1097 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1098 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1113 if (Subtarget->hasBF16ConversionInsts()) {
1115 {MVT::bf16, MVT::v2bf16},
Custom);
1119 if (Subtarget->hasBF16TransInsts()) {
1123 const bool HasE5M3ConversionInsts =
1124 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1125 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1136 if (Subtarget->hasFP8F16ConversionInsts()) {
1141 if (Subtarget->hasCvtPkF16F32Inst()) {
1143 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1196 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1237 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1250 EVT DestVT,
EVT SrcVT)
const {
1252 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1255 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1262 LLT DestTy,
LLT SrcTy)
const {
1263 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1264 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1266 SrcTy.getScalarSizeInBits() == 16 &&
1287 return Subtarget->has16BitInsts()
1293 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1297 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1319 return (NumElts + 1) / 2;
1325 return NumElts * ((
Size + 31) / 32);
1334 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1343 MVT SimpleIntermediateVT =
1345 IntermediateVT = SimpleIntermediateVT;
1346 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1347 NumIntermediates = (NumElts + 1) / 2;
1348 return (NumElts + 1) / 2;
1353 IntermediateVT = RegisterVT;
1354 NumIntermediates = NumElts;
1355 return NumIntermediates;
1360 RegisterVT = MVT::i16;
1361 IntermediateVT = ScalarVT;
1362 NumIntermediates = NumElts;
1363 return NumIntermediates;
1367 RegisterVT = MVT::i32;
1368 IntermediateVT = ScalarVT;
1369 NumIntermediates = NumElts;
1370 return NumIntermediates;
1374 RegisterVT = MVT::i32;
1375 IntermediateVT = RegisterVT;
1376 NumIntermediates = NumElts * ((
Size + 31) / 32);
1377 return NumIntermediates;
1382 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1387 unsigned MaxNumLanes) {
1388 assert(MaxNumLanes != 0);
1392 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1403 unsigned MaxNumLanes) {
1409 assert(ST->getNumContainedTypes() == 2 &&
1410 ST->getContainedType(1)->isIntegerTy(32));
1424 return MVT::amdgpuBufferFatPointer;
1426 DL.getPointerSizeInBits(AS) == 192)
1427 return MVT::amdgpuBufferStridedPointer;
1436 DL.getPointerSizeInBits(AS) == 160) ||
1438 DL.getPointerSizeInBits(AS) == 192))
1445 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1446 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1447 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1449 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1450 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1451 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1452 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1453 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1454 case Intrinsic::amdgcn_flat_load_monitor_b32:
1455 case Intrinsic::amdgcn_global_load_monitor_b32:
1457 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1458 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1459 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1460 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1461 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1462 case Intrinsic::amdgcn_flat_load_monitor_b64:
1463 case Intrinsic::amdgcn_global_load_monitor_b64:
1465 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1466 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1467 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1468 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1469 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1470 case Intrinsic::amdgcn_flat_load_monitor_b128:
1471 case Intrinsic::amdgcn_global_load_monitor_b128:
1507 unsigned IntrID)
const {
1509 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1523 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1537 if (RsrcIntr->IsImage) {
1552 Info.ptrVal = RsrcArg;
1556 if (RsrcIntr->IsImage) {
1557 unsigned MaxNumLanes = 4;
1572 std::numeric_limits<unsigned>::max());
1582 if (RsrcIntr->IsImage) {
1602 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1604 Info.memVT = MVT::i32;
1611 case Intrinsic::amdgcn_raw_buffer_load_lds:
1612 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1613 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1614 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1615 case Intrinsic::amdgcn_struct_buffer_load_lds:
1616 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1617 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1618 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1632 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1641 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1642 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1643 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1644 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1647 std::numeric_limits<unsigned>::max());
1660 case Intrinsic::amdgcn_ds_ordered_add:
1661 case Intrinsic::amdgcn_ds_ordered_swap: {
1675 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1676 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1679 Info.ptrVal =
nullptr;
1685 case Intrinsic::amdgcn_ds_append:
1686 case Intrinsic::amdgcn_ds_consume: {
1700 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1701 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1702 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1707 Info.memVT = MVT::i64;
1715 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1716 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1717 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1720 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1723 ->getElementType(0));
1732 case Intrinsic::amdgcn_global_atomic_fmin_num:
1733 case Intrinsic::amdgcn_global_atomic_fmax_num:
1734 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1735 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1736 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1747 case Intrinsic::amdgcn_cluster_load_b32:
1748 case Intrinsic::amdgcn_cluster_load_b64:
1749 case Intrinsic::amdgcn_cluster_load_b128:
1750 case Intrinsic::amdgcn_ds_load_tr6_b96:
1751 case Intrinsic::amdgcn_ds_load_tr4_b64:
1752 case Intrinsic::amdgcn_ds_load_tr8_b64:
1753 case Intrinsic::amdgcn_ds_load_tr16_b128:
1754 case Intrinsic::amdgcn_global_load_tr6_b96:
1755 case Intrinsic::amdgcn_global_load_tr4_b64:
1756 case Intrinsic::amdgcn_global_load_tr_b64:
1757 case Intrinsic::amdgcn_global_load_tr_b128:
1758 case Intrinsic::amdgcn_ds_read_tr4_b64:
1759 case Intrinsic::amdgcn_ds_read_tr6_b96:
1760 case Intrinsic::amdgcn_ds_read_tr8_b64:
1761 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1770 case Intrinsic::amdgcn_flat_load_monitor_b32:
1771 case Intrinsic::amdgcn_flat_load_monitor_b64:
1772 case Intrinsic::amdgcn_flat_load_monitor_b128:
1773 case Intrinsic::amdgcn_global_load_monitor_b32:
1774 case Intrinsic::amdgcn_global_load_monitor_b64:
1775 case Intrinsic::amdgcn_global_load_monitor_b128: {
1786 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1787 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1788 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1799 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1800 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1801 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1812 case Intrinsic::amdgcn_ds_gws_init:
1813 case Intrinsic::amdgcn_ds_gws_barrier:
1814 case Intrinsic::amdgcn_ds_gws_sema_v:
1815 case Intrinsic::amdgcn_ds_gws_sema_br:
1816 case Intrinsic::amdgcn_ds_gws_sema_p:
1817 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1827 Info.memVT = MVT::i32;
1829 Info.align =
Align(4);
1831 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1838 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1839 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1840 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1841 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1842 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1843 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1844 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1845 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1860 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1861 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1862 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1863 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1878 case Intrinsic::amdgcn_av_load_b128:
1879 case Intrinsic::amdgcn_av_store_b128: {
1880 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1882 Info.memVT = MVT::v4i32;
1884 Info.align =
Align(16);
1892 unsigned ScopeIdx = CI.
arg_size() - 1;
1896 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1900 case Intrinsic::amdgcn_load_to_lds:
1901 case Intrinsic::amdgcn_load_async_to_lds:
1902 case Intrinsic::amdgcn_global_load_lds:
1903 case Intrinsic::amdgcn_global_load_async_lds: {
1922 Width * 8 * Subtarget->getWavefrontSize());
1928 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1929 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1930 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1931 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1941 Info.memVT = MVT::i32;
1943 Info.align =
Align(4);
1949 case Intrinsic::amdgcn_s_prefetch_data:
1950 case Intrinsic::amdgcn_s_prefetch_inst:
1951 case Intrinsic::amdgcn_flat_prefetch:
1952 case Intrinsic::amdgcn_global_prefetch: {
1967 Type *&AccessTy)
const {
1968 Value *Ptr =
nullptr;
1969 switch (
II->getIntrinsicID()) {
1970 case Intrinsic::amdgcn_cluster_load_b128:
1971 case Intrinsic::amdgcn_cluster_load_b64:
1972 case Intrinsic::amdgcn_cluster_load_b32:
1973 case Intrinsic::amdgcn_ds_append:
1974 case Intrinsic::amdgcn_ds_consume:
1975 case Intrinsic::amdgcn_ds_load_tr8_b64:
1976 case Intrinsic::amdgcn_ds_load_tr16_b128:
1977 case Intrinsic::amdgcn_ds_load_tr4_b64:
1978 case Intrinsic::amdgcn_ds_load_tr6_b96:
1979 case Intrinsic::amdgcn_ds_read_tr4_b64:
1980 case Intrinsic::amdgcn_ds_read_tr6_b96:
1981 case Intrinsic::amdgcn_ds_read_tr8_b64:
1982 case Intrinsic::amdgcn_ds_read_tr16_b64:
1983 case Intrinsic::amdgcn_ds_ordered_add:
1984 case Intrinsic::amdgcn_ds_ordered_swap:
1985 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1986 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1987 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1988 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1989 case Intrinsic::amdgcn_global_atomic_fmax_num:
1990 case Intrinsic::amdgcn_global_atomic_fmin_num:
1991 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1992 case Intrinsic::amdgcn_global_load_tr_b64:
1993 case Intrinsic::amdgcn_global_load_tr_b128:
1994 case Intrinsic::amdgcn_global_load_tr4_b64:
1995 case Intrinsic::amdgcn_global_load_tr6_b96:
1996 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1997 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1998 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1999 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
2000 case Intrinsic::amdgcn_av_load_b128:
2001 case Intrinsic::amdgcn_av_store_b128:
2002 Ptr =
II->getArgOperand(0);
2004 case Intrinsic::amdgcn_load_to_lds:
2005 case Intrinsic::amdgcn_load_async_to_lds:
2006 case Intrinsic::amdgcn_global_load_lds:
2007 case Intrinsic::amdgcn_global_load_async_lds:
2008 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2009 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2010 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2011 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2012 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2013 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2014 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2015 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2016 Ptr =
II->getArgOperand(1);
2021 AccessTy =
II->getType();
2027 unsigned AddrSpace)
const {
2028 if (!Subtarget->hasFlatInstOffsets()) {
2035 FlatAddrSpace FlatVariant =
2038 : FlatAddrSpace::FLAT;
2040 return AM.
Scale == 0 &&
2041 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2042 AM.
BaseOffs, AddrSpace, FlatVariant));
2046 if (Subtarget->hasFlatGlobalInsts())
2049 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2062 return isLegalMUBUFAddressingMode(AM);
2065bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2076 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2088 if (AM.HasBaseReg) {
2120 return isLegalMUBUFAddressingMode(AM);
2122 if (!Subtarget->hasScalarSubwordLoads()) {
2127 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2175 return Subtarget->hasFlatScratchEnabled()
2177 : isLegalMUBUFAddressingMode(AM);
2224 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2233 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2236 Align RequiredAlignment(
2238 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2239 Alignment < RequiredAlignment)
2254 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2260 RequiredAlignment =
Align(4);
2262 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2278 *IsFast = (Alignment >= RequiredAlignment) ? 64
2279 : (Alignment <
Align(4)) ? 32
2286 if (!Subtarget->hasDS96AndDS128())
2292 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2301 *IsFast = (Alignment >= RequiredAlignment) ? 96
2302 : (Alignment <
Align(4)) ? 32
2309 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2315 RequiredAlignment =
Align(8);
2317 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2326 *IsFast = (Alignment >= RequiredAlignment) ? 128
2327 : (Alignment <
Align(4)) ? 32
2344 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2346 return Alignment >= RequiredAlignment ||
2347 Subtarget->hasUnalignedDSAccessEnabled();
2355 bool AlignedBy4 = Alignment >=
Align(4);
2356 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2358 *IsFast = AlignedBy4 ?
Size : 1;
2363 *IsFast = AlignedBy4;
2374 return Alignment >=
Align(4) ||
2375 Subtarget->hasUnalignedBufferAccessEnabled();
2388 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2403 return Size >= 32 && Alignment >=
Align(4);
2408 unsigned *IsFast)
const {
2410 Alignment, Flags, IsFast);
2421 if (
Op.size() >= 16 &&
2425 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2443 unsigned DestAS)
const {
2446 Subtarget->hasGloballyAddressableScratch()) {
2477 unsigned Index)
const {
2491 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2496 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2523 if (Subtarget->hasScalarSubwordLoads() &&
N->getOpcode() ==
ISD::LOAD &&
2574 auto [InputPtrReg, RC, ArgTy] =
2590 const SDLoc &SL)
const {
2597 const SDLoc &SL)
const {
2600 std::optional<uint32_t> KnownSize =
2602 if (KnownSize.has_value())
2629 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2644SDValue SITargetLowering::lowerKernargMemParameter(
2649 MachinePointerInfo PtrInfo =
2658 int64_t OffsetDiff =
Offset - AlignDownOffset;
2664 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2665 SDValue
Load = DAG.
getLoad(MVT::i32, SL, Chain, Ptr,
2670 SDValue ShiftAmt = DAG.
getConstant(OffsetDiff * 8, SL, MVT::i32);
2675 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2680 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2685 SDValue Val = convertArgType(DAG, VT, MemVT, SL,
Load,
Signed, Arg);
2694 const SDLoc &SL)
const {
2763 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2766 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2767 if (ConvertedVal == ArgValue)
2768 return ConvertedVal;
2773SDValue SITargetLowering::lowerWorkGroupId(
2778 if (!Subtarget->hasClusters())
2779 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2787 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2788 SDLoc SL(ClusterIdXYZ);
2789 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2791 SDValue ClusterSizeXYZ = DAG.
getNode(
ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2792 SDValue ClusterWorkGroupIdXYZ =
2793 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2794 SDValue GlobalIdXYZ =
2803 return ClusterIdXYZ;
2805 using namespace AMDGPU::Hwreg;
2806 SDValue ClusterIdField =
2809 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2810 SDValue ClusterId(GetReg, 0);
2820SDValue SITargetLowering::getPreloadedValue(
2823 const ArgDescriptor *
Reg =
nullptr;
2828 const ArgDescriptor WorkGroupIDX =
2836 const ArgDescriptor WorkGroupIDZ =
2838 const ArgDescriptor ClusterWorkGroupIDX =
2840 const ArgDescriptor ClusterWorkGroupIDY =
2842 const ArgDescriptor ClusterWorkGroupIDZ =
2844 const ArgDescriptor ClusterWorkGroupMaxIDX =
2846 const ArgDescriptor ClusterWorkGroupMaxIDY =
2848 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2850 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2853 auto LoadConstant = [&](
unsigned N) {
2857 if (Subtarget->hasArchitectedSGPRs() &&
2864 Reg = &WorkGroupIDX;
2865 RC = &AMDGPU::SReg_32RegClass;
2869 Reg = &WorkGroupIDY;
2870 RC = &AMDGPU::SReg_32RegClass;
2874 Reg = &WorkGroupIDZ;
2875 RC = &AMDGPU::SReg_32RegClass;
2879 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2880 return LoadConstant(0);
2881 Reg = &ClusterWorkGroupIDX;
2882 RC = &AMDGPU::SReg_32RegClass;
2886 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2887 return LoadConstant(0);
2888 Reg = &ClusterWorkGroupIDY;
2889 RC = &AMDGPU::SReg_32RegClass;
2893 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2894 return LoadConstant(0);
2895 Reg = &ClusterWorkGroupIDZ;
2896 RC = &AMDGPU::SReg_32RegClass;
2901 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2902 Reg = &ClusterWorkGroupMaxIDX;
2903 RC = &AMDGPU::SReg_32RegClass;
2908 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2909 Reg = &ClusterWorkGroupMaxIDY;
2910 RC = &AMDGPU::SReg_32RegClass;
2915 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2916 Reg = &ClusterWorkGroupMaxIDZ;
2917 RC = &AMDGPU::SReg_32RegClass;
2921 Reg = &ClusterWorkGroupMaxFlatID;
2922 RC = &AMDGPU::SReg_32RegClass;
2953 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2957 "vector type argument should have been split");
2962 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2970 "unexpected vector split in ps argument type");
2984 Info->markPSInputAllocated(PSInputNum);
2986 Info->markPSInputEnabled(PSInputNum);
3002 if (Info.hasWorkItemIDX()) {
3008 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3012 if (Info.hasWorkItemIDY()) {
3013 assert(Info.hasWorkItemIDX());
3014 if (Subtarget->hasPackedTID()) {
3015 Info.setWorkItemIDY(
3018 unsigned Reg = AMDGPU::VGPR1;
3026 if (Info.hasWorkItemIDZ()) {
3027 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3028 if (Subtarget->hasPackedTID()) {
3029 Info.setWorkItemIDZ(
3032 unsigned Reg = AMDGPU::VGPR2;
3043 unsigned NumArgRegs) {
3046 if (RegIdx == ArgSGPRs.
size())
3049 unsigned Reg = ArgSGPRs[RegIdx];
3094 const unsigned Mask = 0x3ff;
3103 auto &
ArgInfo = Info.getArgInfo();
3115 if (Info.hasImplicitArgPtr())
3123 if (Info.hasWorkGroupIDX())
3126 if (Info.hasWorkGroupIDY())
3129 if (Info.hasWorkGroupIDZ())
3132 if (Info.hasLDSKernelId())
3143 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3144 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3150 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3151 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3156 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3157 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3163 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3169 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3178 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3183 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3184 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3189 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3190 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3205 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3207 bool InPreloadSequence =
true;
3209 bool AlignedForImplictArgs =
false;
3210 unsigned ImplicitArgOffset = 0;
3211 for (
auto &Arg :
F.args()) {
3212 if (!InPreloadSequence || !Arg.hasInRegAttr())
3215 unsigned ArgIdx = Arg.getArgNo();
3218 if (InIdx < Ins.
size() &&
3219 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3222 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3223 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3225 assert(ArgLocs[ArgIdx].isMemLoc());
3226 auto &ArgLoc = ArgLocs[InIdx];
3228 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3230 unsigned NumAllocSGPRs =
3231 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3234 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3235 if (!AlignedForImplictArgs) {
3237 alignTo(LastExplicitArgOffset,
3238 Subtarget->getAlignmentForImplicitArgPtr()) -
3239 LastExplicitArgOffset;
3240 AlignedForImplictArgs =
true;
3242 ArgOffset += ImplicitArgOffset;
3246 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3247 assert(InIdx >= 1 &&
"No previous SGPR");
3248 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3249 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3253 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3254 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3257 InPreloadSequence =
false;
3263 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3265 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3267 if (PreloadRegs->
size() > 1)
3268 RC = &AMDGPU::SGPR_32RegClass;
3269 for (
auto &Reg : *PreloadRegs) {
3275 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3284 if (Info.hasLDSKernelId()) {
3285 Register Reg = Info.addLDSKernelId();
3286 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3295 bool IsShader)
const {
3296 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3297 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3303 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3305 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3309 unsigned NumRequiredSystemSGPRs =
3310 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3311 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3312 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3313 Register Reg = Info.addReservedUserSGPR();
3314 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3319 if (!HasArchitectedSGPRs) {
3320 if (Info.hasWorkGroupIDX()) {
3321 Register Reg = Info.addWorkGroupIDX();
3322 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3326 if (Info.hasWorkGroupIDY()) {
3327 Register Reg = Info.addWorkGroupIDY();
3328 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3332 if (Info.hasWorkGroupIDZ()) {
3333 Register Reg = Info.addWorkGroupIDZ();
3334 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3339 if (Info.hasWorkGroupInfo()) {
3340 Register Reg = Info.addWorkGroupInfo();
3341 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3345 if (Info.hasPrivateSegmentWaveByteOffset()) {
3347 unsigned PrivateSegmentWaveByteOffsetReg;
3350 PrivateSegmentWaveByteOffsetReg =
3351 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3355 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3357 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3360 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3362 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3363 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3366 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3367 Info.getNumPreloadedSGPRs() >= 16);
3382 if (HasStackObjects)
3383 Info.setHasNonSpillStackObjects(
true);
3388 HasStackObjects =
true;
3392 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3394 if (!ST.hasFlatScratchEnabled()) {
3395 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3402 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3404 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3414 Info.setScratchRSrcReg(ReservedBufferReg);
3433 if (!MRI.
isLiveIn(AMDGPU::SGPR32)) {
3434 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3441 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3443 Info.setStackPtrOffsetReg(
Reg);
3448 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3455 if (ST.getFrameLowering()->hasFP(MF)) {
3456 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3472 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3481 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3482 RC = &AMDGPU::SGPR_64RegClass;
3483 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3484 RC = &AMDGPU::SGPR_32RegClass;
3490 Entry->addLiveIn(*
I);
3495 for (
auto *Exit : Exits)
3497 TII->get(TargetOpcode::COPY), *
I)
3512 bool IsError =
false;
3516 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3534 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3535 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3537 if (!Subtarget->hasFlatScratchEnabled())
3542 !Subtarget->hasArchitectedSGPRs())
3543 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3544 !Info->hasWorkGroupIDZ());
3547 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3565 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3566 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3569 Info->markPSInputAllocated(0);
3570 Info->markPSInputEnabled(0);
3572 if (Subtarget->isAmdPalOS()) {
3581 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3582 if ((PsInputBits & 0x7F) == 0 ||
3583 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3586 }
else if (IsKernel) {
3587 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3599 if (IsKernel && Subtarget->hasKernargPreload())
3603 }
else if (!IsGraphics) {
3608 if (!Subtarget->hasFlatScratchEnabled())
3620 Info->setNumWaveDispatchSGPRs(
3622 Info->setNumWaveDispatchVGPRs(
3624 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3625 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3630 if (IsWholeWaveFunc) {
3632 {MVT::i1, MVT::Other}, Chain);
3644 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3655 if (IsEntryFunc && VA.
isMemLoc()) {
3679 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3683 int64_t OffsetDiff =
Offset - AlignDownOffset;
3690 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3693 Register VReg = MRI.getLiveInVirtReg(Reg);
3701 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3702 Ins[i].Flags.isSExt(), &Ins[i]);
3710 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3713 if (PreloadRegs.
size() == 1) {
3714 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3719 TRI->getRegSizeInBits(*RC)));
3727 for (
auto Reg : PreloadRegs) {
3728 Register VReg = MRI.getLiveInVirtReg(Reg);
3734 PreloadRegs.size()),
3751 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3752 Ins[i].Flags.isSExt(), &Ins[i]);
3764 "hidden argument in kernel signature was not preloaded",
3770 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3771 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3791 if (!IsEntryFunc && VA.
isMemLoc()) {
3792 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3803 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3804 RC = &AMDGPU::VGPR_32RegClass;
3805 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3806 RC = &AMDGPU::SGPR_32RegClass;
3812 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3818 ReadFirstLane, Val);
3827 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3836 Info->setBytesInStackArgArea(StackArgSize);
3838 return Chains.
empty() ? Chain
3847 const Type *RetTy)
const {
3855 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3860 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3861 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3862 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3863 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3886 Info->setIfReturnsVoid(Outs.
empty());
3887 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3906 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3907 ++
I, ++RealRVLocIdx) {
3911 SDValue Arg = OutVals[RealRVLocIdx];
3934 ReadFirstLane, Arg);
3941 if (!Info->isEntryFunction()) {
3947 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3949 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3962 unsigned Opc = AMDGPUISD::ENDPGM;
3964 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3965 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3966 : AMDGPUISD::RET_GLUE;
4071 const auto [OutgoingArg, ArgRC, ArgTy] =
4076 const auto [IncomingArg, IncomingArgRC, Ty] =
4078 assert(IncomingArgRC == ArgRC);
4081 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4089 InputReg = getImplicitArgPtr(DAG,
DL);
4091 std::optional<uint32_t> Id =
4093 if (Id.has_value()) {
4104 if (OutgoingArg->isRegister()) {
4105 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4106 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4109 unsigned SpecialArgOffset =
4120 auto [OutgoingArg, ArgRC, Ty] =
4123 std::tie(OutgoingArg, ArgRC, Ty) =
4126 std::tie(OutgoingArg, ArgRC, Ty) =
4141 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4142 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4143 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4148 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4156 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4166 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4175 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4176 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4187 : IncomingArgY ? *IncomingArgY
4194 if (OutgoingArg->isRegister()) {
4196 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4222 if (Callee->isDivergent())
4229 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4233 if (!CallerPreserved)
4236 bool CCMatch = CallerCC == CalleeCC;
4249 if (Arg.hasByValAttr())
4263 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4264 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4273 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4286 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4288 if (!CCVA.isRegLoc())
4293 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4295 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4319enum ChainCallArgIdx {
4341 bool UsesDynamicVGPRs =
false;
4342 if (IsChainCallConv) {
4347 auto RequestedExecIt =
4349 return Arg.OrigArgIndex == 2;
4351 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4353 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4356 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4359 "Haven't popped all the special args");
4362 CLI.
Args[ChainCallArgIdx::Exec];
4363 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4371 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4373 ChainCallSpecialArgs.
push_back(Arg.Node);
4376 PushNodeOrTargetConstant(RequestedExecArg);
4382 if (FlagsValue.
isZero()) {
4383 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4385 "no additional args allowed if flags == 0");
4387 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4391 if (!Subtarget->isWave32()) {
4393 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4396 UsesDynamicVGPRs =
true;
4397 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4398 CLI.
Args.end(), PushNodeOrTargetConstant);
4407 bool IsSibCall =
false;
4421 "unsupported call to variadic function ");
4429 "unsupported required tail call to function ");
4434 Outs, OutVals, Ins, DAG);
4438 "site marked musttail or on llvm.amdgcn.cs.chain");
4445 if (!TailCallOpt && IsTailCall)
4469 if (!Subtarget->hasFlatScratchEnabled())
4490 auto *
TRI = Subtarget->getRegisterInfo();
4497 if (!IsSibCall || IsChainCallConv) {
4498 if (!Subtarget->hasFlatScratchEnabled()) {
4504 RegsToPass.emplace_back(IsChainCallConv
4505 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4506 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4513 const unsigned NumSpecialInputs = RegsToPass.size();
4515 MVT PtrVT = MVT::i32;
4518 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4546 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4554 int32_t
Offset = LocMemOffset;
4561 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4567 ? Flags.getNonZeroByValAlign()
4594 if (Outs[i].Flags.isByVal()) {
4596 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4599 Outs[i].Flags.getNonZeroByValAlign(),
4600 Outs[i].Flags.getNonZeroByValAlign(),
4602 nullptr, std::nullopt, DstInfo,
4608 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4614 if (!MemOpChains.
empty())
4630 unsigned ArgIdx = 0;
4631 for (
auto [Reg, Val] : RegsToPass) {
4632 if (ArgIdx++ >= NumSpecialInputs &&
4633 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4659 if (IsTailCall && !IsSibCall) {
4664 std::vector<SDValue>
Ops({Chain});
4670 Ops.push_back(Callee);
4687 Ops.push_back(Callee);
4698 if (IsChainCallConv)
4703 for (
auto &[Reg, Val] : RegsToPass)
4707 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4708 assert(Mask &&
"Missing call preserved mask for calling convention");
4718 MVT::Glue, GlueOps),
4723 Ops.push_back(InGlue);
4729 unsigned OPC = AMDGPUISD::TC_RETURN;
4732 OPC = AMDGPUISD::TC_RETURN_GFX;
4736 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4737 : AMDGPUISD::TC_RETURN_CHAIN;
4743 if (Info->isWholeWaveFunction())
4744 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4754 Chain =
Call.getValue(0);
4755 InGlue =
Call.getValue(1);
4757 uint64_t CalleePopBytes = NumBytes;
4778 EVT VT =
Op.getValueType();
4792 "Stack grows upwards for AMDGPU");
4794 Chain = BaseAddr.getValue(1);
4796 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4797 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4800 if (Alignment > StackAlign) {
4801 uint64_t ScaledAlignment = Alignment.value()
4802 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4803 uint64_t StackAlignMask = ScaledAlignment - 1;
4810 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4819 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4830 if (!HasFlatScratch) {
4833 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4850 if (
Op.getValueType() != MVT::i32)
4869 assert(
Op.getValueType() == MVT::i32);
4878 Op.getOperand(0), IntrinID, GetRoundBothImm);
4912 SDValue RoundModeTimesNumBits =
4932 TableEntry, EnumOffset);
4948 static_cast<uint32_t>(ConstMode->getZExtValue()),
4960 if (UseReducedTable) {
4966 SDValue RoundModeTimesNumBits =
4986 SDValue RoundModeTimesNumBits =
4995 NewMode = TruncTable;
5004 ReadFirstLaneID, NewMode);
5017 IntrinID, RoundBothImm, NewMode);
5025 return Op.getOperand(0);
5030 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5048 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5049 EVT SrcVT = Src.getValueType();
5058 EVT DstVT =
Op.getValueType();
5067 if (
Op.getValueType() != MVT::i64)
5081 Op.getOperand(0), IntrinID, ModeHwRegImm);
5083 Op.getOperand(0), IntrinID, TrapHwRegImm);
5097 if (
Op.getOperand(1).getValueType() != MVT::i64)
5109 ReadFirstLaneID, NewModeReg);
5111 ReadFirstLaneID, NewTrapReg);
5113 unsigned ModeHwReg =
5116 unsigned TrapHwReg =
5124 IntrinID, ModeHwRegImm, NewModeReg);
5127 IntrinID, TrapHwRegImm, NewTrapReg);
5135 .
Case(
"m0", AMDGPU::M0)
5136 .
Case(
"exec", AMDGPU::EXEC)
5137 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5138 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5139 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5140 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5141 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5142 .
Case(
"src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5143 .
Case(
"src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5144 .
Case(
"src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5150 if (!Subtarget->hasFlatScrRegister() &&
5151 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5154 if (!Subtarget->hasGloballyAddressableScratch() &&
5155 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5160 case AMDGPU::EXEC_LO:
5161 case AMDGPU::EXEC_HI:
5162 case AMDGPU::FLAT_SCR_LO:
5163 case AMDGPU::FLAT_SCR_HI:
5164 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5165 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5170 case AMDGPU::FLAT_SCR:
5171 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5190 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5199static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5221 auto Next = std::next(
I);
5232 MBB.addSuccessor(LoopBB);
5234 return std::pair(LoopBB, RemainderBB);
5241 auto I =
MI.getIterator();
5242 auto E = std::next(
I);
5264 Src->setIsKill(
false);
5274 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5283 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5307 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5308 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5330 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5337 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5341 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5343 .
addReg(Idx.getReg(), {}, Idx.getSubReg());
5352 if (UseGPRIdxMode) {
5354 SGPRIdxReg = CurrentIdxReg;
5357 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5368 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5401 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5402 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5410 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5429 InitResultReg, DstReg, PhiReg, TmpExec,
5430 Offset, UseGPRIdxMode, SGPRIdxReg);
5436 LoopBB->removeSuccessor(RemainderBB);
5438 LoopBB->addSuccessor(LandingPad);
5449static std::pair<unsigned, int>
5453 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5458 return std::pair(AMDGPU::sub0,
Offset);
5472 assert(Idx->getReg() != AMDGPU::NoRegister);
5497 return Idx->getReg();
5517 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5518 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5524 std::tie(SubReg,
Offset) =
5527 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5530 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5534 if (UseGPRIdxMode) {
5541 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5550 .
addReg(SrcReg, {}, SubReg)
5554 MI.eraseFromParent();
5570 UseGPRIdxMode, SGPRIdxReg);
5574 if (UseGPRIdxMode) {
5576 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5578 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5583 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5584 .
addReg(SrcReg, {}, SubReg)
5588 MI.eraseFromParent();
5605 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5613 std::tie(SubReg,
Offset) =
5615 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5617 if (Idx->getReg() == AMDGPU::NoRegister) {
5628 MI.eraseFromParent();
5633 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5637 if (UseGPRIdxMode) {
5641 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5650 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5651 TRI.getRegSizeInBits(*VecRC), 32,
false);
5657 MI.eraseFromParent();
5671 UseGPRIdxMode, SGPRIdxReg);
5674 if (UseGPRIdxMode) {
5676 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5678 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5684 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5685 TRI.getRegSizeInBits(*VecRC), 32,
false);
5686 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5692 MI.eraseFromParent();
5708 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5709 if (ST.hasScalarAddSub64()) {
5711 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5721 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5722 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5725 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5727 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5730 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5732 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5737 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5738 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5744 Hi.setOperandDead(3);
5751 MI.eraseFromParent();
5765 Register SrcCond =
MI.getOperand(3).getReg();
5773 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5775 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5777 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5779 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5782 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5784 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5787 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5789 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5792 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5794 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5816 MI.eraseFromParent();
5821 case AMDGPU::S_MIN_U32:
5822 return std::numeric_limits<uint32_t>::max();
5823 case AMDGPU::S_MIN_I32:
5824 return std::numeric_limits<int32_t>::max();
5825 case AMDGPU::S_MAX_U32:
5826 return std::numeric_limits<uint32_t>::min();
5827 case AMDGPU::S_MAX_I32:
5828 return std::numeric_limits<int32_t>::min();
5829 case AMDGPU::V_ADD_F32_e64:
5831 case AMDGPU::V_SUB_F32_e64:
5833 case AMDGPU::S_ADD_I32:
5834 case AMDGPU::S_SUB_I32:
5835 case AMDGPU::S_OR_B32:
5836 case AMDGPU::S_XOR_B32:
5837 return std::numeric_limits<uint32_t>::min();
5838 case AMDGPU::S_AND_B32:
5839 return std::numeric_limits<uint32_t>::max();
5840 case AMDGPU::V_MIN_F32_e64:
5841 case AMDGPU::V_MAX_F32_e64:
5843 case AMDGPU::V_CMP_LT_U64_e64:
5844 return std::numeric_limits<uint64_t>::max();
5845 case AMDGPU::V_CMP_LT_I64_e64:
5846 return std::numeric_limits<int64_t>::max();
5847 case AMDGPU::V_CMP_GT_U64_e64:
5848 return std::numeric_limits<uint64_t>::min();
5849 case AMDGPU::V_CMP_GT_I64_e64:
5850 return std::numeric_limits<int64_t>::min();
5851 case AMDGPU::V_MIN_F64_e64:
5852 case AMDGPU::V_MAX_F64_e64:
5853 case AMDGPU::V_MIN_NUM_F64_e64:
5854 case AMDGPU::V_MAX_NUM_F64_e64:
5855 return 0x7FF8000000000000;
5856 case AMDGPU::S_ADD_U64_PSEUDO:
5857 case AMDGPU::S_SUB_U64_PSEUDO:
5858 case AMDGPU::S_OR_B64:
5859 case AMDGPU::S_XOR_B64:
5860 return std::numeric_limits<uint64_t>::min();
5861 case AMDGPU::S_AND_B64:
5862 return std::numeric_limits<uint64_t>::max();
5863 case AMDGPU::V_ADD_F64_e64:
5864 case AMDGPU::V_ADD_F64_pseudo_e64:
5865 return 0x8000000000000000;
5872 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5873 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5874 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5875 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5876 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5877 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5878 Opc == AMDGPU::V_SUB_F32_e64;
5882 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5883 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5884 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5885 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5886 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5889static std::tuple<unsigned, unsigned>
5893 case AMDGPU::S_MIN_U32:
5894 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5896 case AMDGPU::S_MIN_I32:
5897 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5899 case AMDGPU::S_MAX_U32:
5900 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5902 case AMDGPU::S_MAX_I32:
5903 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5905 case AMDGPU::S_ADD_I32:
5906 case AMDGPU::S_SUB_I32:
5907 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5908 : AMDGPU::V_ADD_CO_U32_dpp;
5910 case AMDGPU::S_AND_B32:
5911 DPPOpc = AMDGPU::V_AND_B32_dpp;
5913 case AMDGPU::S_OR_B32:
5914 DPPOpc = AMDGPU::V_OR_B32_dpp;
5916 case AMDGPU::S_XOR_B32:
5917 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5919 case AMDGPU::V_ADD_F32_e64:
5920 case AMDGPU::V_SUB_F32_e64:
5921 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5923 case AMDGPU::V_MIN_F32_e64:
5924 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5926 case AMDGPU::V_MAX_F32_e64:
5927 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5929 case AMDGPU::V_CMP_LT_U64_e64:
5930 case AMDGPU::V_CMP_LT_I64_e64:
5931 case AMDGPU::V_CMP_GT_U64_e64:
5932 case AMDGPU::V_CMP_GT_I64_e64:
5933 case AMDGPU::S_ADD_U64_PSEUDO:
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 case AMDGPU::S_AND_B64:
5936 case AMDGPU::S_OR_B64:
5937 case AMDGPU::S_XOR_B64:
5938 case AMDGPU::V_MIN_NUM_F64_e64:
5939 case AMDGPU::V_MIN_F64_e64:
5940 case AMDGPU::V_MAX_NUM_F64_e64:
5941 case AMDGPU::V_MAX_F64_e64:
5942 case AMDGPU::V_ADD_F64_pseudo_e64:
5943 case AMDGPU::V_ADD_F64_e64:
5944 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5949 unsigned ClampOpc =
Opc;
5950 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5951 if (
Opc == AMDGPU::S_SUB_I32)
5952 ClampOpc = AMDGPU::S_ADD_I32;
5953 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5954 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5955 else if (
Opc == AMDGPU::S_AND_B64)
5956 ClampOpc = AMDGPU::V_AND_B32_e64;
5957 else if (
Opc == AMDGPU::S_OR_B64)
5958 ClampOpc = AMDGPU::V_OR_B32_e64;
5959 else if (
Opc == AMDGPU::S_XOR_B64)
5960 ClampOpc = AMDGPU::V_XOR_B32_e64;
5962 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5964 return {DPPOpc, ClampOpc};
5967static std::pair<Register, Register>
5974 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5976 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5978 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5979 return {Op1L, Op1H};
5995 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
5996 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
5998 unsigned MIOpc =
MI.getOpcode();
6012 case AMDGPU::S_MIN_U32:
6013 case AMDGPU::S_MIN_I32:
6014 case AMDGPU::V_MIN_F32_e64:
6015 case AMDGPU::S_MAX_U32:
6016 case AMDGPU::S_MAX_I32:
6017 case AMDGPU::V_MAX_F32_e64:
6018 case AMDGPU::S_AND_B32:
6019 case AMDGPU::S_OR_B32: {
6025 case AMDGPU::V_CMP_LT_U64_e64:
6026 case AMDGPU::V_CMP_LT_I64_e64:
6027 case AMDGPU::V_CMP_GT_U64_e64:
6028 case AMDGPU::V_CMP_GT_I64_e64:
6029 case AMDGPU::V_MIN_F64_e64:
6030 case AMDGPU::V_MIN_NUM_F64_e64:
6031 case AMDGPU::V_MAX_F64_e64:
6032 case AMDGPU::V_MAX_NUM_F64_e64:
6033 case AMDGPU::S_AND_B64:
6034 case AMDGPU::S_OR_B64: {
6040 case AMDGPU::S_XOR_B32:
6041 case AMDGPU::S_XOR_B64:
6042 case AMDGPU::S_ADD_I32:
6043 case AMDGPU::S_ADD_U64_PSEUDO:
6044 case AMDGPU::V_ADD_F32_e64:
6045 case AMDGPU::V_ADD_F64_e64:
6046 case AMDGPU::V_ADD_F64_pseudo_e64:
6047 case AMDGPU::S_SUB_I32:
6048 case AMDGPU::S_SUB_U64_PSEUDO:
6049 case AMDGPU::V_SUB_F32_e64: {
6056 bool IsWave32 = ST.isWave32();
6057 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6058 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6059 unsigned BitCountOpc =
6060 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6064 auto NewAccumulator =
6070 case AMDGPU::S_XOR_B32:
6071 case AMDGPU::S_XOR_B64: {
6079 .
addReg(NewAccumulator->getOperand(0).getReg())
6087 if (
Opc == AMDGPU::S_XOR_B32) {
6094 BuildRegSequence(BB,
MI, DstReg, ParityRegister, DstHi);
6099 if (
Opc == AMDGPU::S_XOR_B32) {
6116 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6120 case AMDGPU::S_SUB_I32: {
6129 .
addReg(NewAccumulator->getOperand(0).getReg());
6132 case AMDGPU::S_ADD_I32: {
6139 .
addReg(NewAccumulator->getOperand(0).getReg());
6145 .
addReg(NewAccumulator->getOperand(0).getReg());
6148 case AMDGPU::S_ADD_U64_PSEUDO:
6149 case AMDGPU::S_SUB_U64_PSEUDO: {
6169 if (
Imm == 1 &&
Opc == AMDGPU::S_ADD_U64_PSEUDO) {
6174 BuildRegSequence(BB,
MI, DstReg,
6175 NewAccumulator->getOperand(0).getReg(), DstHi);
6179 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6182 .
addReg(NewAccumulator->getOperand(0).getReg())
6192 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6194 : NewAccumulator->getOperand(0).getReg();
6198 if (ST.hasScalarMulHiInsts()) {
6209 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6212 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6219 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6225 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6231 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6234 case AMDGPU::V_ADD_F32_e64:
6235 case AMDGPU::V_ADD_F64_e64:
6236 case AMDGPU::V_ADD_F64_pseudo_e64:
6237 case AMDGPU::V_SUB_F32_e64: {
6244 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6245 : AMDGPU::V_CVT_F64_I32_e64),
6247 .
addReg(NewAccumulator->getOperand(0).getReg())
6252 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6253 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6256 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6258 ? AMDGPU::V_MUL_F64_pseudo_e64
6259 : AMDGPU::V_MUL_F64_e64;
6269 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6286 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6298 bool NeedsMovDPP = !is32BitOpc;
6303 bool IsWave32 = ST.isWave32();
6304 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6305 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6306 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6332 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6336 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6337 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6346 I = ComputeLoop->begin();
6348 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6352 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6356 I = ComputeLoop->end();
6360 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6365 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6366 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6367 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6368 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6370 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6372 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6374 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6375 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6379 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6383 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6385 OpDstReg = VgprResultReg;
6386 LaneValueReg = LaneValVgpr;
6389 if (hasSrc0Modifier)
6391 OpInstr.addReg(AccumulatorReg);
6392 if (hasSrc1Modifier)
6394 OpInstr.addReg(LaneValueReg);
6402 OpInstr.setOperandDead(3);
6403 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6404 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6418 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6422 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6426 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6427 LaneValueLoReg, LaneValueHiReg);
6429 case AMDGPU::S_OR_B64:
6430 case AMDGPU::S_AND_B64:
6431 case AMDGPU::S_XOR_B64: {
6434 .
addReg(LaneValue->getOperand(0).getReg())
6438 case AMDGPU::V_CMP_GT_I64_e64:
6439 case AMDGPU::V_CMP_GT_U64_e64:
6440 case AMDGPU::V_CMP_LT_I64_e64:
6441 case AMDGPU::V_CMP_LT_U64_e64: {
6446 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6448 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6452 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6455 .
addReg(LaneValue->getOperand(0).getReg())
6456 .
addReg(AccumulatorVReg);
6458 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6459 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6463 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6464 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6465 .
addReg(LaneValue->getOperand(0).getReg())
6469 case AMDGPU::V_MIN_F64_e64:
6470 case AMDGPU::V_MIN_NUM_F64_e64:
6471 case AMDGPU::V_MAX_F64_e64:
6472 case AMDGPU::V_MAX_NUM_F64_e64:
6473 case AMDGPU::V_ADD_F64_e64:
6474 case AMDGPU::V_ADD_F64_pseudo_e64: {
6476 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6478 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6485 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6488 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6494 .
addReg(LaneValue->getOperand(0).getReg())
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6504 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6506 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6508 ReadLaneLo.addReg(Op1L);
6509 ReadLaneHi.addReg(Op1H);
6511 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6514 case AMDGPU::S_ADD_U64_PSEUDO:
6515 case AMDGPU::S_SUB_U64_PSEUDO: {
6518 .
addReg(LaneValue->getOperand(0).getReg())
6527 unsigned BITSETOpc =
6528 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6529 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6535 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6539 if (!ST.hasScalarCompareEq64()) {
6542 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6544 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6547 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6548 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6550 SetSCCInstr.
addReg(NewActiveBitsReg);
6551 if (ST.hasScalarCompareEq64())
6554 SetSCCInstr.
addReg(NewActiveBitsReg);
6555 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6560 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6577 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6581 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6582 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6585 auto IdentityCopyInstr =
6588 unsigned DPPOpc, ClampOpc;
6604 if (isFPOp && !NeedsMovDPP)
6607 if (isFPOp && !NeedsMovDPP)
6611 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6620 bool isAddSub =
false,
6621 bool needsCarryIn =
false,
6623 unsigned InstrOpc = ClampOpc;
6626 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6627 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6632 ClampInstr.addReg(CarryOutReg,
6638 ClampInstr.addReg(Src0);
6641 ClampInstr.addReg(Src1);
6643 ClampInstr.addReg(CarryIn);
6644 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6645 ClampInstr.addImm(0);
6647 ClampInstr.addImm(0);
6648 LastBcastInstr = ClampInstr;
6653 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6654 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6655 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6657 if (isAddSubOpc || isBitWiseOpc) {
6664 auto [Src0Lo, Src0Hi] =
6666 auto [Src1Lo, Src1Hi] =
6668 Register CarryReg = BuildClampInstr(
6669 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6670 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6671 isAddSubOpc, CarryReg);
6672 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6701 SrcWithIdentityInstr =
6702 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6709 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6710 auto [SrcReg0Sub0, SrcReg0Sub1] =
6713 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6715 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6716 SrcWithIdentityInstr =
6717 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6724 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6727 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6729 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6732 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6734 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6737 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6739 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6742 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6744 if (ST.hasDPPBroadcasts()) {
6747 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6762 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6783 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6786 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6788 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6791 FinalDPPResult = RowBcast15;
6793 if (ST.hasDPPBroadcasts()) {
6796 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6812 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6816 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6822 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6830 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6835 .
addReg(ShiftedThreadID);
6840 .
addReg(PermuteByteOffset)
6850 auto [RowBcast15Lo, RowBcast15Hi] =
6854 .
addReg(PermuteByteOffset)
6859 .
addReg(PermuteByteOffset)
6862 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6866 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6868 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6870 FinalDPPResult = RowBcast31;
6872 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6873 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6883 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6886 FinalDPPResult = NegatedValVGPR;
6893 .
addImm(ST.getWavefrontSize() - 1);
6908 .
addImm(ST.getWavefrontSize() - 1);
6912 .
addImm(ST.getWavefrontSize() - 1);
6913 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6916 if (
Opc == AMDGPU::S_SUB_I32) {
6917 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6921 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6922 auto NegatedValInstr =
6931 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6937 MI.eraseFromParent();
6952 switch (
MI.getOpcode()) {
6953 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6955 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6957 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6959 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6961 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6963 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6966 ? AMDGPU::V_MIN_NUM_F64_e64
6967 : AMDGPU::V_MIN_F64_e64);
6968 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6970 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6972 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6974 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6976 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6978 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6981 ? AMDGPU::V_MAX_NUM_F64_e64
6982 : AMDGPU::V_MAX_F64_e64);
6983 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6985 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6987 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6989 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6992 ? AMDGPU::V_ADD_F64_pseudo_e64
6993 : AMDGPU::V_ADD_F64_e64);
6994 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6996 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6998 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
7000 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7005 ? AMDGPU::V_ADD_F64_pseudo_e64
7006 : AMDGPU::V_ADD_F64_e64);
7007 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7009 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7011 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7013 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7015 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7017 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7019 case AMDGPU::S_UADDO_PSEUDO:
7020 case AMDGPU::S_USUBO_PSEUDO: {
7026 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7028 : AMDGPU::S_SUB_U32;
7036 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7039 MI.eraseFromParent();
7042 case AMDGPU::S_ADD_U64_PSEUDO:
7043 case AMDGPU::S_SUB_U64_PSEUDO: {
7046 case AMDGPU::V_ADD_U64_PSEUDO:
7047 case AMDGPU::V_SUB_U64_PSEUDO: {
7048 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7054 if (ST.hasAddSubU64Insts()) {
7056 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7057 : AMDGPU::V_SUB_U64_e64),
7062 TII->legalizeOperands(*
I);
7063 MI.eraseFromParent();
7067 if (IsAdd && ST.hasLshlAddU64Inst()) {
7073 TII->legalizeOperands(*
Add);
7074 MI.eraseFromParent();
7078 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7088 : &AMDGPU::VReg_64RegClass;
7091 : &AMDGPU::VReg_64RegClass;
7094 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7096 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7099 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7101 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7104 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7106 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7109 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7116 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7130 TII->legalizeOperands(*LoHalf);
7131 TII->legalizeOperands(*HiHalf);
7132 MI.eraseFromParent();
7135 case AMDGPU::S_ADD_CO_PSEUDO:
7136 case AMDGPU::S_SUB_CO_PSEUDO: {
7146 if (Src0.isReg() &&
TRI->isVectorRegister(MRI, Src0.getReg())) {
7148 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7150 Src0.setReg(RegOp0);
7152 if (Src1.isReg() &&
TRI->isVectorRegister(MRI, Src1.getReg())) {
7154 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7156 Src1.setReg(RegOp1);
7159 if (
TRI->isVectorRegister(MRI, Src2.getReg())) {
7160 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7162 Src2.setReg(RegOp2);
7165 if (ST.isWave64()) {
7166 if (ST.hasScalarCompareEq64()) {
7173 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7175 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7177 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7180 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7194 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7195 ? AMDGPU::S_ADDC_U32
7196 : AMDGPU::S_SUBB_U32;
7201 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7207 MI.eraseFromParent();
7210 case AMDGPU::SI_INIT_M0: {
7213 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7216 MI.eraseFromParent();
7219 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7222 TII->get(AMDGPU::S_CMP_EQ_U32))
7227 case AMDGPU::GET_GROUPSTATICSIZE: {
7231 .
add(
MI.getOperand(0))
7233 MI.eraseFromParent();
7236 case AMDGPU::GET_SHADERCYCLESHILO: {
7251 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7254 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7257 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7266 .
add(
MI.getOperand(0))
7271 MI.eraseFromParent();
7274 case AMDGPU::SI_INDIRECT_SRC_V1:
7275 case AMDGPU::SI_INDIRECT_SRC_V2:
7276 case AMDGPU::SI_INDIRECT_SRC_V3:
7277 case AMDGPU::SI_INDIRECT_SRC_V4:
7278 case AMDGPU::SI_INDIRECT_SRC_V5:
7279 case AMDGPU::SI_INDIRECT_SRC_V6:
7280 case AMDGPU::SI_INDIRECT_SRC_V7:
7281 case AMDGPU::SI_INDIRECT_SRC_V8:
7282 case AMDGPU::SI_INDIRECT_SRC_V9:
7283 case AMDGPU::SI_INDIRECT_SRC_V10:
7284 case AMDGPU::SI_INDIRECT_SRC_V11:
7285 case AMDGPU::SI_INDIRECT_SRC_V12:
7286 case AMDGPU::SI_INDIRECT_SRC_V16:
7287 case AMDGPU::SI_INDIRECT_SRC_V32:
7289 case AMDGPU::SI_INDIRECT_DST_V1:
7290 case AMDGPU::SI_INDIRECT_DST_V2:
7291 case AMDGPU::SI_INDIRECT_DST_V3:
7292 case AMDGPU::SI_INDIRECT_DST_V4:
7293 case AMDGPU::SI_INDIRECT_DST_V5:
7294 case AMDGPU::SI_INDIRECT_DST_V6:
7295 case AMDGPU::SI_INDIRECT_DST_V7:
7296 case AMDGPU::SI_INDIRECT_DST_V8:
7297 case AMDGPU::SI_INDIRECT_DST_V9:
7298 case AMDGPU::SI_INDIRECT_DST_V10:
7299 case AMDGPU::SI_INDIRECT_DST_V11:
7300 case AMDGPU::SI_INDIRECT_DST_V12:
7301 case AMDGPU::SI_INDIRECT_DST_V16:
7302 case AMDGPU::SI_INDIRECT_DST_V32:
7304 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7305 case AMDGPU::SI_KILL_I1_PSEUDO:
7307 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7311 case AMDGPU::SI_BR_UNDEF: {
7313 .
add(
MI.getOperand(0));
7315 MI.eraseFromParent();
7318 case AMDGPU::ADJCALLSTACKUP:
7319 case AMDGPU::ADJCALLSTACKDOWN: {
7326 case AMDGPU::SI_CALL_ISEL: {
7327 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7338 MI.eraseFromParent();
7341 case AMDGPU::V_ADDC_U32_e32:
7342 case AMDGPU::V_SUBB_U32_e32:
7343 case AMDGPU::V_SUBBREV_U32_e32:
7346 TII->legalizeOperands(
MI);
7348 case AMDGPU::DS_GWS_INIT:
7349 case AMDGPU::DS_GWS_SEMA_BR:
7350 case AMDGPU::DS_GWS_BARRIER:
7351 case AMDGPU::DS_GWS_SEMA_V:
7352 case AMDGPU::DS_GWS_SEMA_P:
7353 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7361 case AMDGPU::S_SETREG_B32: {
7371 auto [ID,
Offset, Width] =
7377 const unsigned SetMask = WidthMask <<
Offset;
7380 unsigned SetDenormOp = 0;
7381 unsigned SetRoundOp = 0;
7389 SetRoundOp = AMDGPU::S_ROUND_MODE;
7390 SetDenormOp = AMDGPU::S_DENORM_MODE;
7392 SetRoundOp = AMDGPU::S_ROUND_MODE;
7394 SetDenormOp = AMDGPU::S_DENORM_MODE;
7397 if (SetRoundOp || SetDenormOp) {
7399 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7400 unsigned ImmVal = Def->getOperand(1).getImm();
7414 MI.eraseFromParent();
7423 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7427 case AMDGPU::S_INVERSE_BALLOT_U32:
7428 case AMDGPU::S_INVERSE_BALLOT_U64:
7431 MI.setDesc(
TII->get(AMDGPU::COPY));
7433 case AMDGPU::ENDPGM_TRAP: {
7435 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7455 MI.eraseFromParent();
7458 case AMDGPU::SIMULATED_TRAP: {
7459 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7461 TII->insertSimulatedTrap(MRI, *BB,
MI,
MI.getDebugLoc());
7462 MI.eraseFromParent();
7465 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7466 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7472 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7473 Register OriginalExec = Setup->getOperand(0).getReg();
7475 MI.getOperand(0).setReg(OriginalExec);
7478 case AMDGPU::V_DOT2_F32_F16:
7479 case AMDGPU::V_DOT2_F32_BF16: {
7486 case AMDGPU::SCHED_BARRIER:
7487 case AMDGPU::SCHED_GROUP_BARRIER:
7488 MI.getOperand(0).setImm(
MI.getOperand(0).getImm() &
7525 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7529 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7558 if (!Subtarget->hasMadMacF32Insts())
7559 return Subtarget->hasFastFMAF32();
7565 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7568 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7574 return Subtarget->has16BitInsts() &&
7592 F.getDenormalFPEnv());
7597 switch (Ty.getScalarSizeInBits()) {
7615 return Subtarget->hasMadMacF32Insts() &&
7618 return Subtarget->hasMadF16() &&
7629 if (Ty.getScalarSizeInBits() == 16)
7631 if (Ty.getScalarSizeInBits() == 32)
7646 F.getDenormalFPEnv());
7657 unsigned Opc =
Op.getOpcode();
7658 EVT VT =
Op.getValueType();
7670 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7671 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7684 [[maybe_unused]]
EVT VT =
Op.getValueType();
7686 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7687 VT == MVT::v16i32) &&
7688 "Unexpected ValueType.");
7697 unsigned Opc =
Op.getOpcode();
7698 EVT VT =
Op.getValueType();
7707 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7709 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7716 unsigned Opc =
Op.getOpcode();
7717 EVT VT =
Op.getValueType();
7734 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7736 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7742 switch (
Op.getOpcode()) {
7746 return LowerBRCOND(
Op, DAG);
7748 return LowerRETURNADDR(
Op, DAG);
7750 return LowerSPONENTRY(
Op, DAG);
7753 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7754 "Load should return a value and a chain");
7758 EVT VT =
Op.getValueType();
7760 return lowerFSQRTF32(
Op, DAG);
7762 return lowerFSQRTF64(
Op, DAG);
7767 return LowerTrig(
Op, DAG);
7769 return LowerSELECT(
Op, DAG);
7771 return LowerFDIV(
Op, DAG);
7773 return LowerFFREXP(
Op, DAG);
7775 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7777 return LowerSTORE(
Op, DAG);
7781 return LowerGlobalAddress(MFI,
Op, DAG);
7786 return LowerExternalSymbol(
Op, DAG);
7788 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7790 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7792 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7794 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7796 return LowerINTRINSIC_VOID(
Op, DAG);
7798 return lowerADDRSPACECAST(
Op, DAG);
7800 return lowerINSERT_SUBVECTOR(
Op, DAG);
7802 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7804 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7806 return lowerVECTOR_SHUFFLE(
Op, DAG);
7808 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7810 return lowerBUILD_VECTOR(
Op, DAG);
7813 return lowerFP_ROUND(
Op, DAG);
7815 return lowerTRAP(
Op, DAG);
7817 return lowerDEBUGTRAP(
Op, DAG);
7826 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7827 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7831 if (
Op.getValueType() == MVT::bf16) {
7861 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7864 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7867 return lowerFLDEXP(
Op, DAG);
7872 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7873 Op.getOperand(0).getValueType() == MVT::f32) {
7899 return lowerFCOPYSIGN(
Op, DAG);
7901 return lowerMUL(
Op, DAG);
7904 return lowerXMULO(
Op, DAG);
7907 return lowerXMUL_LOHI(
Op, DAG);
7928 return LowerINLINEASM(
Op, DAG);
7934static std::pair<SDValue, SDValue>
7964 EVT FittingLoadVT = LoadVT;
7996SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7999 bool IsIntrinsic)
const {
8002 bool IsTFE =
M->getNumValues() == 3;
8003 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8004 EVT LoadVT =
M->getValueType(0);
8006 EVT EquivLoadVT = LoadVT;
8023 SDVTList VTList = DAG.
getVTList(LoadDWordsVT, MVT::Other);
8025 Opcode,
DL, VTList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
8033 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
8037 M->getMemoryVT(),
M->getMemOperand());
8048 EVT LoadVT =
M->getValueType(0);
8057 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
8061 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
8062 bool IsTFE =
M->getNumValues() == 3;
8064 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8067 "TFE D16 format buffer load is not supported on this GPU",
8070 M->getOperand(0),
DL);
8073 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8074 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8075 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8076 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8077 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8078 : AMDGPUISD::BUFFER_LOAD;
8081 return adjustLoadValueType(
Opc, M, DAG,
Ops);
8085 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
8089 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
8090 M->getMemOperand(), DAG);
8094 SDVTList VTList = IsTFE ? DAG.
getVTList(CastVT, MVT::i32, MVT::Other)
8096 SDValue MemNode = getMemIntrinsicNode(
Opc,
DL, VTList,
Ops, CastVT,
8097 M->getMemOperand(), DAG);
8107 EVT VT =
N->getValueType(0);
8131 Exec = AMDGPU::EXEC_LO;
8133 Exec = AMDGPU::EXEC;
8150 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8152 EVT VT =
Op.getValueType();
8157 if (VT != MVT::i32) {
8165 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8174 EVT VT =
N->getValueType(0);
8176 unsigned IID =
N->getConstantOperandVal(0);
8177 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8178 IID == Intrinsic::amdgcn_permlanex16;
8179 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8180 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8181 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8182 IID == Intrinsic::amdgcn_permlane_up ||
8183 IID == Intrinsic::amdgcn_permlane_down ||
8184 IID == Intrinsic::amdgcn_permlane_xor;
8189 unsigned SplitSize = 32;
8190 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8191 ST->hasDPALU_DPP() &&
8199 case Intrinsic::amdgcn_permlane16:
8200 case Intrinsic::amdgcn_permlanex16:
8201 case Intrinsic::amdgcn_update_dpp:
8206 case Intrinsic::amdgcn_writelane:
8207 case Intrinsic::amdgcn_permlane_bcast:
8208 case Intrinsic::amdgcn_permlane_up:
8209 case Intrinsic::amdgcn_permlane_down:
8210 case Intrinsic::amdgcn_permlane_xor:
8213 case Intrinsic::amdgcn_readlane:
8214 case Intrinsic::amdgcn_set_inactive:
8215 case Intrinsic::amdgcn_set_inactive_chain_arg:
8216 case Intrinsic::amdgcn_mov_dpp8:
8219 case Intrinsic::amdgcn_readfirstlane:
8220 case Intrinsic::amdgcn_permlane64:
8230 if (
SDNode *GL =
N->getGluedNode()) {
8232 GL = GL->getOperand(0).getNode();
8242 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8243 IID == Intrinsic::amdgcn_mov_dpp8 ||
8244 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8245 IsPermlaneShuffle) {
8246 Src1 =
N->getOperand(2);
8247 if (IID == Intrinsic::amdgcn_writelane ||
8248 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8250 Src2 =
N->getOperand(3);
8253 if (ValSize == SplitSize) {
8263 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8268 if (IID == Intrinsic::amdgcn_writelane) {
8273 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8275 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8278 if (ValSize % SplitSize != 0)
8282 EVT VT =
N->getValueType(0);
8286 unsigned NumOperands =
N->getNumOperands();
8288 SDNode *GL =
N->getGluedNode();
8293 for (
unsigned i = 0; i != NE; ++i) {
8294 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8296 SDValue Operand =
N->getOperand(j);
8326 if (SplitSize == 32) {
8328 return unrollLaneOp(LaneOp.
getNode());
8334 unsigned SubVecNumElt =
8338 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8339 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8343 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8349 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8350 }
else if (IID == Intrinsic::amdgcn_writelane) {
8354 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8356 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8359 EltIdx += SubVecNumElt;
8373 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8376 if (IID == Intrinsic::amdgcn_writelane)
8379 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8386 EVT VT =
N->getValueType(0);
8404 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8414 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8415 {ShiftedIndex, ValueI32});
8425 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8426 {ValueI32, PoisonVal});
8427 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8428 {ShiftedIndex, PoisonVal});
8431 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8434 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8435 {WWMIndex, WWMValue});
8436 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8437 MVT::i32, {WWMIndex, Swapped});
8439 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8447 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8455 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8465 switch (
N->getOpcode()) {
8482 unsigned IID =
N->getConstantOperandVal(0);
8484 case Intrinsic::amdgcn_wave_reduce_min:
8485 case Intrinsic::amdgcn_wave_reduce_umin:
8486 case Intrinsic::amdgcn_wave_reduce_max:
8487 case Intrinsic::amdgcn_wave_reduce_umax:
8488 case Intrinsic::amdgcn_wave_reduce_add:
8489 case Intrinsic::amdgcn_wave_reduce_sub:
8490 case Intrinsic::amdgcn_wave_reduce_and:
8491 case Intrinsic::amdgcn_wave_reduce_or:
8492 case Intrinsic::amdgcn_wave_reduce_xor: {
8493 EVT VT =
N->getValueType(0);
8497 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8498 IID == Intrinsic::amdgcn_wave_reduce_max ||
8499 IID == Intrinsic::amdgcn_wave_reduce_add ||
8500 IID == Intrinsic::amdgcn_wave_reduce_sub;
8504 N->getOperand(0), ExtSrc,
N->getOperand(2));
8508 case Intrinsic::amdgcn_make_buffer_rsrc:
8509 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8511 case Intrinsic::amdgcn_cvt_pkrtz: {
8516 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8520 case Intrinsic::amdgcn_cvt_pknorm_i16:
8521 case Intrinsic::amdgcn_cvt_pknorm_u16:
8522 case Intrinsic::amdgcn_cvt_pk_i16:
8523 case Intrinsic::amdgcn_cvt_pk_u16: {
8529 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8530 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8531 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8532 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8533 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8534 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8536 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8538 EVT VT =
N->getValueType(0);
8547 case Intrinsic::amdgcn_s_buffer_load: {
8549 EVT VT =
Op.getValueType();
8551 Op.getOperand(1),
Op.getOperand(2),
8552 Op.getOperand(3), DAG));
8555 case Intrinsic::amdgcn_dead: {
8556 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8564 if (
N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8565 N->getValueType(0).isSimple() &&
8566 SBufferLoadDiagnosticVTs[
N->getSimpleValueType(0).SimpleTy])
8571 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8572 Results.push_back(Res.getOperand(
I));
8575 for (
unsigned I = 0;
I <
N->getNumValues(); ++
I)
8576 Results.push_back(Res.getValue(
I));
8585 EVT VT =
N->getValueType(0);
8590 EVT SelectVT = NewVT;
8591 if (NewVT.
bitsLT(MVT::i32)) {
8594 SelectVT = MVT::i32;
8600 if (NewVT != SelectVT)
8606 if (
N->getValueType(0) != MVT::v2f16)
8618 if (
N->getValueType(0) != MVT::v2f16)
8630 if (
N->getValueType(0) != MVT::f16)
8645 if (U.get() !=
Value)
8648 if (U.getUser()->getOpcode() == Opcode)
8654unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8657 case Intrinsic::amdgcn_if:
8658 return AMDGPUISD::IF;
8659 case Intrinsic::amdgcn_else:
8660 return AMDGPUISD::ELSE;
8661 case Intrinsic::amdgcn_loop:
8662 return AMDGPUISD::LOOP;
8663 case Intrinsic::amdgcn_end_cf:
8683 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8707 assert(GVar->isDeclaration() &&
8708 "AS 3 & 13 GVs should be declaration here "
8709 "when object linking is enabled");
8724 SDNode *Intr = BRCOND.getOperand(1).getNode();
8741 Intr =
LHS.getNode();
8749 assert(BR &&
"brcond missing unconditional branch user");
8754 unsigned CFNode = isCFIntrinsic(Intr);
8774 Ops.push_back(Target);
8782 SDValue
Ops[] = {SDValue(Result, 0),
BRCOND.getOperand(0)};
8789 SDValue
Ops[] = {
BR->getOperand(0),
BRCOND.getOperand(2)};
8794 SDValue Chain = SDValue(Result,
Result->getNumValues() - 1);
8797 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8803 SDValue(Result, i - 1), SDValue());
8816 MVT VT =
Op.getSimpleValueType();
8819 if (
Op.getConstantOperandVal(0) != 0)
8823 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8825 if (
Info->isEntryFunction())
8842 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8856 return Op.getValueType().bitsLE(VT)
8864 EVT DstVT =
Op.getValueType();
8871 unsigned Opc =
Op.getOpcode();
8872 SDValue
Flags =
Op.getOperand(1);
8882 bool IsStrict =
Op->isStrictFPOpcode();
8883 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8884 EVT SrcVT = Src.getValueType();
8885 EVT DstVT =
Op.getValueType();
8888 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8891 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8898 if (DstVT == MVT::f16) {
8903 if (!Subtarget->has16BitInsts()) {
8908 if (
Op->getFlags().hasApproximateFuncs()) {
8909 SDValue
Flags =
Op.getOperand(1);
8919 "custom lower FP_ROUND for f16 or bf16");
8920 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8937 EVT VT =
Op.getValueType();
8939 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8940 bool IsIEEEMode =
Info->getMode().IEEE;
8946 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8949 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8950 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8951 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8952 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8958SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8960 EVT VT =
Op.getValueType();
8962 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8963 bool IsIEEEMode =
Info->getMode().IEEE;
8965 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8968 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8969 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8970 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8971 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8978 EVT VT =
Op.getValueType();
8981 SDValue
Exp =
Op.getOperand(IsStrict ? 2 : 1);
8982 EVT ExpVT =
Exp.getValueType();
8983 if (ExpVT == MVT::i16)
9004 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
9011 switch (
Op->getOpcode()) {
9044SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
9045 DAGCombinerInfo &DCI)
const {
9046 EVT OpTy =
Op.getValueType();
9047 SelectionDAG &DAG = DCI.DAG;
9054 SDValue Input =
Op.getOperand(0);
9056 Input = DAG.
getNode(ExtOp,
DL, ExtTy, Input);
9058 SDValue NewVal = DAG.
getNode(
Op.getOpcode(),
DL, ExtTy, Input);
9064 DAGCombinerInfo &DCI)
const {
9065 const unsigned Opc =
Op.getOpcode();
9074 :
Op->getOperand(0).getValueType();
9075 auto &DAG = DCI.DAG;
9078 if (DCI.isBeforeLegalizeOps() ||
9086 LHS =
Op->getOperand(1);
9087 RHS =
Op->getOperand(2);
9089 LHS =
Op->getOperand(0);
9090 RHS =
Op->getOperand(1);
9125 SDValue Mag =
Op.getOperand(0);
9131 SDValue Sign =
Op.getOperand(1);
9134 if (MagVT == SignVT)
9144 SDValue SignShifted =
9155 EVT VT =
Op.getValueType();
9161 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9188 if (
Op->isDivergent())
9191 SDValue Op0 =
Op.getOperand(0);
9192 SDValue Op1 =
Op.getOperand(1);
9201 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9203 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9206 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9208 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9214 EVT VT =
Op.getValueType();
9216 SDValue
LHS =
Op.getOperand(0);
9217 SDValue
RHS =
Op.getOperand(1);
9221 const APInt &
C = RHSC->getAPIntValue();
9223 if (
C.isPowerOf2()) {
9225 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9226 SDValue ShiftAmt = DAG.
getConstant(
C.logBase2(), SL, MVT::i32);
9252 if (
Op->isDivergent()) {
9256 if (Subtarget->hasSMulHi()) {
9267 if (!Subtarget->hasTrapHandler() ||
9269 return lowerTrapEndpgm(
Op, DAG);
9271 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9272 : lowerTrapHsaQueuePtr(
Op, DAG);
9277 SDValue Chain =
Op.getOperand(0);
9278 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9282SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9284 ImplicitParameter Param)
const {
9288 MachinePointerInfo PtrInfo =
9298 SDValue Chain =
Op.getOperand(0);
9305 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9308 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9311 if (UserSGPR == AMDGPU::NoRegister) {
9322 SDValue SGPR01 = DAG.
getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9323 SDValue ToReg = DAG.
getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9328 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9333 SDValue Chain =
Op.getOperand(0);
9337 if (Subtarget->hasPrivEnabledTrap2NopBug())
9338 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9342 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9347 SDValue Chain =
Op.getOperand(0);
9350 if (!Subtarget->hasTrapHandler() ||
9354 "debugtrap handler not supported",
9362 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9372 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9373 SmallSet<Register, 8> SGPRInputRegs;
9375 unsigned NumVals = 0;
9378 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9379 NumVals =
Flags.getNumOperandRegisters();
9383 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9384 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9386 for (
unsigned J = 0; J < NumVals; ++J) {
9387 SDValue Val =
Op.getOperand(
I + 1 + J);
9388 if (
const RegisterSDNode *RegNode =
9397 if (SGPRInputRegs.
empty())
9402 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9406 SDValue SrcVal =
N->getOperand(2);
9410 SDValue ReadFirstLaneID =
9412 SDValue ReadFirstLane =
9414 ReadFirstLaneID, SrcVal);
9418 if (
N->getNumOperands() > 3)
9419 Ops.push_back(
N->getOperand(3));
9425 SDNode *
Next =
nullptr;
9426 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9427 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9428 Next =
N->getOperand(
I).getNode();
9438SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9440 unsigned BaseAS = AS;
9445 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9455SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9459 if (Subtarget->hasApertureRegs()) {
9460 const unsigned ApertureRegNo =
9461 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9462 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9463 !Subtarget->hasGloballyAddressableScratch()) &&
9464 "Cannot use src_private_base with globally addressable scratch!");
9484 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9488 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9490 if (UserSGPR == AMDGPU::NoRegister) {
9501 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9535 const AMDGPUTargetMachine &TM =
9539 unsigned SrcAS = ASC->getSrcAddressSpace();
9540 SDValue Src = ASC->getOperand(0);
9541 unsigned DestAS = ASC->getDestAddressSpace();
9542 bool IsNonNull = ASC->getFlags().hasNonNull();
9544 SDValue FlatNullPtr = DAG.
getConstant(0, SL, MVT::i64);
9553 Subtarget->hasGloballyAddressableScratch()) {
9556 SDValue FlatScratchBaseLo(
9558 AMDGPU::S_MOV_B32, SL, MVT::i32,
9559 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9568 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9582 Subtarget->hasGloballyAddressableScratch()) {
9586 SDValue ThreadID = DAG.
getConstant(0, SL, MVT::i32);
9591 if (Subtarget->isWave64())
9597 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9603 SDValue FlatScratchBase = {
9605 AMDGPU::S_MOV_B64, SL, MVT::i64,
9606 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9608 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9610 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9620 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9631 Op.getValueType() == MVT::i64) {
9632 const SIMachineFunctionInfo *
Info =
9634 if (
Info->get32BitAddressHighBits() == 0)
9643 Src.getValueType() == MVT::i64)
9659 SDValue Vec =
Op.getOperand(0);
9660 SDValue Ins =
Op.getOperand(1);
9661 SDValue
Idx =
Op.getOperand(2);
9666 unsigned IdxVal =
Idx->getAsZExtVal();
9671 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9676 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9678 MVT::i32, InsNumElts / 2);
9683 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9685 if (InsNumElts == 2) {
9698 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9709 SDValue Vec =
Op.getOperand(0);
9710 SDValue InsVal =
Op.getOperand(1);
9711 SDValue
Idx =
Op.getOperand(2);
9721 if (NumElts == 4 && EltSize == 16 && KIdx) {
9732 unsigned Idx = KIdx->getZExtValue();
9733 bool InsertLo =
Idx < 2;
9734 SDValue InsHalf = DAG.
getNode(
9737 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9743 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9756 assert(VecSize <= 64 &&
"Expected target vector size to be <= 64 bits");
9764 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9791 EVT ResultVT =
Op.getValueType();
9792 SDValue Vec =
Op.getOperand(0);
9793 SDValue
Idx =
Op.getOperand(1);
9804 if (SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9807 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9811 if (VecSize == 128) {
9812 SDValue V2 = DAG.
getBitcast(MVT::v2i64, Vec);
9819 }
else if (VecSize == 256) {
9820 SDValue V2 = DAG.
getBitcast(MVT::v4i64, Vec);
9822 for (
unsigned P = 0;
P < 4; ++
P) {
9828 Parts[0], Parts[1]));
9830 Parts[2], Parts[3]));
9834 SDValue V2 = DAG.
getBitcast(MVT::v8i64, Vec);
9836 for (
unsigned P = 0;
P < 8; ++
P) {
9843 Parts[0], Parts[1], Parts[2], Parts[3]));
9846 Parts[4], Parts[5], Parts[6], Parts[7]));
9849 EVT IdxVT =
Idx.getValueType();
9852 SDValue IdxMask = DAG.
getConstant(NElem / 2 - 1, SL, IdxVT);
9866 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9876 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9881 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9891 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9896 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9897 !(Mask[Elt + 1] & 1);
9903 EVT ResultVT =
Op.getValueType();
9906 const int NewSrcNumElts = 2;
9908 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9924 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9946 if (ShouldUseConsecutiveExtract &&
9949 int VecIdx =
Idx < SrcNumElts ? 0 : 1;
9950 int EltIdx =
Idx < SrcNumElts ?
Idx :
Idx - SrcNumElts;
9961 SDValue SrcOp1 = SrcOp0;
9962 if (Idx0 >= SrcNumElts) {
9967 if (Idx1 >= SrcNumElts) {
9972 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9973 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9981 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9982 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9984 SDValue Result0 = SubVec0;
9985 SDValue Result1 = SubVec0;
9987 if (SubVec0 != SubVec1) {
9988 NewMaskIdx1 += NewSrcNumElts;
9995 {NewMaskIdx0, NewMaskIdx1});
10000 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10001 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10002 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10003 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10021 SDValue SVal =
Op.getOperand(0);
10022 EVT ResultVT =
Op.getValueType();
10024 SDValue UndefVal = DAG.
getPOISON(SValVT);
10038 EVT VT =
Op.getValueType();
10040 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10041 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10043 SDValue
Lo =
Op.getOperand(0);
10044 SDValue
Hi =
Op.getOperand(1);
10047 if (
Hi.isUndef()) {
10075 for (
unsigned P = 0;
P < NumParts; ++
P) {
10077 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10103 if (!Subtarget->isAmdHsaOS())
10146 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10155 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10163 EVT PtrVT =
Op.getValueType();
10165 const GlobalValue *GV = GSD->
getGlobal();
10178 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10193 return SDValue(DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, GA), 0);
10199 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10202 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10203 if (Subtarget->has64BitLiterals()) {
10212 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10216 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10234 MachinePointerInfo PtrInfo =
10247 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10269 unsigned Offset)
const {
10271 SDValue Param = lowerKernargMemParameter(
10282 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10290 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10298 unsigned NumElts = Elts.
size();
10300 if (NumElts <= 12) {
10304 Type = MVT::v16f32;
10309 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10315 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10324 SDValue Src,
int ExtraElts) {
10325 EVT SrcVT = Src.getValueType();
10335 while (ExtraElts--)
10346 bool Unpacked,
bool IsD16,
int DMaskPop,
10347 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10351 EVT ReqRetVT = ResultTypes[0];
10353 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10354 ? (ReqRetNumElts + 1) / 2
10357 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10360 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10363 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10368 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10372 SDValue(Result, 0), ZeroIdx);
10375 SDValue(Result, 0), ZeroIdx);
10379 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10381 NumDataDwords - MaskPopDwords);
10386 EVT LegalReqRetVT = ReqRetVT;
10388 if (!
Data.getValueType().isInteger())
10390 Data.getValueType().changeTypeToInteger(),
Data);
10411 if (Result->getNumValues() == 1)
10418 SDValue *LWE,
bool &IsTexFail) {
10438 unsigned DimIdx,
unsigned EndIdx,
10439 unsigned NumGradients) {
10441 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10449 if (((
I + 1) >= EndIdx) ||
10450 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10451 I == DimIdx + NumGradients - 1))) {
10483 !
Op.getNode()->hasAnyUseOfValue(0))
10485 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10496 ResultTypes.erase(&ResultTypes[0]);
10498 bool IsD16 =
false;
10499 bool IsG16 =
false;
10500 bool IsA16 =
false;
10502 int NumVDataDwords = 0;
10503 bool AdjustRetType =
false;
10504 bool IsAtomicPacked16Bit =
false;
10507 const unsigned ArgOffset = WithChain ? 2 : 1;
10510 unsigned DMaskLanes = 0;
10512 if (BaseOpcode->
Atomic) {
10513 VData =
Op.getOperand(2);
10515 IsAtomicPacked16Bit =
10516 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10517 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10518 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10519 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10524 "unsupported image atomic data type");
10529 SDValue VData2 =
Op.getOperand(3);
10536 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10538 DMask = Is64Bit ? 0xf : 0x3;
10539 NumVDataDwords = Is64Bit ? 4 : 2;
10541 DMask = Is64Bit ? 0x3 : 0x1;
10542 NumVDataDwords = Is64Bit ? 2 : 1;
10545 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10548 if (BaseOpcode->
Store) {
10549 VData =
Op.getOperand(2);
10553 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10556 "unsupported image store data type");
10558 if (StoreScalarVT == MVT::f16) {
10559 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10563 VData = handleD16VData(VData, DAG,
true);
10566 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10567 }
else if (!BaseOpcode->
NoReturn) {
10572 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10575 "unsupported image load data type");
10577 if (LoadScalarVT == MVT::f16) {
10578 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10586 (!LoadVT.
isVector() && DMaskLanes > 1))
10592 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10593 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10594 NumVDataDwords = (DMaskLanes + 1) / 2;
10596 NumVDataDwords = DMaskLanes;
10598 AdjustRetType =
true;
10602 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10609 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10610 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10612 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10614 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10615 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10619 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10625 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10629 "Bias needs to be converted to 16 bit in A16 mode");
10634 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10638 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10639 "require 16 bit args for both gradients and addresses");
10644 if (!
ST->hasA16()) {
10645 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10646 "support 16 bit addresses\n");
10656 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10658 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10660 IntrOpcode = G16MappingInfo->
G16;
10683 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10701 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10702 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10703 const bool UseNSA =
ST->hasNSAEncoding() &&
10704 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10705 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10706 const bool UsePartialNSA =
10707 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10710 if (UsePartialNSA) {
10712 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10713 }
else if (!UseNSA) {
10724 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10732 bool IsTexFail =
false;
10733 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10742 NumVDataDwords = 1;
10744 NumVDataDwords += 1;
10745 AdjustRetType =
true;
10750 if (AdjustRetType) {
10753 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10762 MVT::i32, NumVDataDwords)
10765 ResultTypes[0] = NewVT;
10766 if (ResultTypes.size() == 3) {
10770 ResultTypes.erase(&ResultTypes[1]);
10784 Ops.push_back(VData);
10785 if (UsePartialNSA) {
10787 Ops.push_back(VAddr);
10791 Ops.push_back(VAddr);
10792 SDValue Rsrc =
Op.getOperand(ArgOffset + Intr->
RsrcIndex);
10794 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10795 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10797 Ops.push_back(Rsrc);
10798 bool IsSampIndexed =
false;
10800 SDValue Samp =
Op.getOperand(ArgOffset + Intr->
SampIndex);
10802 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10803 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10805 Ops.push_back(Samp);
10810 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10811 Ops.push_back(Unorm);
10813 Ops.push_back(IsA16 &&
10814 ST->hasFeature(AMDGPU::FeatureR128A16)
10820 if (!Subtarget->hasGFX90AInsts())
10821 Ops.push_back(TFE);
10825 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10828 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10829 Ops.push_back(LWE);
10835 Ops.push_back(
Op.getOperand(0));
10837 int NumVAddrDwords =
10844 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10845 }
else if (IsGFX12Plus) {
10847 NumVDataDwords, NumVAddrDwords);
10848 }
else if (IsGFX11Plus) {
10850 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10851 : AMDGPU::MIMGEncGfx11Default,
10852 NumVDataDwords, NumVAddrDwords);
10853 }
else if (IsGFX10Plus) {
10855 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10856 : AMDGPU::MIMGEncGfx10Default,
10857 NumVDataDwords, NumVAddrDwords);
10859 if (Subtarget->hasGFX90AInsts()) {
10861 NumVDataDwords, NumVAddrDwords);
10862 if (Opcode == -1) {
10864 DAG,
Op, OrigResultTypes,
DL,
10865 "requested image instruction is not supported on this GPU");
10868 if (Opcode == -1 &&
10871 NumVDataDwords, NumVAddrDwords);
10874 NumVDataDwords, NumVAddrDwords);
10881 MachineMemOperand *MemRef = MemOp->getMemOperand();
10888 {DAG.
getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)},
DL);
10890 return SDValue(NewNode, 0);
10900 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10901 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10910 bool HasChainResult = MMO !=
nullptr;
10914 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10915 Subtarget->hasScalarSubwordLoads();
10918 MF.
getFunction(),
"unsupported s_buffer_load result type",
10919 DL.getDebugLoc()));
10920 EVT ResultTypes[] = {VT, MVT::Other};
10922 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain,
DL);
10925 if (!HasChainResult) {
10937 if (!
Offset->isDivergent()) {
10938 SDValue
Ops[] = {Chain, Rsrc,
Offset, CachePolicy};
10945 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) -> SDValue {
10947 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10950 if (HasChainResult)
10954 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10955 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10957 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10958 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10963 !Subtarget->hasScalarDwordx3Loads()) {
10967 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10972 if (HasChainResult)
10994 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10995 Subtarget->hasScalarSubwordLoads()) {
10997 SDValue
Load = handleByteShortBufferLoads(DAG, MemVT,
DL,
Ops, MMO);
10999 if (HasChainResult)
11005 unsigned NumLoads = 1;
11011 if (NumElts == 8 || NumElts == 16) {
11012 NumLoads = NumElts / 4;
11016 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
11021 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
11025 for (
unsigned i = 0; i < NumLoads; ++i) {
11028 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
11029 LoadVT, LoadMMO, DAG));
11032 if (NumElts == 8 || NumElts == 16) {
11034 if (HasChainResult) {
11036 for (SDValue
Load : Loads)
11049 if (!Subtarget->hasArchitectedSGPRs())
11054 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11061 unsigned Width)
const {
11063 using namespace AMDGPU::Hwreg;
11065 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11085 SDValue Val =
loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11104 SDValue Src =
Op.getOperand(0);
11105 EVT DstVT =
Op.getValueType();
11107 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11108 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11112 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11114 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11127SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11136 const bool HasE5M3ConversionInsts =
11137 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11138 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11142 EVT DstVT =
Op.getValueType();
11146 !Subtarget->hasFP8F16ConversionInsts())
11154 SDValue Src =
Op.getOperand(0);
11156 "only the v2f32 vector result is custom lowered");
11162 auto ConvertByte = [&](
unsigned ByteSel) {
11163 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11168 return ConvertByte(0);
11169 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11173 SDValue Src =
Op.getOperand(0);
11174 if (Src.getValueType() != MVT::i32) {
11184 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11185 return lowerFromFP8(
Op, IsBF8, DAG);
11192 SDValue Src =
Op.getOperand(0);
11193 EVT ResVT =
Op.getValueType();
11194 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11195 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11196 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11198 "only the v2i8 vector result is custom lowered");
11202 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11203 SDValue Bytes = DAG.
getNode(
Opc, SL, MVT::i16, Src);
11207 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11208 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11209 : AMDGPUISD::CVT_PK_FP8_F32;
11210 SDValue PoisonI32 = DAG.
getPOISON(MVT::i32);
11217 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11229SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11238 const bool HasE5M3ConversionInsts =
11239 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11240 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11250 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11253 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11256 if (SrcEltVT == MVT::f32)
11257 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11258 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11259 Subtarget->hasF16FP8ConversionInsts()) {
11262 if (!
Op.getValueType().isVector())
11264 return lowerToFP8(
Op, IsBF8,
false, DAG);
11272 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11274 EVT VT =
Op.getValueType();
11276 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11280 switch (IntrinsicID) {
11281 case Intrinsic::amdgcn_wave_reduce_min:
11282 case Intrinsic::amdgcn_wave_reduce_umin:
11283 case Intrinsic::amdgcn_wave_reduce_fmin:
11284 case Intrinsic::amdgcn_wave_reduce_max:
11285 case Intrinsic::amdgcn_wave_reduce_umax:
11286 case Intrinsic::amdgcn_wave_reduce_fmax:
11287 case Intrinsic::amdgcn_wave_reduce_add:
11288 case Intrinsic::amdgcn_wave_reduce_fadd:
11289 case Intrinsic::amdgcn_wave_reduce_sub:
11290 case Intrinsic::amdgcn_wave_reduce_fsub:
11291 case Intrinsic::amdgcn_wave_reduce_and:
11292 case Intrinsic::amdgcn_wave_reduce_or:
11293 case Intrinsic::amdgcn_wave_reduce_xor: {
11294 EVT SrcVT =
Op.getOperand(1).getValueType();
11297 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11298 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11299 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11300 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11304 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11305 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11306 SDValue ExtendedSrc = DAG.
getNode(ExtOpc,
DL, ExtType,
Op.getOperand(1));
11307 SDValue Strategy =
Op.getOperand(2);
11309 Op.getOperand(0), ExtendedSrc, Strategy);
11318 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11321 return getPreloadedValue(DAG, *MFI, VT,
11324 case Intrinsic::amdgcn_dispatch_ptr:
11325 case Intrinsic::amdgcn_queue_ptr: {
11326 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11328 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11329 DL.getDebugLoc()));
11333 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11336 return getPreloadedValue(DAG, *MFI, VT, RegID);
11338 case Intrinsic::amdgcn_implicitarg_ptr: {
11340 return getImplicitArgPtr(DAG,
DL);
11341 return getPreloadedValue(DAG, *MFI, VT,
11344 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11350 return getPreloadedValue(DAG, *MFI, VT,
11353 case Intrinsic::amdgcn_dispatch_id: {
11356 case Intrinsic::amdgcn_rcp:
11357 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11358 case Intrinsic::amdgcn_rsq:
11359 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11360 case Intrinsic::amdgcn_rsq_legacy:
11364 case Intrinsic::amdgcn_rcp_legacy:
11367 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11368 case Intrinsic::amdgcn_fma_legacy:
11369 case Intrinsic::amdgcn_sudot4:
11370 case Intrinsic::amdgcn_sudot8:
11371 case Intrinsic::amdgcn_tanh:
11373 case Intrinsic::amdgcn_rsq_clamp: {
11375 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11381 SDValue Rsq = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11387 case Intrinsic::r600_read_ngroups_x:
11388 if (Subtarget->isAmdHsaOS())
11391 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11394 case Intrinsic::r600_read_ngroups_y:
11395 if (Subtarget->isAmdHsaOS())
11398 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11401 case Intrinsic::r600_read_ngroups_z:
11402 if (Subtarget->isAmdHsaOS())
11405 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11408 case Intrinsic::r600_read_local_size_x:
11409 if (Subtarget->isAmdHsaOS())
11412 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11414 case Intrinsic::r600_read_local_size_y:
11415 if (Subtarget->isAmdHsaOS())
11418 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11420 case Intrinsic::r600_read_local_size_z:
11421 if (Subtarget->isAmdHsaOS())
11424 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11426 case Intrinsic::amdgcn_workgroup_id_x:
11427 return lowerWorkGroupId(DAG, *MFI, VT,
11431 case Intrinsic::amdgcn_workgroup_id_y:
11432 return lowerWorkGroupId(DAG, *MFI, VT,
11436 case Intrinsic::amdgcn_workgroup_id_z:
11437 return lowerWorkGroupId(DAG, *MFI, VT,
11441 case Intrinsic::amdgcn_cluster_id_x:
11442 return Subtarget->hasClusters()
11443 ? getPreloadedValue(DAG, *MFI, VT,
11445 : DAG.getPOISON(VT);
11446 case Intrinsic::amdgcn_cluster_id_y:
11447 return Subtarget->hasClusters()
11448 ? getPreloadedValue(DAG, *MFI, VT,
11451 case Intrinsic::amdgcn_cluster_id_z:
11452 return Subtarget->hasClusters()
11453 ? getPreloadedValue(DAG, *MFI, VT,
11456 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11457 return Subtarget->hasClusters()
11458 ? getPreloadedValue(
11462 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11463 return Subtarget->hasClusters()
11464 ? getPreloadedValue(
11468 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11469 return Subtarget->hasClusters()
11470 ? getPreloadedValue(
11474 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11475 return Subtarget->hasClusters()
11478 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11479 return Subtarget->hasClusters()
11480 ? getPreloadedValue(
11484 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11485 return Subtarget->hasClusters()
11486 ? getPreloadedValue(
11490 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11491 return Subtarget->hasClusters()
11492 ? getPreloadedValue(
11496 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11497 return Subtarget->hasClusters()
11498 ? getPreloadedValue(
11502 case Intrinsic::amdgcn_wave_id:
11503 return lowerWaveID(DAG,
Op);
11504 case Intrinsic::amdgcn_lds_kernel_id: {
11506 return getLDSKernelId(DAG,
DL);
11507 return getPreloadedValue(DAG, *MFI, VT,
11510 case Intrinsic::amdgcn_workitem_id_x:
11511 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11512 case Intrinsic::amdgcn_workitem_id_y:
11513 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11514 case Intrinsic::amdgcn_workitem_id_z:
11515 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11516 case Intrinsic::amdgcn_wavefrontsize:
11518 SDLoc(
Op), MVT::i32);
11519 case Intrinsic::amdgcn_s_buffer_load: {
11520 unsigned CPol =
Op.getConstantOperandVal(3);
11528 Op.getOperand(2),
Op.getOperand(3), DAG);
11530 case Intrinsic::amdgcn_fdiv_fast:
11531 return lowerFDIV_FAST(
Op, DAG);
11532 case Intrinsic::amdgcn_sin:
11533 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11535 case Intrinsic::amdgcn_cos:
11536 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11538 case Intrinsic::amdgcn_mul_u24:
11539 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11541 case Intrinsic::amdgcn_mul_i24:
11542 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11545 case Intrinsic::amdgcn_log_clamp: {
11551 case Intrinsic::amdgcn_fract:
11552 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11554 case Intrinsic::amdgcn_class: {
11555 SDValue Src =
Op.getOperand(1);
11556 EVT SrcVT = Src.getValueType();
11557 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11558 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11562 "llvm.amdgcn.class only supports f16, f32, and f64",
11563 DL.getDebugLoc()));
11566 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11568 case Intrinsic::amdgcn_div_fmas:
11569 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11570 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11572 case Intrinsic::amdgcn_div_fixup:
11573 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11574 Op.getOperand(2),
Op.getOperand(3));
11576 case Intrinsic::amdgcn_div_scale: {
11581 SDValue Numerator =
Op.getOperand(1);
11582 SDValue Denominator =
Op.getOperand(2);
11589 SDValue
Src0 =
Param->isAllOnes() ? Numerator : Denominator;
11591 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11592 Denominator, Numerator);
11594 case Intrinsic::amdgcn_ballot:
11596 case Intrinsic::amdgcn_fmed3:
11597 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11598 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11599 case Intrinsic::amdgcn_fdot2:
11600 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11601 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11602 case Intrinsic::amdgcn_fmul_legacy:
11603 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11605 case Intrinsic::amdgcn_sbfe:
11606 case Intrinsic::amdgcn_ubfe:
11608 case Intrinsic::amdgcn_cvt_pkrtz:
11609 case Intrinsic::amdgcn_cvt_pknorm_i16:
11610 case Intrinsic::amdgcn_cvt_pknorm_u16:
11611 case Intrinsic::amdgcn_cvt_pk_i16:
11612 case Intrinsic::amdgcn_cvt_pk_u16: {
11614 EVT VT =
Op.getValueType();
11617 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11618 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11619 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11620 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11621 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11622 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11623 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11624 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11626 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11629 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11632 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11635 case Intrinsic::amdgcn_fmad_ftz:
11636 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11637 Op.getOperand(2),
Op.getOperand(3));
11639 case Intrinsic::amdgcn_if_break:
11641 Op->getOperand(1),
Op->getOperand(2)),
11644 case Intrinsic::amdgcn_groupstaticsize: {
11650 const GlobalValue *GV =
11656 case Intrinsic::amdgcn_is_shared:
11657 case Intrinsic::amdgcn_is_private: {
11664 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11668 Subtarget->hasGloballyAddressableScratch()) {
11669 SDValue FlatScratchBaseHi(
11671 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11672 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11681 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11684 case Intrinsic::amdgcn_perm:
11685 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11686 Op.getOperand(2),
Op.getOperand(3));
11687 case Intrinsic::amdgcn_reloc_constant: {
11697 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11698 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11699 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11700 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11701 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11702 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11703 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11704 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11705 if (
Op.getOperand(4).getValueType() == MVT::i32)
11711 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11712 Op.getOperand(3), IndexKeyi32);
11714 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11715 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11716 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11717 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11718 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11719 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11720 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11721 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11722 if (
Op.getOperand(4).getValueType() == MVT::i64)
11727 Op.getOperand(4).getValueType() == MVT::v2i32
11731 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11732 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11733 Op.getOperand(6)});
11735 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11736 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11737 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11738 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11739 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11740 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11741 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11744 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11749 Op.getOperand(6).getValueType().isVector()
11753 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11754 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11755 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11756 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11757 Args.push_back(
Op.getOperand(9));
11760 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11761 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11762 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11763 if (
Op.getOperand(6).getValueType() == MVT::i32)
11769 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11770 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11771 IndexKeyi32, Op.getOperand(7)});
11773 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11774 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11775 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11776 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11777 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11778 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11782 "invalid matrix and scale format combination in wmma call");
11788 case Intrinsic::amdgcn_readlane:
11789 case Intrinsic::amdgcn_readfirstlane:
11790 case Intrinsic::amdgcn_writelane:
11791 case Intrinsic::amdgcn_permlane16:
11792 case Intrinsic::amdgcn_permlanex16:
11793 case Intrinsic::amdgcn_permlane64:
11794 case Intrinsic::amdgcn_set_inactive:
11795 case Intrinsic::amdgcn_set_inactive_chain_arg:
11796 case Intrinsic::amdgcn_mov_dpp8:
11797 case Intrinsic::amdgcn_update_dpp:
11798 case Intrinsic::amdgcn_permlane_bcast:
11799 case Intrinsic::amdgcn_permlane_up:
11800 case Intrinsic::amdgcn_permlane_down:
11801 case Intrinsic::amdgcn_permlane_xor:
11803 case Intrinsic::amdgcn_dead: {
11805 for (
const EVT ValTy :
Op.getNode()->values())
11809 case Intrinsic::amdgcn_wave_shuffle:
11812 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11814 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11824 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(SOffset))
11825 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11831 unsigned NewOpcode)
const {
11834 SDValue VData =
Op.getOperand(2);
11838 "unsupported buffer atomic data type");
11840 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11841 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11859 M->getMemOperand());
11864 unsigned NewOpcode)
const {
11867 SDValue VData =
Op.getOperand(2);
11871 "unsupported buffer atomic data type");
11873 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11874 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11892 M->getMemOperand());
11899 unsigned NumOperands =
N->getNumOperands();
11900 if (
N->getOperand(NumOperands - 1) == Zero)
11903 Ops[NumOperands - 1] = Zero;
11909 unsigned IntrID =
Op.getConstantOperandVal(1);
11913 case Intrinsic::amdgcn_cluster_load_b32:
11914 case Intrinsic::amdgcn_cluster_load_b64:
11915 case Intrinsic::amdgcn_cluster_load_b128: {
11916 if (Subtarget->hasGFX1250_STRICT())
11920 case Intrinsic::amdgcn_ds_ordered_add:
11921 case Intrinsic::amdgcn_ds_ordered_swap: {
11923 SDValue Chain =
M->getOperand(0);
11924 SDValue
M0 =
M->getOperand(2);
11925 SDValue
Value =
M->getOperand(3);
11926 unsigned IndexOperand =
M->getConstantOperandVal(7);
11927 unsigned WaveRelease =
M->getConstantOperandVal(8);
11928 unsigned WaveDone =
M->getConstantOperandVal(9);
11930 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11931 IndexOperand &= ~0x3f;
11932 unsigned CountDw = 0;
11935 CountDw = (IndexOperand >> 24) & 0xf;
11936 IndexOperand &= ~(0xf << 24);
11938 if (CountDw < 1 || CountDw > 4) {
11941 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11942 DL.getDebugLoc()));
11947 if (IndexOperand) {
11950 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11953 if (WaveDone && !WaveRelease) {
11957 Fn,
"ds_ordered_count: wave_done requires wave_release",
11958 DL.getDebugLoc()));
11961 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11962 unsigned ShaderType =
11964 unsigned Offset0 = OrderedCountIndex << 2;
11965 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11968 Offset1 |= (CountDw - 1) << 6;
11971 Offset1 |= ShaderType << 2;
11973 unsigned Offset = Offset0 | (Offset1 << 8);
11980 M->getVTList(),
Ops,
M->getMemoryVT(),
11981 M->getMemOperand());
11983 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11984 unsigned CPol =
Op.getConstantOperandVal(4);
11991 return lowerSBuffer(
11992 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
11993 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
11994 Op.getOperand(4), DAG,
M->getMemOperand());
11996 case Intrinsic::amdgcn_raw_buffer_load:
11997 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11998 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11999 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12000 case Intrinsic::amdgcn_raw_buffer_load_format:
12001 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12002 const bool IsFormat =
12003 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12004 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12006 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12007 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12021 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
12023 case Intrinsic::amdgcn_struct_buffer_load:
12024 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12025 case Intrinsic::amdgcn_struct_buffer_load_format:
12026 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12027 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12028 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12029 const bool IsFormat =
12030 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12031 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12033 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12034 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12049 case Intrinsic::amdgcn_raw_tbuffer_load:
12050 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12052 EVT LoadVT =
Op.getValueType();
12053 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12054 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12070 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12072 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12073 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12076 case Intrinsic::amdgcn_struct_tbuffer_load:
12077 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12079 EVT LoadVT =
Op.getValueType();
12080 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12081 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12097 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12099 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12100 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12103 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12104 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12105 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12106 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12107 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12108 return lowerStructBufferAtomicIntrin(
Op, DAG,
12109 AMDGPUISD::BUFFER_ATOMIC_FADD);
12110 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12111 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12112 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12113 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12114 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12115 return lowerStructBufferAtomicIntrin(
Op, DAG,
12116 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12117 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12118 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12119 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12120 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12121 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12122 return lowerStructBufferAtomicIntrin(
Op, DAG,
12123 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12124 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12125 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12126 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12127 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12129 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12132 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12133 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12135 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12136 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12137 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12138 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12139 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12140 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12141 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12142 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12144 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12147 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12148 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12150 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12151 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12152 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12153 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12154 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12155 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12156 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12157 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12158 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12159 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12160 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12162 return lowerStructBufferAtomicIntrin(
Op, DAG,
12163 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12164 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12166 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12167 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12168 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12169 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12170 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12172 return lowerStructBufferAtomicIntrin(
Op, DAG,
12173 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12174 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12175 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12176 return lowerStructBufferAtomicIntrin(
Op, DAG,
12177 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12178 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12179 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12180 return lowerStructBufferAtomicIntrin(
Op, DAG,
12181 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12182 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12183 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12184 return lowerStructBufferAtomicIntrin(
Op, DAG,
12185 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12186 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12187 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12188 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12189 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12190 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12191 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12192 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12194 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12195 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12196 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12197 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12198 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12199 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12200 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12201 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12202 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12203 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12204 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12205 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12206 return lowerStructBufferAtomicIntrin(
Op, DAG,
12207 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12208 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12209 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12210 return lowerRawBufferAtomicIntrin(
Op, DAG,
12211 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12212 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12213 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12214 return lowerStructBufferAtomicIntrin(
Op, DAG,
12215 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12216 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12217 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12218 SDValue Src =
Op.getOperand(2);
12219 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12222 "unsupported buffer atomic data type");
12224 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12225 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12239 EVT VT =
Op.getValueType();
12243 Op->getVTList(),
Ops, VT,
12244 M->getMemOperand());
12246 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12247 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12248 SDValue Src =
Op.getOperand(2);
12249 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12252 "unsupported buffer atomic data type");
12254 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12255 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12269 EVT VT =
Op.getValueType();
12273 Op->getVTList(),
Ops, VT,
12274 M->getMemOperand());
12276 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12277 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12279 SDValue NodePtr =
M->getOperand(2);
12280 SDValue RayExtent =
M->getOperand(3);
12281 SDValue InstanceMask =
M->getOperand(4);
12282 SDValue RayOrigin =
M->getOperand(5);
12283 SDValue RayDir =
M->getOperand(6);
12284 SDValue
Offsets =
M->getOperand(7);
12285 SDValue TDescr =
M->getOperand(8);
12290 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12291 const unsigned NumVDataDwords = 10;
12292 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12294 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12295 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12296 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12300 Ops.push_back(NodePtr);
12303 {DAG.getBitcast(MVT::i32, RayExtent),
12304 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12305 Ops.push_back(RayOrigin);
12306 Ops.push_back(RayDir);
12307 Ops.push_back(Offsets);
12308 Ops.push_back(TDescr);
12309 Ops.push_back(
M->getChain());
12312 MachineMemOperand *MemRef =
M->getMemOperand();
12314 return SDValue(NewNode, 0);
12316 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12318 SDValue NodePtr =
M->getOperand(2);
12319 SDValue RayExtent =
M->getOperand(3);
12320 SDValue RayOrigin =
M->getOperand(4);
12321 SDValue RayDir =
M->getOperand(5);
12322 SDValue RayInvDir =
M->getOperand(6);
12323 SDValue TDescr =
M->getOperand(7);
12335 const unsigned NumVDataDwords = 4;
12336 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12337 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12338 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12341 const unsigned BaseOpcodes[2][2] = {
12342 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12343 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12344 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12348 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12349 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12350 : AMDGPU::MIMGEncGfx10NSA,
12351 NumVDataDwords, NumVAddrDwords);
12355 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12356 : AMDGPU::MIMGEncGfx10Default,
12357 NumVDataDwords, NumVAddrDwords);
12363 auto packLanes = [&DAG, &
Ops, &
DL](SDValue
Op,
bool IsAligned) {
12366 if (Lanes[0].getValueSizeInBits() == 32) {
12367 for (
unsigned I = 0;
I < 3; ++
I)
12374 Ops.push_back(Lanes[2]);
12376 SDValue Elt0 =
Ops.pop_back_val();
12386 if (UseNSA && IsGFX11Plus) {
12387 Ops.push_back(NodePtr);
12389 Ops.push_back(RayOrigin);
12394 for (
unsigned I = 0;
I < 3; ++
I) {
12397 {DirLanes[I], InvDirLanes[I]})));
12401 Ops.push_back(RayDir);
12402 Ops.push_back(RayInvDir);
12409 Ops.push_back(NodePtr);
12412 packLanes(RayOrigin,
true);
12413 packLanes(RayDir,
true);
12414 packLanes(RayInvDir,
false);
12419 if (NumVAddrDwords > 12) {
12424 SDValue MergedOps =
12427 Ops.push_back(MergedOps);
12430 Ops.push_back(TDescr);
12432 Ops.push_back(
M->getChain());
12435 MachineMemOperand *MemRef =
M->getMemOperand();
12437 return SDValue(NewNode, 0);
12439 case Intrinsic::amdgcn_global_atomic_fmin_num:
12440 case Intrinsic::amdgcn_global_atomic_fmax_num:
12441 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12442 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12449 unsigned Opcode = 0;
12451 case Intrinsic::amdgcn_global_atomic_fmin_num:
12452 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12456 case Intrinsic::amdgcn_global_atomic_fmax_num:
12457 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12464 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12465 Ops,
M->getMemOperand());
12467 case Intrinsic::amdgcn_s_alloc_vgpr: {
12472 SDValue ReadFirstLaneID =
12475 ReadFirstLaneID, NumVGPRs);
12478 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12480 case Intrinsic::amdgcn_s_get_barrier_state:
12481 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12482 SDValue Chain =
Op->getOperand(0);
12488 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12489 BarID = BarID & 0x3F;
12490 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12493 Ops.push_back(Chain);
12495 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12496 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12505 return SDValue(NewMI, 0);
12507 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12508 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12509 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12511 SDValue Chain =
Op->getOperand(0);
12512 SDValue Ptr =
Op->getOperand(2);
12513 EVT VT =
Op->getValueType(0);
12517 case Intrinsic::amdgcn_av_load_b128: {
12519 SDValue Chain =
Op->getOperand(0);
12520 SDValue Ptr =
Op->getOperand(2);
12521 EVT VT =
Op->getValueType(0);
12528 case Intrinsic::amdgcn_flat_load_monitor_b32:
12529 case Intrinsic::amdgcn_flat_load_monitor_b64:
12530 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12532 SDValue Chain =
Op->getOperand(0);
12533 SDValue Ptr =
Op->getOperand(2);
12535 Op->getVTList(), {Chain, Ptr},
12538 case Intrinsic::amdgcn_global_load_monitor_b32:
12539 case Intrinsic::amdgcn_global_load_monitor_b64:
12540 case Intrinsic::amdgcn_global_load_monitor_b128: {
12542 SDValue Chain =
Op->getOperand(0);
12543 SDValue Ptr =
Op->getOperand(2);
12545 Op->getVTList(), {Chain, Ptr},
12550 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12552 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12560SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12567 EVT VT = VTList.
VTs[0];
12570 bool IsTFE = VTList.
NumVTs == 3;
12573 unsigned NumOpDWords = NumValueDWords + 1;
12575 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12576 MachineMemOperand *OpDWordsMMO =
12578 SDValue
Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12579 OpDWordsVT, OpDWordsMMO, DAG);
12584 if (!Subtarget->hasDwordx3LoadStores() &&
12585 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12589 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12591 WidenedMemVT, WidenedMMO);
12601 bool ImageStore)
const {
12611 if (Subtarget->hasUnpackedD16VMem()) {
12625 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12636 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12642 if ((NumElements % 2) == 1) {
12644 unsigned I = Elts.
size() / 2;
12660 if (NumElements == 3) {
12679 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12680 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12681 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12682 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12683 case Intrinsic::amdgcn_load_async_to_lds:
12684 case Intrinsic::amdgcn_global_load_async_lds:
12693 SDValue Chain =
Op.getOperand(0);
12694 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12696 switch (IntrinsicID) {
12697 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12698 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12699 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12700 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12701 if (Subtarget->hasGFX1250_STRICT())
12705 case Intrinsic::amdgcn_exp_compr: {
12706 SDValue
Src0 =
Op.getOperand(4);
12707 SDValue
Src1 =
Op.getOperand(5);
12714 const SDValue
Ops[] = {
12726 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12730 case Intrinsic::amdgcn_struct_tbuffer_store:
12731 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12732 SDValue VData =
Op.getOperand(2);
12735 VData = handleD16VData(VData, DAG);
12736 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12737 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12751 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12752 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12755 M->getMemoryVT(),
M->getMemOperand());
12758 case Intrinsic::amdgcn_raw_tbuffer_store:
12759 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12760 SDValue VData =
Op.getOperand(2);
12763 VData = handleD16VData(VData, DAG);
12764 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12765 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12779 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12780 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12783 M->getMemoryVT(),
M->getMemOperand());
12786 case Intrinsic::amdgcn_raw_buffer_store:
12787 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12788 case Intrinsic::amdgcn_raw_buffer_store_format:
12789 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12790 const bool IsFormat =
12791 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12792 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12794 SDValue VData =
Op.getOperand(2);
12802 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12807 VData = handleD16VData(VData, DAG);
12817 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12818 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12832 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12833 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12838 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12841 M->getMemoryVT(),
M->getMemOperand());
12844 case Intrinsic::amdgcn_struct_buffer_store:
12845 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12846 case Intrinsic::amdgcn_struct_buffer_store_format:
12847 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12848 const bool IsFormat =
12849 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12850 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12852 SDValue VData =
Op.getOperand(2);
12860 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12865 VData = handleD16VData(VData, DAG);
12875 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12876 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12890 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12891 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12895 EVT VDataType = VData.getValueType().getScalarType();
12897 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12900 M->getMemoryVT(),
M->getMemOperand());
12902 case Intrinsic::amdgcn_raw_buffer_load_lds:
12903 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12904 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12905 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12906 case Intrinsic::amdgcn_struct_buffer_load_lds:
12907 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12908 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12909 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12912 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12913 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12914 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12915 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12916 unsigned OpOffset = HasVIndex ? 1 : 0;
12917 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12919 unsigned Size =
Op->getConstantOperandVal(4);
12925 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12926 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12927 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12928 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12931 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12932 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12933 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12934 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12937 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12938 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12939 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12940 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12943 if (!Subtarget->hasLDSLoadB96_B128())
12945 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12946 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12947 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12948 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12951 if (!Subtarget->hasLDSLoadB96_B128())
12953 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12954 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12955 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12956 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12960 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
12964 if (HasVIndex && HasVOffset)
12968 else if (HasVIndex)
12969 Ops.push_back(
Op.getOperand(5));
12970 else if (HasVOffset)
12971 Ops.push_back(VOffset);
12973 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12974 Ops.push_back(Rsrc);
12975 Ops.push_back(
Op.getOperand(6 + OpOffset));
12976 Ops.push_back(
Op.getOperand(7 + OpOffset));
12978 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
12996 return SDValue(
Load, 0);
13001 case Intrinsic::amdgcn_load_to_lds:
13002 case Intrinsic::amdgcn_load_async_to_lds:
13003 case Intrinsic::amdgcn_global_load_lds:
13004 case Intrinsic::amdgcn_global_load_async_lds: {
13005 if (!Subtarget->hasVMemToLDSLoad())
13009 unsigned Size =
Op->getConstantOperandVal(4);
13014 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13017 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13020 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13023 if (!Subtarget->hasLDSLoadB96_B128())
13025 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13028 if (!Subtarget->hasLDSLoadB96_B128())
13030 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13034 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
13038 SDValue Addr =
Op.getOperand(2);
13046 if (
LHS->isDivergent())
13050 RHS.getOperand(0).getValueType() == MVT::i32) {
13053 VOffset =
RHS.getOperand(0);
13057 Ops.push_back(Addr);
13065 Ops.push_back(VOffset);
13068 Ops.push_back(
Op.getOperand(5));
13070 unsigned Aux =
Op.getConstantOperandVal(6);
13083 return SDValue(
Load, 0);
13085 case Intrinsic::amdgcn_end_cf:
13087 Op->getOperand(2), Chain),
13089 case Intrinsic::amdgcn_s_barrier_signal_var: {
13094 SDValue CntOp =
Op->getOperand(3);
13096 if (CntC && CntC->isZero()) {
13097 SDValue Chain =
Op->getOperand(0);
13098 SDValue BarOp =
Op->getOperand(2);
13101 std::optional<uint64_t> BarVal;
13103 BarVal =
C->getZExtValue();
13107 BarVal = *Addr + GA->getOffset();
13110 unsigned BarID = *BarVal & 0x3F;
13112 Ops.push_back(Chain);
13114 Op->getVTList(),
Ops);
13115 return SDValue(NewMI, 0);
13120 case Intrinsic::amdgcn_s_barrier_init: {
13122 SDValue Chain =
Op->getOperand(0);
13124 SDValue BarOp =
Op->getOperand(2);
13125 SDValue CntOp =
Op->getOperand(3);
13127 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13128 ? AMDGPU::S_BARRIER_INIT_M0
13129 : AMDGPU::S_BARRIER_SIGNAL_M0;
13139 constexpr unsigned ShAmt = 16;
13148 return SDValue(NewMI, 0);
13150 case Intrinsic::amdgcn_s_wakeup_barrier: {
13151 if (!Subtarget->hasSWakeupBarrier())
13155 case Intrinsic::amdgcn_s_barrier_join: {
13157 SDValue Chain =
Op->getOperand(0);
13159 SDValue BarOp =
Op->getOperand(2);
13164 switch (IntrinsicID) {
13167 case Intrinsic::amdgcn_s_barrier_join:
13168 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13170 case Intrinsic::amdgcn_s_wakeup_barrier:
13171 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13175 unsigned BarID = BarVal & 0x3F;
13178 Ops.push_back(Chain);
13180 switch (IntrinsicID) {
13183 case Intrinsic::amdgcn_s_barrier_join:
13184 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13186 case Intrinsic::amdgcn_s_wakeup_barrier:
13187 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13197 return SDValue(NewMI, 0);
13199 case Intrinsic::amdgcn_s_prefetch_data:
13200 case Intrinsic::amdgcn_s_prefetch_inst: {
13203 return Op.getOperand(0);
13206 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13208 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13215 Op->getVTList(),
Ops,
M->getMemoryVT(),
13216 M->getMemOperand());
13218 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13219 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13220 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13222 SDValue Chain =
Op->getOperand(0);
13223 SDValue Ptr =
Op->getOperand(2);
13224 SDValue Val =
Op->getOperand(3);
13228 case Intrinsic::amdgcn_av_store_b128: {
13230 SDValue Chain =
Op->getOperand(0);
13231 SDValue Ptr =
Op->getOperand(2);
13232 SDValue Val =
Op->getOperand(3);
13236 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13238 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13254 return PtrVT == MVT::i64;
13268std::pair<SDValue, SDValue>
13281 bool CheckNUW = Subtarget->hasGFX1250Insts();
13298 unsigned Overflow = ImmOffset & ~MaxImm;
13299 ImmOffset -= Overflow;
13300 if ((int32_t)Overflow < 0) {
13301 Overflow += ImmOffset;
13306 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13310 SDValue
Ops[] = {N0, OverflowVal};
13319 return {N0, SDValue(C1, 0)};
13325void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13327 Align Alignment)
const {
13329 SDLoc
DL(CombinedOffset);
13331 uint32_t
Imm =
C->getZExtValue();
13332 uint32_t SOffset, ImmOffset;
13333 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13344 bool CheckNUW = Subtarget->hasGFX1250Insts();
13347 uint32_t SOffset, ImmOffset;
13350 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13358 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13367SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13370 return MaybePointer;
13372 SDValue Rsrc = DAG.
getBitcast(MVT::v4i32, MaybePointer);
13383 SDValue Stride =
Op->getOperand(2);
13384 SDValue NumRecords =
Op->getOperand(3);
13385 SDValue
Flags =
Op->getOperand(4);
13390 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13393 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13398 SDValue NumRecordsLHS =
13406 SDValue NumRecordsRHS =
13409 SDValue ShiftedStride =
13412 SDValue ExtShiftedStrideVec =
13414 SDValue ExtShiftedStride =
13416 SDValue ShiftedFlags =
13419 SDValue ExtShiftedFlagsVec =
13421 SDValue ExtShiftedFlags =
13423 SDValue CombinedFields =
13424 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13426 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13431 auto [LowHalf, HighHalf] =
13432 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13435 SDValue ShiftedStride =
13438 SDValue NewHighHalf =
13442 NumRecords, Flags);
13454 bool IsTFE)
const {
13459 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13460 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13463 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13464 SDValue
Op = getMemIntrinsicNode(
Opc,
DL, VTs,
Ops, MVT::v2i32, OpMMO, DAG);
13475 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13476 : AMDGPUISD::BUFFER_LOAD_USHORT;
13478 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13479 SDValue BufferLoad =
13492 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13496 Ops[1] = BufferStoreExt;
13497 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13498 : AMDGPUISD::BUFFER_STORE_SHORT;
13501 M->getMemOperand());
13526 DAGCombinerInfo &DCI)
const {
13527 SelectionDAG &DAG = DCI.DAG;
13528 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13532 unsigned AS = Ld->getAddressSpace();
13541 EVT MemVT = Ld->getMemoryVT();
13542 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13549 "unexpected vector extload");
13552 SDValue Ptr = Ld->getBasePtr();
13553 SDValue NewLoad = DAG.
getLoad(
13555 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13556 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13561 "unexpected fp extload");
13565 SDValue Cvt = NewLoad;
13576 EVT VT = Ld->getValueType(0);
13579 DCI.AddToWorklist(Cvt.
getNode());
13584 DCI.AddToWorklist(Cvt.
getNode());
13595 if (Info.isEntryFunction())
13596 return Info.getUserSGPRInfo().hasFlatScratchInit();
13604 EVT MemVT =
Load->getMemoryVT();
13605 MachineMemOperand *MMO =
Load->getMemOperand();
13612 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13614 SDValue Chain =
Load->getChain();
13619 BasePtr, MVT::i16, MMO);
13625 SDValue
Result = (MemVT == MVT::i16)
13639 SDValue Chain =
Load->getChain();
13642 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13670 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13671 "Custom lowering for non-i32 vectors hasn't been implemented.");
13674 unsigned AS =
Load->getAddressSpace();
13675 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13682 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13686 !Subtarget->hasMultiDwordFlatScratchAddressing())
13698 Alignment >=
Align(4) && NumElements < 32) {
13700 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13712 if (NumElements > 4)
13715 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13725 switch (Subtarget->getMaxPrivateElementSize()) {
13731 if (NumElements > 2)
13736 if (NumElements > 4)
13739 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13748 auto Flags =
Load->getMemOperand()->getFlags();
13750 Load->getAlign(), Flags, &
Fast) &&
13759 MemVT, *
Load->getMemOperand())) {
13768 EVT VT =
Op.getValueType();
13803 SDValue
LHS =
Op.getOperand(0);
13804 SDValue
RHS =
Op.getOperand(1);
13805 EVT VT =
Op.getValueType();
13806 const SDNodeFlags
Flags =
Op->getFlags();
13808 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13814 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13817 if (CLHS->isOne()) {
13830 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13834 if (CLHS->isMinusOne()) {
13837 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13843 if (!AllowInaccurateRcp &&
13844 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13849 SDValue Recip = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13856 SDValue
X =
Op.getOperand(0);
13857 SDValue
Y =
Op.getOperand(1);
13858 EVT VT =
Op.getValueType();
13859 const SDNodeFlags
Flags =
Op->getFlags();
13861 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13862 if (!AllowInaccurateDiv)
13875 SDValue
R = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
Y);
13886 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13898 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13908 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13912 return DAG.
getNode(Opcode, SL, VTList,
13921 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13931 Opcode = AMDGPUISD::FMA_W_CHAIN;
13935 return DAG.
getNode(Opcode, SL, VTList,
13941 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13942 return FastLowered;
13945 EVT VT =
Op.getValueType();
13946 SDValue
LHS =
Op.getOperand(0);
13947 SDValue
RHS =
Op.getOperand(1);
13952 if (VT == MVT::bf16) {
13975 unsigned FMADOpCode =
13979 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
13982 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13984 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
13985 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13995 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
14001 SDNodeFlags
Flags =
Op->getFlags();
14003 SDValue
LHS =
Op.getOperand(1);
14004 SDValue
RHS =
Op.getOperand(2);
14011 const APFloat K0Val(0x1p+96f);
14014 const APFloat K1Val(0x1p-32f);
14029 SDValue
r0 = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32,
r1, Flags);
14041 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
14042 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14043 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14048 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
14049 return FastLowered;
14055 SDNodeFlags
Flags =
Op->getFlags();
14056 Flags.setNoFPExcept(
true);
14059 SDValue
LHS =
Op.getOperand(0);
14060 SDValue
RHS =
Op.getOperand(1);
14064 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
14066 SDValue DenominatorScaled =
14068 SDValue NumeratorScaled =
14072 SDValue ApproxRcp =
14073 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14074 SDValue NegDivScale0 =
14077 using namespace AMDGPU::Hwreg;
14078 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14082 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
14083 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
14086 const bool HasDynamicDenormals =
14090 SDValue SavedDenormMode;
14092 if (!PreservesDenormals) {
14097 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14100 if (HasDynamicDenormals) {
14104 SavedDenormMode = SDValue(GetReg, 0);
14107 {DAG.
getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14110 SDNode *EnableDenorm;
14111 if (Subtarget->hasDenormModeInst()) {
14112 const SDValue EnableDenormValue =
14115 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14119 const SDValue EnableDenormValue =
14121 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14122 {EnableDenormValue,
BitField, Glue});
14125 SDValue
Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14126 SDValue(EnableDenorm, 1)};
14132 ApproxRcp, One, NegDivScale0, Flags);
14135 ApproxRcp, Fma0, Flags);
14141 NumeratorScaled,
Mul, Flags);
14147 NumeratorScaled, Fma3, Flags);
14149 if (!PreservesDenormals) {
14150 SDNode *DisableDenorm;
14151 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14155 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14157 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14161 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14162 const SDValue DisableDenormValue =
14163 HasDynamicDenormals
14168 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14173 SDValue(DisableDenorm, 0), DAG.
getRoot());
14177 SDValue Scale = NumeratorScaled.
getValue(1);
14178 SDValue Fmas = DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14179 {Fma4, Fma1, Fma3, Scale},
Flags);
14181 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14185 if (SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14186 return FastLowered;
14189 SDValue
X =
Op.getOperand(0);
14190 SDValue
Y =
Op.getOperand(1);
14194 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14196 SDValue DivScale0 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
Y,
Y,
X);
14200 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14202 SDValue Fma0 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14206 SDValue Fma2 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14208 SDValue DivScale1 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
X,
Y,
X);
14210 SDValue Fma3 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14218 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14248 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14250 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14254 EVT VT =
Op.getValueType();
14256 if (VT == MVT::f32)
14257 return LowerFDIV32(
Op, DAG);
14259 if (VT == MVT::f64)
14260 return LowerFDIV64(
Op, DAG);
14262 if (VT == MVT::f16 || VT == MVT::bf16)
14263 return LowerFDIV16(
Op, DAG);
14270 SDValue Val =
Op.getOperand(0);
14272 EVT ResultExpVT =
Op->getValueType(1);
14273 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14283 if (Subtarget->hasFractBug()) {
14301 EVT VT =
Store->getMemoryVT();
14303 if (VT == MVT::i1) {
14307 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14311 Store->getValue().getValueType().getScalarType() == MVT::i32);
14313 unsigned AS =
Store->getAddressSpace();
14314 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14322 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14326 !Subtarget->hasMultiDwordFlatScratchAddressing())
14333 if (NumElements > 4)
14336 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14340 VT, *
Store->getMemOperand()))
14346 switch (Subtarget->getMaxPrivateElementSize()) {
14350 if (NumElements > 2)
14354 if (NumElements > 4 ||
14355 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14363 auto Flags =
Store->getMemOperand()->getFlags();
14382 assert(!Subtarget->has16BitInsts());
14383 SDNodeFlags
Flags =
Op->getFlags();
14397 SDNodeFlags
Flags =
Op->getFlags();
14398 MVT VT =
Op.getValueType().getSimpleVT();
14399 const SDValue
X =
Op.getOperand(0);
14425 SDValue SqrtSNextDownInt =
14430 SDValue NegSqrtSNextDown =
14454 SDValue SqrtR = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT, SqrtX, Flags);
14474 SDValue ScaledDown =
14478 SDValue IsZeroOrInf =
14506 SDNodeFlags
Flags =
Op->getFlags();
14510 SDValue
X =
Op.getOperand(0);
14515 if (!
Flags.hasApproximateFuncs()) {
14520 SDValue ScaleUpFactor = DAG.
getConstant(256,
DL, MVT::i32);
14526 SDValue SqrtY = DAG.
getNode(AMDGPUISD::RSQ,
DL, MVT::f64, SqrtX);
14546 SDValue SqrtRet = SqrtS2;
14547 if (!
Flags.hasApproximateFuncs()) {
14556 ScaleDownFactor, ZeroInt);
14562 SDValue IsZeroOrInf;
14563 if (
Flags.hasNoInfs()) {
14579 EVT VT =
Op.getValueType();
14580 SDValue Arg =
Op.getOperand(0);
14589 auto UnrollIfVec = [&DAG](SDValue
V) -> SDValue {
14590 if (!
V.getValueType().isVector())
14598 if (Subtarget->hasTrigReducedRange()) {
14600 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14605 switch (
Op.getOpcode()) {
14607 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14610 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14616 return UnrollIfVec(TrigVal);
14632 SDValue ChainIn =
Op.getOperand(0);
14633 SDValue Addr =
Op.getOperand(1);
14634 SDValue Old =
Op.getOperand(2);
14635 SDValue
New =
Op.getOperand(3);
14636 EVT VT =
Op.getValueType();
14641 SDValue
Ops[] = {ChainIn, Addr, NewOld};
14644 Op->getVTList(),
Ops, VT,
14653SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14654 DAGCombinerInfo &DCI)
const {
14655 EVT VT =
N->getValueType(0);
14657 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14660 SelectionDAG &DAG = DCI.DAG;
14663 SDValue Src =
N->getOperand(0);
14664 EVT SrcVT = Src.getValueType();
14670 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14672 SDValue Cvt = DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0,
DL, MVT::f32, Src);
14673 DCI.AddToWorklist(Cvt.
getNode());
14676 if (ScalarVT != MVT::f32) {
14688 DAGCombinerInfo &DCI)
const {
14699 SelectionDAG &DAG = DCI.DAG;
14718 for (
unsigned I = 0;
I != NumElts; ++
I) {
14726 SDValue SignOpElt =
14742 if (NewElts.
size() == 1)
14764 for (
unsigned I = 0;
I != NumElts; ++
I) {
14766 SDValue SignAsF32 =
14799SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14801 DAGCombinerInfo &DCI)
const {
14818 SelectionDAG &DAG = DCI.DAG;
14831 AM.BaseOffs =
Offset.getSExtValue();
14836 EVT VT =
N->getValueType(0);
14842 Flags.setNoUnsignedWrap(
14843 N->getFlags().hasNoUnsignedWrap() &&
14855 switch (
N->getOpcode()) {
14866 DAGCombinerInfo &DCI)
const {
14867 SelectionDAG &DAG = DCI.DAG;
14874 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14875 N->getMemoryVT(), DCI);
14879 NewOps[PtrIdx] = NewPtr;
14888 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14889 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14898SDValue SITargetLowering::splitBinaryBitConstantOp(
14902 uint32_t ValLo =
Lo_32(Val);
14903 uint32_t ValHi =
Hi_32(Val);
14910 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14924 if (V.getValueType() != MVT::i1)
14926 switch (V.getOpcode()) {
14931 case AMDGPUISD::FP_CLASS:
14943 return V.getResNo() == 1;
14945 unsigned IntrinsicID = V.getConstantOperandVal(0);
14946 switch (IntrinsicID) {
14947 case Intrinsic::amdgcn_is_shared:
14948 case Intrinsic::amdgcn_is_private:
14965 if (!(
C & 0x000000ff))
14966 ZeroByteMask |= 0x000000ff;
14967 if (!(
C & 0x0000ff00))
14968 ZeroByteMask |= 0x0000ff00;
14969 if (!(
C & 0x00ff0000))
14970 ZeroByteMask |= 0x00ff0000;
14971 if (!(
C & 0xff000000))
14972 ZeroByteMask |= 0xff000000;
14973 uint32_t NonZeroByteMask = ~ZeroByteMask;
14974 if ((NonZeroByteMask &
C) != NonZeroByteMask)
14987 assert(V.getValueSizeInBits() == 32);
14989 if (V.getNumOperands() != 2)
14998 switch (V.getOpcode()) {
15003 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15008 return (0x03020100 & ~ConstMask) | ConstMask;
15015 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
15021 return uint32_t(0x0c0c0c0c03020100ull >>
C);
15028 DAGCombinerInfo &DCI)
const {
15029 if (DCI.isBeforeLegalize())
15032 SelectionDAG &DAG = DCI.DAG;
15033 EVT VT =
N->getValueType(0);
15034 SDValue
LHS =
N->getOperand(0);
15035 SDValue
RHS =
N->getOperand(1);
15038 if (VT == MVT::i64 && CRHS) {
15039 if (SDValue Split =
15040 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
15044 if (CRHS && VT == MVT::i32) {
15054 unsigned Shift = CShift->getZExtValue();
15056 unsigned Offset = NB + Shift;
15057 if ((
Offset & (Bits - 1)) == 0) {
15060 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
15081 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15083 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15093 if (Shift && Shift->getZExtValue() < 16 &&
15110 SDValue
X =
LHS.getOperand(0);
15111 SDValue
Y =
RHS.getOperand(0);
15112 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
15117 if (
X !=
LHS.getOperand(1))
15121 const ConstantFPSDNode *C1 =
15138 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15144 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15147 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15155 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15156 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15158 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15159 :
Mask->getZExtValue() & OrdMask;
15162 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15180 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15183 if (LHSMask != ~0u && RHSMask != ~0u) {
15186 if (LHSMask > RHSMask) {
15193 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15194 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15197 if (!(LHSUsedLanes & RHSUsedLanes) &&
15200 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15206 uint32_t
Mask = LHSMask & RHSMask;
15207 for (
unsigned I = 0;
I < 32;
I += 8) {
15208 uint32_t ByteSel = 0xff <<
I;
15209 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15210 Mask &= (0x0c <<
I) & 0xffffffff;
15215 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15218 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15268static const std::optional<ByteProvider<SDValue>>
15270 unsigned Depth = 0) {
15273 return std::nullopt;
15275 if (
Op.getValueSizeInBits() < 8)
15276 return std::nullopt;
15278 if (
Op.getValueType().isVector())
15281 switch (
Op->getOpcode()) {
15294 NarrowVT = VTSign->getVT();
15297 return std::nullopt;
15300 if (SrcIndex >= NarrowByteWidth)
15301 return std::nullopt;
15309 return std::nullopt;
15311 uint64_t BitShift = ShiftOp->getZExtValue();
15313 if (BitShift % 8 != 0)
15314 return std::nullopt;
15316 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15317 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15318 return std::nullopt;
15337static const std::optional<ByteProvider<SDValue>>
15339 unsigned StartingIndex = 0) {
15343 return std::nullopt;
15345 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15347 return std::nullopt;
15349 return std::nullopt;
15351 bool IsVec =
Op.getValueType().isVector();
15352 switch (
Op.getOpcode()) {
15355 return std::nullopt;
15360 return std::nullopt;
15364 return std::nullopt;
15367 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15368 return std::nullopt;
15369 if (!
LHS ||
LHS->isConstantZero())
15371 if (!
RHS ||
RHS->isConstantZero())
15373 return std::nullopt;
15378 return std::nullopt;
15382 return std::nullopt;
15384 uint32_t BitMask = BitMaskOp->getZExtValue();
15386 uint32_t IndexMask = 0xFF << (Index * 8);
15388 if ((IndexMask & BitMask) != IndexMask) {
15391 if (IndexMask & BitMask)
15392 return std::nullopt;
15401 return std::nullopt;
15405 if (!ShiftOp ||
Op.getValueType().isVector())
15406 return std::nullopt;
15408 uint64_t BitsProvided =
Op.getValueSizeInBits();
15409 if (BitsProvided % 8 != 0)
15410 return std::nullopt;
15412 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15414 return std::nullopt;
15416 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15417 uint64_t ByteShift = BitShift / 8;
15419 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15420 uint64_t BytesProvided = BitsProvided / 8;
15421 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15422 NewIndex %= BytesProvided;
15429 return std::nullopt;
15433 return std::nullopt;
15435 uint64_t BitShift = ShiftOp->getZExtValue();
15437 return std::nullopt;
15439 auto BitsProvided =
Op.getScalarValueSizeInBits();
15440 if (BitsProvided % 8 != 0)
15441 return std::nullopt;
15443 uint64_t BytesProvided = BitsProvided / 8;
15444 uint64_t ByteShift = BitShift / 8;
15445 if (Index + ByteShift < BytesProvided)
15447 Index + ByteShift);
15450 return std::nullopt;
15456 return std::nullopt;
15460 return std::nullopt;
15462 uint64_t BitShift = ShiftOp->getZExtValue();
15463 if (BitShift % 8 != 0)
15464 return std::nullopt;
15465 uint64_t ByteShift = BitShift / 8;
15471 return Index < ByteShift
15474 Depth + 1, StartingIndex);
15483 return std::nullopt;
15491 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15493 if (NarrowBitWidth % 8 != 0)
15494 return std::nullopt;
15495 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15497 if (Index >= NarrowByteWidth)
15499 ? std::optional<ByteProvider<SDValue>>(
15507 return std::nullopt;
15511 if (NarrowByteWidth >= Index) {
15516 return std::nullopt;
15523 return std::nullopt;
15529 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15530 if (NarrowBitWidth % 8 != 0)
15531 return std::nullopt;
15532 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15537 if (Index >= NarrowByteWidth) {
15539 ? std::optional<ByteProvider<SDValue>>(
15544 if (NarrowByteWidth > Index) {
15548 return std::nullopt;
15553 return std::nullopt;
15556 Depth + 1, StartingIndex);
15562 return std::nullopt;
15563 auto VecIdx = IdxOp->getZExtValue();
15564 auto ScalarSize =
Op.getScalarValueSizeInBits();
15565 if (ScalarSize < 32)
15566 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15568 StartingIndex, Index);
15571 case AMDGPUISD::PERM: {
15573 return std::nullopt;
15577 return std::nullopt;
15580 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15581 if (IdxMask > 0x07 && IdxMask != 0x0c)
15582 return std::nullopt;
15584 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15585 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15587 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15593 return std::nullopt;
15608 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15615 auto MemVT = L->getMemoryVT();
15618 return L->getMemoryVT().getSizeInBits() == 16;
15628 int Low8 = Mask & 0xff;
15629 int Hi8 = (Mask & 0xff00) >> 8;
15631 assert(Low8 < 8 && Hi8 < 8);
15633 bool IsConsecutive = (Hi8 - Low8 == 1);
15638 bool Is16Aligned = !(Low8 % 2);
15640 return IsConsecutive && Is16Aligned;
15648 int Low16 = PermMask & 0xffff;
15649 int Hi16 = (PermMask & 0xffff0000) >> 16;
15659 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15661 if (!OtherOpIs16Bit)
15669 unsigned DWordOffset) {
15674 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15679 if (Src.getValueType().isVector()) {
15680 auto ScalarTySize = Src.getScalarValueSizeInBits();
15681 auto ScalarTy = Src.getValueType().getScalarType();
15682 if (ScalarTySize == 32) {
15686 if (ScalarTySize > 32) {
15689 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15690 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15697 assert(ScalarTySize < 32);
15706 auto NumElements =
TypeSize / ScalarTySize;
15707 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15708 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15709 auto NumElementsIn32 = 32 / ScalarTySize;
15710 auto NumAvailElements = DWordOffset < Trunc32Elements
15712 : NumElements - NormalizedTrunc;
15725 auto ShiftVal = 32 * DWordOffset;
15733 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15738 for (
int i = 0; i < 4; i++) {
15740 std::optional<ByteProvider<SDValue>>
P =
15743 if (!
P ||
P->isConstantZero())
15748 if (PermNodes.
size() != 4)
15751 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15752 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15754 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15755 auto PermOp = PermNodes[i];
15758 int SrcByteAdjust = 4;
15762 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15763 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15765 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15766 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15770 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15771 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15774 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15776 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15779 SDValue Op = *PermNodes[FirstSrc.first].Src;
15781 assert(
Op.getValueSizeInBits() == 32);
15785 int Low16 = PermMask & 0xffff;
15786 int Hi16 = (PermMask & 0xffff0000) >> 16;
15788 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15789 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15792 if (WellFormedLow && WellFormedHi)
15796 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15805 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15806 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15811 assert(
Op.getValueType().isByteSized() &&
15822 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15829 DAGCombinerInfo &DCI)
const {
15830 SelectionDAG &DAG = DCI.DAG;
15831 SDValue
LHS =
N->getOperand(0);
15832 SDValue
RHS =
N->getOperand(1);
15834 EVT VT =
N->getValueType(0);
15835 if (VT == MVT::i1) {
15837 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15838 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15839 SDValue Src =
LHS.getOperand(0);
15840 if (Src !=
RHS.getOperand(0))
15845 if (!CLHS || !CRHS)
15849 static const uint32_t MaxMask = 0x3ff;
15854 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15863 LHS.getOpcode() == AMDGPUISD::PERM &&
15869 Sel |=
LHS.getConstantOperandVal(2);
15871 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15878 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15882 auto usesCombinedOperand = [](SDNode *OrUse) {
15885 !OrUse->getValueType(0).isVector())
15889 for (
auto *VUser : OrUse->users()) {
15890 if (!VUser->getValueType(0).isVector())
15897 if (VUser->getOpcode() == VectorwiseOp)
15903 if (!
any_of(
N->users(), usesCombinedOperand))
15909 if (LHSMask != ~0u && RHSMask != ~0u) {
15912 if (LHSMask > RHSMask) {
15919 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15920 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15923 if (!(LHSUsedLanes & RHSUsedLanes) &&
15926 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15928 LHSMask &= ~RHSUsedLanes;
15929 RHSMask &= ~LHSUsedLanes;
15931 LHSMask |= LHSUsedLanes & 0x04040404;
15933 uint32_t Sel = LHSMask | RHSMask;
15936 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15941 if (LHSMask == ~0u || RHSMask == ~0u) {
15972 SDValue LEVE =
LHS->getOperand(0);
15973 SDValue REVE =
RHS->getOperand(1);
15982 return IdentitySrc;
15988 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
16001 SDValue ExtSrc =
RHS.getOperand(0);
16003 if (SrcVT == MVT::i32) {
16006 SDValue LowOr = DAG.
getNode(
ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
16008 DCI.AddToWorklist(LowOr.
getNode());
16009 DCI.AddToWorklist(HiBits.getNode());
16019 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::OR,
16020 N->getOperand(0), CRHS))
16028 DAGCombinerInfo &DCI)
const {
16029 if (SDValue RV = reassociateScalarOps(
N, DCI.DAG))
16032 SDValue
LHS =
N->getOperand(0);
16033 SDValue
RHS =
N->getOperand(1);
16036 SelectionDAG &DAG = DCI.DAG;
16038 EVT VT =
N->getValueType(0);
16039 if (CRHS && VT == MVT::i64) {
16040 if (SDValue Split =
16041 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
16048 unsigned Opc =
LHS.getOpcode();
16052 SDValue CC =
LHS->getOperand(0);
16053 SDValue TRUE =
LHS->getOperand(1);
16054 SDValue FALSE =
LHS->getOperand(2);
16078 LHS->getOperand(0), FNegLHS, FNegRHS);
16087SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
16088 DAGCombinerInfo &DCI)
const {
16089 if (!Subtarget->has16BitInsts() ||
16093 EVT VT =
N->getValueType(0);
16094 if (VT != MVT::i32)
16097 SDValue Src =
N->getOperand(0);
16098 if (Src.getValueType() != MVT::i16)
16101 if (!Src->hasOneUse())
16104 if (SDValue Ext = performExtendTruncShiftCombine(
N, DCI))
16111 std::optional<ByteProvider<SDValue>> BP0 =
16113 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16115 SDValue
V0 = *BP0->Src;
16117 std::optional<ByteProvider<SDValue>> BP1 =
16119 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16122 SDValue
V1 = *BP1->Src;
16127 SelectionDAG &DAG = DCI.DAG;
16129 uint32_t PermMask = 0x0c0c0c0c;
16132 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16137 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16140 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16148SITargetLowering::performExtendTruncShiftCombine(
SDNode *
N,
16149 DAGCombinerInfo &DCI)
const {
16153 const unsigned Opc =
N->getOpcode();
16155 SDValue Src =
N->getOperand(0);
16156 if (
N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16157 Src.getOpcode() != (IsSigned ?
ISD::SRA :
ISD::SRL) || !Src.hasOneUse() ||
16163 if (!IsSigned && !Src->isDivergent())
16166 SDValue
X = Src.getOperand(0).getOperand(0);
16168 if (
X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16169 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16172 SelectionDAG &DAG = DCI.DAG;
16174 const unsigned Width = 16 - Shift->getZExtValue();
16187SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16188 DAGCombinerInfo &DCI)
const {
16189 SDValue Src =
N->getOperand(0);
16194 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16195 VTSign->getVT() == MVT::i8) ||
16196 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16197 VTSign->getVT() == MVT::i16))) {
16198 assert(Subtarget->hasScalarSubwordLoads() &&
16199 "s_buffer_load_{u8, i8} are supported "
16200 "in GFX12 (or newer) architectures.");
16201 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16202 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16203 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16206 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16214 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16215 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16216 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16218 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16219 VTSign->getVT() == MVT::i8) ||
16220 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16221 VTSign->getVT() == MVT::i16)) &&
16224 SDValue
Ops[] = {Src.getOperand(0),
16230 Src.getOperand(6), Src.getOperand(7)};
16233 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16234 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16235 ? AMDGPUISD::BUFFER_LOAD_BYTE
16236 : AMDGPUISD::BUFFER_LOAD_SHORT;
16237 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16238 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16239 return DCI.DAG.getMergeValues(
16240 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16246 DAGCombinerInfo &DCI)
const {
16247 SelectionDAG &DAG = DCI.DAG;
16248 SDValue
Mask =
N->getOperand(1);
16254 if (
N->getOperand(0).isUndef())
16261 DAGCombinerInfo &DCI)
const {
16262 EVT VT =
N->getValueType(0);
16273 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16282 unsigned MaxDepth)
const {
16283 EVT VT =
Op.getValueType();
16285 "expected a floating-point value to query canonicality of");
16291 unsigned MaxDepth)
const {
16293 "QueryVT must be a floating-point scalar type");
16294 EVT VT =
Op.getValueType();
16298 unsigned Opcode =
Op.getOpcode();
16303 const auto &
F = CFP->getValueAPF();
16304 if (
F.isNaN() &&
F.isSignaling())
16306 if (!
F.isDenormal())
16338 case AMDGPUISD::FMUL_LEGACY:
16339 case AMDGPUISD::FMAD_FTZ:
16340 case AMDGPUISD::RCP:
16341 case AMDGPUISD::RSQ:
16342 case AMDGPUISD::RSQ_CLAMP:
16343 case AMDGPUISD::RCP_LEGACY:
16344 case AMDGPUISD::RCP_IFLAG:
16345 case AMDGPUISD::LOG:
16346 case AMDGPUISD::EXP:
16347 case AMDGPUISD::DIV_SCALE:
16348 case AMDGPUISD::DIV_FMAS:
16349 case AMDGPUISD::DIV_FIXUP:
16350 case AMDGPUISD::FRACT:
16351 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16352 case AMDGPUISD::CVT_F32_UBYTE0:
16353 case AMDGPUISD::CVT_F32_UBYTE1:
16354 case AMDGPUISD::CVT_F32_UBYTE2:
16355 case AMDGPUISD::CVT_F32_UBYTE3:
16356 case AMDGPUISD::FP_TO_FP16:
16357 case AMDGPUISD::SIN_HW:
16358 case AMDGPUISD::COS_HW:
16370 if (
Op.getValueType() == MVT::i32) {
16376 if (RHS->getZExtValue() == 0xffff0000) {
16387 return Op.getValueType().getScalarType() != MVT::f16;
16397 case AMDGPUISD::CLAMP:
16398 case AMDGPUISD::FMED3:
16399 case AMDGPUISD::FMAX3:
16400 case AMDGPUISD::FMIN3:
16401 case AMDGPUISD::FMAXIMUM3:
16402 case AMDGPUISD::FMINIMUM3: {
16408 if (Subtarget->supportsMinMaxDenormModes() ||
16418 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16433 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16467 if (
Op.getValueType() == MVT::i16) {
16479 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16481 switch (IntrinsicID) {
16482 case Intrinsic::amdgcn_cvt_pkrtz:
16483 case Intrinsic::amdgcn_cubeid:
16484 case Intrinsic::amdgcn_frexp_mant:
16485 case Intrinsic::amdgcn_fdot2:
16486 case Intrinsic::amdgcn_rcp:
16487 case Intrinsic::amdgcn_rsq:
16488 case Intrinsic::amdgcn_rsq_clamp:
16489 case Intrinsic::amdgcn_rcp_legacy:
16490 case Intrinsic::amdgcn_rsq_legacy:
16491 case Intrinsic::amdgcn_trig_preop:
16492 case Intrinsic::amdgcn_tanh:
16493 case Intrinsic::amdgcn_log:
16494 case Intrinsic::amdgcn_exp2:
16495 case Intrinsic::amdgcn_sqrt:
16513 unsigned MaxDepth)
const {
16516 unsigned Opcode =
MI->getOpcode();
16518 if (Opcode == AMDGPU::G_FCANONICALIZE)
16521 std::optional<FPValueAndVReg> FCR;
16524 if (FCR->Value.isSignaling())
16526 if (!FCR->Value.isDenormal())
16537 case AMDGPU::G_FADD:
16538 case AMDGPU::G_FSUB:
16539 case AMDGPU::G_FMUL:
16540 case AMDGPU::G_FCEIL:
16541 case AMDGPU::G_FFLOOR:
16542 case AMDGPU::G_FRINT:
16543 case AMDGPU::G_FNEARBYINT:
16544 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16545 case AMDGPU::G_INTRINSIC_TRUNC:
16546 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16547 case AMDGPU::G_FMA:
16548 case AMDGPU::G_FMAD:
16549 case AMDGPU::G_FSQRT:
16550 case AMDGPU::G_FDIV:
16551 case AMDGPU::G_FREM:
16552 case AMDGPU::G_FPOW:
16553 case AMDGPU::G_FPEXT:
16554 case AMDGPU::G_FLOG:
16555 case AMDGPU::G_FLOG2:
16556 case AMDGPU::G_FLOG10:
16557 case AMDGPU::G_FPTRUNC:
16558 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16559 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16560 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16561 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16562 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16564 case AMDGPU::G_FNEG:
16565 case AMDGPU::G_FABS:
16566 case AMDGPU::G_FCOPYSIGN:
16568 case AMDGPU::G_FMINNUM:
16569 case AMDGPU::G_FMAXNUM:
16570 case AMDGPU::G_FMINNUM_IEEE:
16571 case AMDGPU::G_FMAXNUM_IEEE:
16572 case AMDGPU::G_FMINIMUM:
16573 case AMDGPU::G_FMAXIMUM:
16574 case AMDGPU::G_FMINIMUMNUM:
16575 case AMDGPU::G_FMAXIMUMNUM: {
16576 if (Subtarget->supportsMinMaxDenormModes() ||
16583 case AMDGPU::G_BUILD_VECTOR:
16588 case AMDGPU::G_INTRINSIC:
16589 case AMDGPU::G_INTRINSIC_CONVERGENT:
16591 case Intrinsic::amdgcn_fmul_legacy:
16592 case Intrinsic::amdgcn_fmad_ftz:
16593 case Intrinsic::amdgcn_sqrt:
16594 case Intrinsic::amdgcn_fmed3:
16595 case Intrinsic::amdgcn_sin:
16596 case Intrinsic::amdgcn_cos:
16597 case Intrinsic::amdgcn_log:
16598 case Intrinsic::amdgcn_exp2:
16599 case Intrinsic::amdgcn_log_clamp:
16600 case Intrinsic::amdgcn_rcp:
16601 case Intrinsic::amdgcn_rcp_legacy:
16602 case Intrinsic::amdgcn_rsq:
16603 case Intrinsic::amdgcn_rsq_clamp:
16604 case Intrinsic::amdgcn_rsq_legacy:
16605 case Intrinsic::amdgcn_div_scale:
16606 case Intrinsic::amdgcn_div_fmas:
16607 case Intrinsic::amdgcn_div_fixup:
16608 case Intrinsic::amdgcn_fract:
16609 case Intrinsic::amdgcn_cvt_pkrtz:
16610 case Intrinsic::amdgcn_cubeid:
16611 case Intrinsic::amdgcn_cubema:
16612 case Intrinsic::amdgcn_cubesc:
16613 case Intrinsic::amdgcn_cubetc:
16614 case Intrinsic::amdgcn_frexp_mant:
16615 case Intrinsic::amdgcn_fdot2:
16616 case Intrinsic::amdgcn_trig_preop:
16617 case Intrinsic::amdgcn_tanh:
16636 if (
C.isDenormal()) {
16649 if (
C.isSignaling()) {
16664SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16665 DAGCombinerInfo &DCI)
const {
16666 SelectionDAG &DAG = DCI.DAG;
16668 EVT VT =
N->getValueType(0);
16677 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16689 SDValue NewElts[2];
16692 EVT EltVT =
Lo.getValueType();
16701 for (
unsigned I = 0;
I != 2; ++
I) {
16705 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16706 }
else if (
Op.isUndef()) {
16741 return AMDGPUISD::FMAX3;
16743 return AMDGPUISD::FMAXIMUM3;
16745 return AMDGPUISD::SMAX3;
16747 return AMDGPUISD::UMAX3;
16751 return AMDGPUISD::FMIN3;
16753 return AMDGPUISD::FMINIMUM3;
16755 return AMDGPUISD::SMIN3;
16757 return AMDGPUISD::UMIN3;
16778 if (!MinK || !MaxK)
16790 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16791 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16792 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16816 bool IsKnownNoNaNs)
const {
16852 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16858 if (
Info->getMode().DX10Clamp) {
16867 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16881 SDValue(K0, 0), SDValue(K1, 0));
16899 case AMDGPUISD::FMIN_LEGACY:
16900 case AMDGPUISD::FMAX_LEGACY:
16901 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.
hasMin3Max3_16()) ||
16902 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16905 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16906 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16907 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16912 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.
hasMin3Max3_16());
16921 DAGCombinerInfo &DCI)
const {
16922 SelectionDAG &DAG = DCI.DAG;
16933 auto IsTreeWithCombinableChildren = [
Opc](SDValue
Op) {
16934 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16935 Op.getOperand(0).hasOneUse()) ||
16937 Op.getOperand(1).hasOneUse());
16942 bool HasCombinableTreeChild =
16943 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16944 IsTreeWithCombinableChildren(Op1));
16953 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16991 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
16999 if (SDValue Med3 = performIntMed3ImmCombine(
17004 if (SDValue Med3 = performIntMed3ImmCombine(
17010 if (SDValue Med3 = performIntMed3ImmCombine(
17015 if (SDValue Med3 = performIntMed3ImmCombine(
17028 (
Opc == AMDGPUISD::FMIN_LEGACY &&
17029 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17030 (VT == MVT::f32 || VT == MVT::f64 ||
17031 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17032 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17033 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17034 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17036 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
17037 N->getFlags().hasNoNaNs()))
17044 const SDNodeFlags
Flags =
N->getFlags();
17046 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17050 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
17060 return (CA->isPosZero() && CB->isOne()) ||
17061 (CA->isOne() && CB->isPosZero());
17070 DAGCombinerInfo &DCI)
const {
17071 EVT VT =
N->getValueType(0);
17075 SelectionDAG &DAG = DCI.DAG;
17078 SDValue
Src0 =
N->getOperand(0);
17079 SDValue
Src1 =
N->getOperand(1);
17080 SDValue
Src2 =
N->getOperand(2);
17086 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17090 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
17094 if (
Info->getMode().DX10Clamp) {
17107 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17114 DAGCombinerInfo &DCI)
const {
17115 SDValue
Src0 =
N->getOperand(0);
17116 SDValue
Src1 =
N->getOperand(1);
17117 if (
Src0.isUndef() &&
Src1.isUndef())
17118 return DCI.DAG.getUNDEF(
N->getValueType(0));
17126 bool IsDivergentIdx,
17131 unsigned VecSize = EltSize * NumElem;
17134 if (VecSize <= 64 && EltSize < 32)
17143 if (IsDivergentIdx)
17147 unsigned NumInsts = NumElem +
17148 ((EltSize + 31) / 32) * NumElem ;
17152 if (Subtarget->useVGPRIndexMode())
17153 return NumInsts <= 16;
17157 if (Subtarget->hasMovrel())
17158 return NumInsts <= 15;
17164 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17175 EltSize, NumElem, Idx->isDivergent(),
getSubtarget());
17179SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17180 DAGCombinerInfo &DCI)
const {
17186 EVT ResVT =
N->getValueType(0);
17210 if (!
C ||
C->getZExtValue() != 0x1f)
17226 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17228 SDValue
Idx =
N->getOperand(1);
17254 DCI.AddToWorklist(Elt0.
getNode());
17255 DCI.AddToWorklist(Elt1.
getNode());
17264 SDValue
Idx =
N->getOperand(1);
17286 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17287 uint64_t KImmValue = KImm->getZExtValue();
17289 (KImmValue >> (32 *
Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17292 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17294 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17295 return DAG.
getConstant((KFPImmValue >> (32 *
Idx->getZExtValue())) &
17301 if (!DCI.isBeforeLegalize())
17308 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17311 unsigned BitIndex =
Idx->getZExtValue() * VecEltSize;
17312 unsigned EltIdx = BitIndex / 32;
17313 unsigned LeftoverBitIdx = BitIndex % 32;
17317 DCI.AddToWorklist(Cast.
getNode());
17321 DCI.AddToWorklist(Elt.
getNode());
17324 DCI.AddToWorklist(Srl.
getNode());
17328 DCI.AddToWorklist(Trunc.
getNode());
17330 if (VecEltVT == ResVT) {
17342SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17343 DAGCombinerInfo &DCI)
const {
17345 SDValue
Idx =
N->getOperand(2);
17354 SelectionDAG &DAG = DCI.DAG;
17357 EVT IdxVT =
Idx.getValueType();
17374 Src.getOperand(0).getValueType() == MVT::f16) {
17375 return Src.getOperand(0);
17379 APFloat Val = CFP->getValueAPF();
17380 bool LosesInfo =
true;
17390 DAGCombinerInfo &DCI)
const {
17391 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17392 "combine only useful on gfx8");
17394 SDValue TruncSrc =
N->getOperand(0);
17395 EVT VT =
N->getValueType(0);
17396 if (VT != MVT::f16)
17399 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17403 SelectionDAG &DAG = DCI.DAG;
17434unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17436 const SDNode *N1)
const {
17441 if (((VT == MVT::f32 &&
17443 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17460 EVT VT =
N->getValueType(0);
17461 if (VT != MVT::i32 && VT != MVT::i64)
17467 unsigned Opc =
N->getOpcode();
17489 SDValue Add1 = DAG.
getNode(
Opc, SL, VT, Op0, Op1);
17522 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17541 DAGCombinerInfo &DCI)
const {
17544 SelectionDAG &DAG = DCI.DAG;
17545 EVT VT =
N->getValueType(0);
17547 SDValue
LHS =
N->getOperand(0);
17548 SDValue
RHS =
N->getOperand(1);
17555 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17559 if (NumBits <= 32 || NumBits > 64)
17570 if (!Subtarget->hasFullRate64Ops()) {
17571 unsigned NumUsers = 0;
17572 for (SDNode *User :
LHS->
users()) {
17575 if (!
User->isAnyAdd())
17586 SDValue MulLHS =
LHS.getOperand(0);
17587 SDValue MulRHS =
LHS.getOperand(1);
17588 SDValue AddRHS =
RHS;
17599 bool MulSignedLo =
false;
17600 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17609 if (VT != MVT::i64) {
17632 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17634 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17635 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17637 if (!MulLHSUnsigned32) {
17640 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17644 if (!MulRHSUnsigned32) {
17647 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17655 if (VT != MVT::i64)
17661SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17662 DAGCombinerInfo &DCI)
const {
17663 SDValue
RHS =
N->getOperand(1);
17672 SelectionDAG &DAG = DCI.DAG;
17674 SDValue
LHS =
N->getOperand(0);
17687 unsigned Opcode =
N->getOpcode();
17691 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17702static std::optional<ByteProvider<SDValue>>
17705 if (!Byte0 || Byte0->isConstantZero()) {
17706 return std::nullopt;
17709 if (Byte1 && !Byte1->isConstantZero()) {
17710 return std::nullopt;
17716 unsigned FirstCs =
First & 0x0c0c0c0c;
17717 unsigned SecondCs = Second & 0x0c0c0c0c;
17718 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17719 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17721 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17722 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17723 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17724 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17726 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17740 assert(Src0.Src.has_value() && Src1.Src.has_value());
17743 Src0s.
push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17744 Src0.SrcOffset / 4});
17745 Src1s.
push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17746 Src1.SrcOffset / 4});
17750 for (
int BPI = 0; BPI < 2; BPI++) {
17753 BPP = {Src1, Src0};
17755 unsigned ZeroMask = 0x0c0c0c0c;
17756 unsigned FMask = 0xFF << (8 * (3 - Step));
17758 unsigned FirstMask =
17759 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17760 unsigned SecondMask =
17761 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17765 int FirstGroup = -1;
17766 for (
int I = 0;
I < 2;
I++) {
17768 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17769 return IterElt.SrcOp == *BPP.first.Src &&
17770 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17774 if (Match != Srcs.
end()) {
17775 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17780 if (FirstGroup != -1) {
17782 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17783 return IterElt.SrcOp == *BPP.second.Src &&
17784 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17787 if (Match != Srcs.
end()) {
17788 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17790 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17798 unsigned ZeroMask = 0x0c0c0c0c;
17799 unsigned FMask = 0xFF << (8 * (3 - Step));
17803 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17804 Src0.SrcOffset / 4});
17807 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17808 Src1.SrcOffset / 4});
17816 if (Srcs.
size() == 1) {
17817 auto *Elt = Srcs.
begin();
17821 if (Elt->PermMask == 0x3020100)
17824 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17828 auto *FirstElt = Srcs.
begin();
17829 auto *SecondElt = std::next(FirstElt);
17836 auto FirstMask = FirstElt->PermMask;
17837 auto SecondMask = SecondElt->PermMask;
17839 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17840 unsigned FirstPlusFour = FirstMask | 0x04040404;
17843 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17855 FirstElt = std::next(SecondElt);
17856 if (FirstElt == Srcs.
end())
17859 SecondElt = std::next(FirstElt);
17862 if (SecondElt == Srcs.
end()) {
17867 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17868 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17874 return Perms.
size() == 2
17880 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17881 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17882 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17883 EntryMask += ZeroMask;
17888 auto Opcode =
Op.getOpcode();
17890 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17891 Opcode == AMDGPUISD::MUL_I24);
17894static std::optional<bool>
17905 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17908 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17910 assert(!(S0IsUnsigned && S0IsSigned));
17911 assert(!(S1IsUnsigned && S1IsSigned));
17919 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17925 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17926 return std::nullopt;
17938 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17939 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17944 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17950 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17951 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17952 return std::nullopt;
17958 DAGCombinerInfo &DCI)
const {
17959 SelectionDAG &DAG = DCI.DAG;
17960 EVT VT =
N->getValueType(0);
17962 SDValue
LHS =
N->getOperand(0);
17963 SDValue
RHS =
N->getOperand(1);
17966 if (Subtarget->hasMad64_32()) {
17967 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
17972 if (SDValue V = reassociateScalarOps(
N, DAG)) {
17976 if (VT == MVT::i64) {
17977 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17984 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17985 SDValue TempNode(
N, 0);
17986 std::optional<bool> IsSigned;
17992 int ChainLength = 0;
17993 for (
int I = 0;
I < 4;
I++) {
18005 TempNode->getOperand(MulIdx), *Src0, *Src1,
18006 TempNode->getOperand(MulIdx)->getOperand(0),
18007 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18011 IsSigned = *IterIsSigned;
18012 if (*IterIsSigned != *IsSigned)
18015 auto AddIdx = 1 - MulIdx;
18018 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
18019 Src2s.
push_back(TempNode->getOperand(AddIdx));
18029 TempNode->getOperand(AddIdx), *Src0, *Src1,
18030 TempNode->getOperand(AddIdx)->getOperand(0),
18031 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18035 if (*IterIsSigned != *IsSigned)
18039 ChainLength =
I + 2;
18043 TempNode = TempNode->getOperand(AddIdx);
18045 ChainLength =
I + 1;
18047 if (TempNode.getOpcode() !=
ISD::ADD)
18049 LHS = TempNode->getOperand(0);
18050 RHS = TempNode->getOperand(1);
18053 if (ChainLength < 2)
18059 if (ChainLength < 4) {
18069 bool UseOriginalSrc =
false;
18070 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
18071 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
18072 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
18073 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
18074 SmallVector<unsigned, 4> SrcBytes;
18075 auto Src0Mask = Src0s.
begin()->PermMask;
18076 SrcBytes.
push_back(Src0Mask & 0xFF000000);
18077 bool UniqueEntries =
true;
18078 for (
auto I = 1;
I < 4;
I++) {
18079 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
18082 UniqueEntries =
false;
18088 if (UniqueEntries) {
18089 UseOriginalSrc =
true;
18091 auto *FirstElt = Src0s.
begin();
18095 auto *SecondElt = Src1s.
begin();
18097 SecondElt->DWordOffset);
18106 if (!UseOriginalSrc) {
18113 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18116 : Intrinsic::amdgcn_udot4,
18126 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18131 unsigned Opc =
LHS.getOpcode();
18143 auto Cond =
RHS.getOperand(0);
18148 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18157 SDValue
Args[] = {
LHS,
RHS.getOperand(0),
RHS.getOperand(2)};
18165 DAGCombinerInfo &DCI)
const {
18166 SelectionDAG &DAG = DCI.DAG;
18168 EVT VT =
N->getValueType(0);
18181 SDNodeFlags ShlFlags = N1->
getFlags();
18185 SDNodeFlags NewShlFlags =
18190 DCI.AddToWorklist(Inner.
getNode());
18197 if (Subtarget->hasMad64_32()) {
18198 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
18207 if (VT == MVT::i64) {
18208 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18221 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18222 Y->isDivergent() !=
Z->isDivergent()) {
18231 if (
Y->isDivergent())
18234 SDNodeFlags ReassocFlags =
18237 DCI.AddToWorklist(UniformInner.
getNode());
18249 DAGCombinerInfo &DCI)
const {
18250 SelectionDAG &DAG = DCI.DAG;
18251 EVT VT =
N->getValueType(0);
18253 if (VT == MVT::i64) {
18254 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18258 if (VT != MVT::i32)
18262 SDValue
LHS =
N->getOperand(0);
18263 SDValue
RHS =
N->getOperand(1);
18267 unsigned Opc =
RHS.getOpcode();
18274 auto Cond =
RHS.getOperand(0);
18279 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18290 SDValue
Args[] = {
LHS.getOperand(0),
RHS,
LHS.getOperand(2)};
18296 SDValue CtlzSrc =
LHS.getOperand(0);
18305 ConstantSDNode *ShiftAmt =
18307 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18318 DAGCombinerInfo &DCI)
const {
18322 SelectionDAG &DAG = DCI.DAG;
18323 EVT VT =
N->getValueType(0);
18326 SDValue
LHS =
N->getOperand(0);
18327 SDValue
RHS =
N->getOperand(1);
18334 SDValue
A =
LHS.getOperand(0);
18335 if (
A ==
LHS.getOperand(1)) {
18336 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18337 if (FusedOp != 0) {
18339 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18346 SDValue
A =
RHS.getOperand(0);
18347 if (
A ==
RHS.getOperand(1)) {
18348 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18349 if (FusedOp != 0) {
18351 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18360 DAGCombinerInfo &DCI)
const {
18364 SelectionDAG &DAG = DCI.DAG;
18366 EVT VT =
N->getValueType(0);
18374 SDValue
LHS =
N->getOperand(0);
18375 SDValue
RHS =
N->getOperand(1);
18378 SDValue
A =
LHS.getOperand(0);
18379 if (
A ==
LHS.getOperand(1)) {
18380 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18381 if (FusedOp != 0) {
18385 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18393 SDValue
A =
RHS.getOperand(0);
18394 if (
A ==
RHS.getOperand(1)) {
18395 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18396 if (FusedOp != 0) {
18398 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18407 DAGCombinerInfo &DCI)
const {
18408 SelectionDAG &DAG = DCI.DAG;
18410 EVT VT =
N->getValueType(0);
18412 if (VT != MVT::f16 && VT != MVT::bf16)
18415 SDValue
LHS =
N->getOperand(0);
18416 SDValue
RHS =
N->getOperand(1);
18418 SDNodeFlags
Flags =
N->getFlags();
18419 SDNodeFlags RHSFlags =
RHS->getFlags();
18425 bool IsNegative =
false;
18426 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18431 SDValue SqrtOp =
RHS.getOperand(0);
18435 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18436 }
else if (VT == MVT::f16) {
18445 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18462 DAGCombinerInfo &DCI)
const {
18463 SelectionDAG &DAG = DCI.DAG;
18464 EVT VT =
N->getValueType(0);
18468 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18469 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18474 SDValue
LHS =
N->getOperand(0);
18475 SDValue
RHS =
N->getOperand(1);
18484 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18489 const ConstantFPSDNode *FalseNode =
18499 if (ScalarVT == MVT::f32 &&
18505 if (TrueNodeExpVal == INT_MIN)
18508 if (FalseNodeExpVal == INT_MIN)
18512 SDValue SelectNode =
18528 DAGCombinerInfo &DCI)
const {
18529 SelectionDAG &DAG = DCI.DAG;
18530 EVT VT =
N->getValueType(0);
18533 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18540 SDValue
FMA =
N->getOperand(2);
18561 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18562 FMA->getFlags().hasApproximateFuncs();
18563 if (!AllowInaccuracy) {
18566 if (Subtarget->dot2UnconditionalFlush()) {
18578 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18589 SDValue FMAOp1 =
FMA.getOperand(0);
18590 SDValue FMAOp2 =
FMA.getOperand(1);
18591 SDValue FMAAcc =
FMA.getOperand(2);
18614 if (Vec1 == Vec2 || Vec3 == Vec4)
18620 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18621 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18664 EVT VT =
LHS.getValueType();
18665 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18697 if (CC ==
ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18701 if (CC ==
ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18705 if (CC ==
ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18709 if (CC ==
ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18712 const std::optional<bool> KnownEq =
18741 if (CC ==
ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18745 if (CC ==
ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18753 const std::optional<bool> KnownUge =
18778 if (CC ==
ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18792 if (CC ==
ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18795 const std::optional<bool> KnownUle =
18818 DAGCombinerInfo &DCI)
const {
18819 SelectionDAG &DAG = DCI.DAG;
18822 SDValue
LHS =
N->getOperand(0);
18823 SDValue
RHS =
N->getOperand(1);
18824 EVT VT =
LHS.getValueType();
18853 return LHS.getOperand(0);
18867 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18868 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18873 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18876 return LHS.getOperand(0);
18882 if (VT == MVT::i64) {
18885 const KnownBits LHSKnownLo32 = LHSKnown.
trunc(32);
18886 const KnownBits RHSKnownLo32 = RHSKnown.
trunc(32);
18913 const std::optional<bool> KnownEq =
18921 const std::optional<bool> KnownEq =
18932 const std::optional<bool> KnownUge =
18952 const std::optional<bool> KnownUle =
18976 const KnownBits LHSKnownHi32 = LHSKnown.
extractBits(32, 32);
18977 const KnownBits RHSKnownHi32 = RHSKnown.
extractBits(32, 32);
18978 const std::optional<bool> KnownEq =
18981 if (KnownEq ==
true) {
18987 return DAG.
getSetCC(SL,
N->getValueType(0), LHSLo, RHSLo, NewCC);
19008 SDValue Op0 =
LHS.getOperand(0);
19009 SDValue Op1 =
LHS.getOperand(1);
19019 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19021 SDValue CarryInHi = NodeLo.
getValue(1);
19024 {Op0Hi, Op1Hi, CarryInHi});
19026 SDValue ResultLo = NodeLo.
getValue(0);
19027 SDValue ResultHi = NodeHi.
getValue(0);
19029 SDValue JoinedResult =
19033 SDValue Overflow = NodeHi.
getValue(1);
19034 DCI.CombineTo(
LHS.getNode(), Result);
19038 if (VT != MVT::f32 && VT != MVT::f64 &&
19039 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19054 const unsigned IsInfMask =
19056 const unsigned IsFiniteMask =
19061 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
19066 if (VT == MVT::f64) {
19077SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
19078 DAGCombinerInfo &DCI)
const {
19079 SelectionDAG &DAG = DCI.DAG;
19081 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19083 SDValue Src =
N->getOperand(0);
19084 SDValue Shift =
N->getOperand(0);
19100 unsigned ShiftOffset = 8 *
Offset;
19102 ShiftOffset -=
C->getZExtValue();
19104 ShiftOffset +=
C->getZExtValue();
19106 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19107 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19108 MVT::f32, Shifted);
19119 DCI.AddToWorklist(
N);
19120 return SDValue(
N, 0);
19124 if (SDValue DemandedSrc =
19126 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
19132 DAGCombinerInfo &DCI)
const {
19141 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19142 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
19147 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
19149 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
19158 if (V.getOpcode() ==
ISD::FFREXP && V.getResNo() == 1) {
19169SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
19170 DAGCombinerInfo &DCI)
const {
19172 if (Subtarget->hasFractBug())
19175 SDValue
Cond =
N->getOperand(0);
19176 SDValue
TrueVal =
N->getOperand(1);
19184 bool CondSelectsZero;
19188 SDValue FrexpInput;
19192 CondSelectsZero =
true;
19193 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19196 CondSelectsZero =
false;
19208 bool IsNonFiniteTest =
false;
19214 SDValue CondLHS =
Cond.getOperand(0);
19215 SDValue CondRHS =
Cond.getOperand(1);
19220 bool LHSMatchesFrexp =
19221 (CondLHS == FrexpInput) ||
19222 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19224 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19232 SelectionDAG &DAG = DCI.DAG;
19233 if (LHSMatchesFrexp &&
19235 IsNonFiniteTest = CondSelectsZero;
19237 IsNonFiniteTest = CondSelectsZero;
19244 IsNonFiniteTest = CondSelectsZero;
19251 IsNonFiniteTest = !CondSelectsZero;
19257 SelectionDAG &DAG = DCI.DAG;
19258 if (LHSMatchesFrexp &&
19260 IsNonFiniteTest = !CondSelectsZero;
19262 IsNonFiniteTest = !CondSelectsZero;
19266 if (!IsNonFiniteTest)
19274 DAGCombinerInfo &DCI)
const {
19283 SDValue
Cond =
N->getOperand(0);
19284 SDValue
TrueVal =
N->getOperand(1);
19291 SDValue
LHS =
Cond.getOperand(0);
19292 SDValue
RHS =
Cond.getOperand(1);
19295 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19296 bool isInteger =
LHS.getValueType().isInteger();
19299 if (!isFloatingPoint && !isInteger)
19304 bool isNonEquality =
19306 if (!isEquality && !isNonEquality)
19309 SDValue ArgVal, ConstVal;
19323 if (isFloatingPoint) {
19325 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19328 const std::optional<int64_t> Val =
19337 if (!(isEquality && TrueVal == ConstVal) &&
19338 !(isNonEquality && FalseVal == ConstVal))
19342 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19343 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19346 SDValue SelectLHS = (isEquality &&
TrueVal == ConstVal) ? ArgVal :
TrueVal;
19347 SDValue SelectRHS =
19350 SelectLHS, SelectRHS);
19355 switch (
N->getOpcode()) {
19377 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19387 switch (
N->getOpcode()) {
19389 return performAddCombine(
N, DCI);
19391 return performPtrAddCombine(
N, DCI);
19393 return performSubCombine(
N, DCI);
19395 return performFAddCombine(
N, DCI);
19397 return performFSubCombine(
N, DCI);
19399 return performFDivCombine(
N, DCI);
19401 return performFMulCombine(
N, DCI);
19403 return performSetCCCombine(
N, DCI);
19405 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19407 if (
auto Res = performSelectCombine(
N, DCI))
19422 case AMDGPUISD::FMIN_LEGACY:
19423 case AMDGPUISD::FMAX_LEGACY:
19424 return performMinMaxCombine(
N, DCI);
19426 return performFMACombine(
N, DCI);
19428 return performAndCombine(
N, DCI);
19430 return performOrCombine(
N, DCI);
19433 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19434 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19440 return performXorCombine(
N, DCI);
19443 return performZeroOrAnyExtendCombine(
N, DCI);
19445 return performExtendTruncShiftCombine(
N, DCI);
19447 return performSignExtendInRegCombine(
N, DCI);
19448 case AMDGPUISD::FP_CLASS:
19449 return performClassCombine(
N, DCI);
19451 return performFCanonicalizeCombine(
N, DCI);
19452 case AMDGPUISD::RCP:
19453 return performRcpCombine(
N, DCI);
19455 case AMDGPUISD::FRACT:
19456 case AMDGPUISD::RSQ:
19457 case AMDGPUISD::RCP_LEGACY:
19458 case AMDGPUISD::RCP_IFLAG:
19459 case AMDGPUISD::RSQ_CLAMP: {
19468 return performUCharToFloatCombine(
N, DCI);
19470 return performFCopySignCombine(
N, DCI);
19471 case AMDGPUISD::CVT_F32_UBYTE0:
19472 case AMDGPUISD::CVT_F32_UBYTE1:
19473 case AMDGPUISD::CVT_F32_UBYTE2:
19474 case AMDGPUISD::CVT_F32_UBYTE3:
19475 return performCvtF32UByteNCombine(
N, DCI);
19476 case AMDGPUISD::FMED3:
19477 return performFMed3Combine(
N, DCI);
19478 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19479 return performCvtPkRTZCombine(
N, DCI);
19480 case AMDGPUISD::CLAMP:
19481 return performClampCombine(
N, DCI);
19484 EVT VT =
N->getValueType(0);
19489 if (VT == MVT::v2bf16 && Subtarget->hasBF16InlineConstFromUpperFP32()) {
19492 C->getValueAPF().bitcastToAPInt().getSExtValue(),
19493 Subtarget->hasInv2PiInlineImm()))
19495 {
N->getOperand(0),
N->getOperand(0)});
19499 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19502 EVT EltVT = Src.getValueType();
19503 if (EltVT != MVT::i16)
19513 return performExtractVectorEltCombine(
N, DCI);
19515 return performInsertVectorEltCombine(
N, DCI);
19517 return performFPRoundCombine(
N, DCI);
19526 return performMemSDNodeCombine(MemNode, DCI);
19557 unsigned Opcode =
Node->getMachineOpcode();
19560 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19561 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19564 SDNode *
Users[5] = {
nullptr};
19566 unsigned DmaskIdx =
19567 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19568 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19569 unsigned NewDmask = 0;
19570 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19571 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19572 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19573 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19574 unsigned TFCLane = 0;
19575 bool HasChain =
Node->getNumValues() > 1;
19577 if (OldDmask == 0) {
19585 TFCLane = OldBitsSet;
19589 for (SDUse &Use :
Node->uses()) {
19592 if (
Use.getResNo() != 0)
19595 SDNode *
User =
Use.getUser();
19598 if (!
User->isMachineOpcode() ||
19599 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19611 if (UsesTFC && Lane == TFCLane) {
19616 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19618 Dmask &= ~(1 << Comp);
19626 NewDmask |= 1 << Comp;
19631 bool NoChannels = !NewDmask;
19638 if (OldBitsSet == 1)
19644 if (NewDmask == OldDmask)
19653 unsigned NewChannels = BitsSet + UsesTFC;
19657 assert(NewOpcode != -1 &&
19658 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19659 "failed to find equivalent MIMG op");
19667 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19669 MVT ResultVT = NewChannels == 1
19672 : NewChannels == 5 ? 8
19674 SDVTList NewVTList =
19677 MachineSDNode *NewNode =
19686 if (NewChannels == 1) {
19696 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19701 if (i || !NoChannels)
19706 if (NewUser != User) {
19716 Idx = AMDGPU::sub1;
19719 Idx = AMDGPU::sub2;
19722 Idx = AMDGPU::sub3;
19725 Idx = AMDGPU::sub4;
19736 Op =
Op.getOperand(0);
19761 Node->getOperand(0), SL, VReg, SrcVal,
19767 return ToResultReg.
getNode();
19772 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19774 Ops.push_back(
Node->getOperand(i));
19780 Node->getOperand(i).getValueType(),
19781 Node->getOperand(i)),
19793 unsigned Opcode =
Node->getMachineOpcode();
19795 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19796 !
TII->isGather4(Opcode) &&
19798 return adjustWritemask(
Node, DAG);
19801 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19807 case AMDGPU::V_DIV_SCALE_F32_e64:
19808 case AMDGPU::V_DIV_SCALE_F64_e64: {
19816 if ((Src0.isMachineOpcode() &&
19817 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19818 (Src0 == Src1 || Src0 == Src2))
19821 MVT VT = Src0.getValueType().getSimpleVT();
19833 if (Src0.isMachineOpcode() &&
19834 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19835 if (Src1.isMachineOpcode() &&
19836 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19838 else if (Src2.isMachineOpcode() &&
19839 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19842 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19874 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19875 unsigned InitIdx = 0;
19877 if (
TII->isImage(
MI)) {
19885 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19886 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19887 unsigned D16Val = D16 ? D16->getImm() : 0;
19889 if (!TFEVal && !LWEVal)
19900 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19902 unsigned dmask = MO_Dmask->
getImm();
19907 bool Packed = !Subtarget->hasUnpackedD16VMem();
19909 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19916 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19917 if (DstSize < InitIdx)
19921 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
19930 unsigned NewDst = 0;
19935 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19936 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19939 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19960 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
19972 if (
TII->isVOP3(
MI.getOpcode())) {
19974 TII->legalizeOperandsVOP3(MRI,
MI);
19977 if (
MI.getOpcode() == AMDGPU::V_PK_FMA_F32 &&
19978 !
TII->isLegalPkFMAF32OpSel(
MI)) {
19979 TII->decomposePkFMAF32(
MI, MRI);
19983 if (
TII->isMAI(
MI)) {
19988 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19989 AMDGPU::OpName::scale_src0);
19990 if (Src0Idx != -1) {
19991 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19992 AMDGPU::OpName::scale_src1);
19993 if (
TII->usesConstantBus(MRI,
MI, Src0Idx) &&
19994 TII->usesConstantBus(MRI,
MI, Src1Idx))
19995 TII->legalizeOpWithMove(
MI, Src1Idx);
20002 if (
TII->isImage(
MI))
20003 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
20045 uint64_t RsrcDword2And3)
const {
20075std::pair<unsigned, const TargetRegisterClass *>
20082 if (Constraint.
size() == 1) {
20086 if (VT == MVT::Other)
20089 switch (Constraint[0]) {
20096 RC = &AMDGPU::SReg_32RegClass;
20099 RC = &AMDGPU::SGPR_64RegClass;
20104 return std::pair(0U,
nullptr);
20111 return std::pair(0U,
nullptr);
20113 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20114 : &AMDGPU::VGPR_32_Lo256RegClass;
20117 RC = Subtarget->has1024AddressableVGPRs()
20118 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
20121 return std::pair(0U,
nullptr);
20126 if (!Subtarget->hasMAIInsts())
20130 return std::pair(0U,
nullptr);
20132 RC = &AMDGPU::AGPR_32RegClass;
20137 return std::pair(0U,
nullptr);
20142 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
20146 RC = &AMDGPU::AV_32RegClass;
20149 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
20151 return std::pair(0U,
nullptr);
20160 return std::pair(0U, RC);
20163 if (Kind !=
'\0') {
20165 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20166 }
else if (Kind ==
's') {
20167 RC = &AMDGPU::SGPR_32RegClass;
20168 }
else if (Kind ==
'a') {
20169 RC = &AMDGPU::AGPR_32RegClass;
20175 return std::pair(0U,
nullptr);
20181 return std::pair(0U,
nullptr);
20185 RC =
TRI->getVGPRClassForBitWidth(Width);
20187 RC =
TRI->getSGPRClassForBitWidth(Width);
20189 RC =
TRI->getAGPRClassForBitWidth(Width);
20191 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20196 return std::pair(0U,
nullptr);
20198 return std::pair(Reg, RC);
20207 return std::pair(0U,
nullptr);
20208 if (RC && Idx < RC->getNumRegs())
20210 return std::pair(0U,
nullptr);
20216 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20217 if (!Subtarget->useRealTrue16Insts() &&
20218 TRI->getRegSizeInBits(*Ret.second) == 16)
20219 return std::pair(0U,
nullptr);
20226 if (Constraint.
size() == 1) {
20227 switch (Constraint[0]) {
20237 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20245 if (Constraint.
size() == 1) {
20246 switch (Constraint[0]) {
20254 }
else if (Constraint.
size() == 2) {
20255 if (Constraint ==
"VA")
20273 std::vector<SDValue> &
Ops,
20288 unsigned Size =
Op.getScalarValueSizeInBits();
20292 if (
Size == 16 && !Subtarget->has16BitInsts())
20296 Val =
C->getSExtValue();
20300 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20304 if (
Size != 16 ||
Op.getNumOperands() != 2)
20306 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20309 Val =
C->getSExtValue();
20313 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20322 uint64_t Val)
const {
20323 if (Constraint.
size() == 1) {
20324 switch (Constraint[0]) {
20339 }
else if (Constraint.
size() == 2) {
20340 if (Constraint ==
"DA") {
20341 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20342 int64_t LoBits =
static_cast<int32_t
>(Val);
20346 if (Constraint ==
"DB") {
20354 unsigned MaxSize)
const {
20355 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20356 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20358 MVT VT =
Op.getSimpleValueType();
20383 switch (UnalignedClassID) {
20384 case AMDGPU::VReg_64RegClassID:
20385 return AMDGPU::VReg_64_Align2RegClassID;
20386 case AMDGPU::VReg_96RegClassID:
20387 return AMDGPU::VReg_96_Align2RegClassID;
20388 case AMDGPU::VReg_128RegClassID:
20389 return AMDGPU::VReg_128_Align2RegClassID;
20390 case AMDGPU::VReg_160RegClassID:
20391 return AMDGPU::VReg_160_Align2RegClassID;
20392 case AMDGPU::VReg_192RegClassID:
20393 return AMDGPU::VReg_192_Align2RegClassID;
20394 case AMDGPU::VReg_224RegClassID:
20395 return AMDGPU::VReg_224_Align2RegClassID;
20396 case AMDGPU::VReg_256RegClassID:
20397 return AMDGPU::VReg_256_Align2RegClassID;
20398 case AMDGPU::VReg_288RegClassID:
20399 return AMDGPU::VReg_288_Align2RegClassID;
20400 case AMDGPU::VReg_320RegClassID:
20401 return AMDGPU::VReg_320_Align2RegClassID;
20402 case AMDGPU::VReg_352RegClassID:
20403 return AMDGPU::VReg_352_Align2RegClassID;
20404 case AMDGPU::VReg_384RegClassID:
20405 return AMDGPU::VReg_384_Align2RegClassID;
20406 case AMDGPU::VReg_512RegClassID:
20407 return AMDGPU::VReg_512_Align2RegClassID;
20408 case AMDGPU::VReg_1024RegClassID:
20409 return AMDGPU::VReg_1024_Align2RegClassID;
20410 case AMDGPU::AReg_64RegClassID:
20411 return AMDGPU::AReg_64_Align2RegClassID;
20412 case AMDGPU::AReg_96RegClassID:
20413 return AMDGPU::AReg_96_Align2RegClassID;
20414 case AMDGPU::AReg_128RegClassID:
20415 return AMDGPU::AReg_128_Align2RegClassID;
20416 case AMDGPU::AReg_160RegClassID:
20417 return AMDGPU::AReg_160_Align2RegClassID;
20418 case AMDGPU::AReg_192RegClassID:
20419 return AMDGPU::AReg_192_Align2RegClassID;
20420 case AMDGPU::AReg_256RegClassID:
20421 return AMDGPU::AReg_256_Align2RegClassID;
20422 case AMDGPU::AReg_512RegClassID:
20423 return AMDGPU::AReg_512_Align2RegClassID;
20424 case AMDGPU::AReg_1024RegClassID:
20425 return AMDGPU::AReg_1024_Align2RegClassID;
20441 if (Info->isEntryFunction()) {
20448 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20450 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20451 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20452 &AMDGPU::SGPR_64RegClass);
20453 Info->setSGPRForEXECCopy(SReg);
20455 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20456 Info->getStackPtrOffsetReg()));
20457 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20458 MRI.
replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20462 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20463 MRI.
replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20465 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20468 Info->limitOccupancy(MF);
20470 if (ST.isWave32() && !MF.
empty()) {
20471 for (
auto &
MBB : MF) {
20472 for (
auto &
MI :
MBB) {
20473 TII->fixImplicitOperands(
MI);
20483 if (ST.needsAlignedVGPRs()) {
20490 if (NewClassID != -1)
20500 const APInt &DemandedElts,
20502 unsigned Depth)
const {
20504 unsigned Opc =
Op.getOpcode();
20507 unsigned IID =
Op.getConstantOperandVal(0);
20509 case Intrinsic::amdgcn_mbcnt_lo:
20510 case Intrinsic::amdgcn_mbcnt_hi: {
20515 Known.Zero.setBitsFrom(
20516 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20542 unsigned MaxValue =
20549 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20553 unsigned Src1Cst = 0;
20554 if (Src1.isImm()) {
20555 Src1Cst = Src1.getImm();
20556 }
else if (Src1.isReg()) {
20560 Src1Cst = Cst->Value.getZExtValue();
20571 if (Width >= BFEWidth)
20588 unsigned Depth)
const {
20591 switch (
MI->getOpcode()) {
20592 case AMDGPU::S_BFE_I32:
20595 case AMDGPU::S_BFE_U32:
20598 case AMDGPU::S_BFE_I64:
20601 case AMDGPU::S_BFE_U64:
20604 case AMDGPU::G_INTRINSIC:
20605 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20608 case Intrinsic::amdgcn_workitem_id_x:
20611 case Intrinsic::amdgcn_workitem_id_y:
20614 case Intrinsic::amdgcn_workitem_id_z:
20617 case Intrinsic::amdgcn_mbcnt_lo:
20618 case Intrinsic::amdgcn_mbcnt_hi: {
20621 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20630 case Intrinsic::amdgcn_groupstaticsize: {
20634 Known.Zero.setHighBits(
20638 case Intrinsic::amdgcn_readfirstlane:
20639 case Intrinsic::amdgcn_readlane: {
20648 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20649 Known.Zero.setHighBits(24);
20651 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20652 Known.Zero.setHighBits(16);
20654 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20657 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20659 case AMDGPU::G_AMDGPU_SMED3:
20660 case AMDGPU::G_AMDGPU_UMED3: {
20661 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20688 unsigned Depth)
const {
20697 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20718 BlockToAlign =
ML->getHeader();
20722 if (needsFetchWindowAlignment(*BlockToAlign))
20743 if (Header->getAlignment() != PrefAlign)
20744 return Header->getAlignment();
20746 unsigned LoopSize = 0;
20751 LoopSize +=
MBB->getAlignment().value() / 2;
20754 LoopSize +=
TII->getInstSizeInBytes(
MI);
20755 if (LoopSize > 192)
20760 if (LoopSize <= 64)
20763 if (LoopSize <= 128)
20764 return CacheLineAlign;
20770 auto I = Exit->getFirstNonDebugInstr();
20771 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20772 return CacheLineAlign;
20781 if (PreTerm == Pre->
begin() ||
20782 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20786 auto ExitHead = Exit->getFirstNonDebugInstr();
20787 if (ExitHead == Exit->end() ||
20788 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20793 return CacheLineAlign;
20801 if (needsFetchWindowAlignment(*
MBB))
20806bool SITargetLowering::needsFetchWindowAlignment(
20808 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20812 if (
MI.isMetaInstruction())
20815 return TII->getInstSizeInBytes(
MI) > 4;
20825 N =
N->getOperand(0).getNode();
20835 switch (
N->getOpcode()) {
20843 if (Reg.isPhysical() || MRI.
isLiveIn(Reg))
20844 return !
TRI->isSGPRReg(MRI, Reg);
20850 return !
TRI->isSGPRReg(MRI, Reg);
20854 unsigned AS = L->getAddressSpace();
20864 case AMDGPUISD::ATOMIC_CMP_SWAP:
20865 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20866 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20867 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20868 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20869 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20870 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20871 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20872 case AMDGPUISD::BUFFER_ATOMIC_AND:
20873 case AMDGPUISD::BUFFER_ATOMIC_OR:
20874 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20875 case AMDGPUISD::BUFFER_ATOMIC_INC:
20876 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20877 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20878 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20879 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20880 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20886 return A->readMem() &&
A->writeMem();
20907 switch (Ty.getScalarSizeInBits()) {
20919 const APInt &DemandedElts,
20922 unsigned Depth)
const {
20923 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
20927 if (Info->getMode().DX10Clamp)
20940enum class AtomicFlushDenormalReason {
20943 IgnoreDenormalMode,
20944 FunctionFlushesDenormals
20949enum class GlobalFPAtomicLegality {
20951 AgentScopeFineGrainedRemoteMemory,
20952 EmulatedSystemScope,
20954 NoFineGrainedMemory
20961static AtomicFlushDenormalReason
20963 if (RMW->
hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
20964 return AtomicFlushDenormalReason::IgnoreDenormalMode;
20969 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
20970 : AtomicFlushDenormalReason::IEEE;
20975 GlobalFPAtomicLegality MemLegality,
20976 AtomicFlushDenormalReason DenormReason) {
20979 if (MemScope.empty())
20980 MemScope =
"system";
20983 R <<
"hardware instruction generated for atomic "
20985 <<
" at " <<
ore::NV(
"SyncScope", MemScope) <<
" scope since ";
20987 switch (MemLegality) {
20988 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
20989 R <<
"fine-grained remote memory atomics work below system scope";
20991 case GlobalFPAtomicLegality::EmulatedSystemScope:
20992 R <<
"system scope atomics are emulated in hardware";
20994 case GlobalFPAtomicLegality::NoRemoteMemory:
20995 R <<
"memory is not remote (!amdgpu.no.remote.memory)";
20997 case GlobalFPAtomicLegality::NoFineGrainedMemory:
20998 R <<
"memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
21000 case GlobalFPAtomicLegality::Illegal:
21004 switch (DenormReason) {
21005 case AtomicFlushDenormalReason::Native:
21007 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21008 R <<
", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21010 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21011 R <<
", and the floating-point environment flushes denormals";
21013 case AtomicFlushDenormalReason::IEEE:
21022 Type *EltTy = VT->getElementType();
21023 return VT->getNumElements() == 2 &&
21043 unsigned BW =
IT->getBitWidth();
21044 return BW == 32 || BW == 64;
21058 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
21059 return BW == 32 || BW == 64;
21062 if (Ty->isFloatTy() || Ty->isDoubleTy())
21066 return VT->getNumElements() == 2 &&
21067 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21075static GlobalFPAtomicLegality
21084 if (HasSystemScope) {
21085 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21087 return GlobalFPAtomicLegality::NoRemoteMemory;
21088 if (Subtarget.hasEmulatedSystemScopeAtomics())
21089 return GlobalFPAtomicLegality::EmulatedSystemScope;
21090 }
else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21091 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21093 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory")
21094 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21095 : GlobalFPAtomicLegality::Illegal;
21108 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
21116 return STI.hasGloballyAddressableScratch()
21134 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
21138 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21139 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21149 bool HasSystemScope =
21181 if (!Subtarget->hasSubClampInsts() ||
21183 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21185 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21190 if (!
IT ||
IT->getBitWidth() != 32)
21196 if (Subtarget->hasEmulatedSystemScopeAtomics())
21212 if (!HasSystemScope &&
21213 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21225 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
21234 ConstVal && ConstVal->isNullValue() &&
21273 if (Ty->isFloatTy()) {
21278 if (Ty->isDoubleTy()) {
21299 if (Ty->isFloatTy() &&
21300 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21302 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21308 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21315 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21319 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21323 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21328 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21333 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21337 if (Ty->isFloatTy()) {
21340 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21343 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21348 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21356 if (Subtarget->hasFlatAtomicFaddF32Inst())
21365 if (Subtarget->hasLDSFPAtomicAddF32()) {
21366 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21368 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21388 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21398 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21400 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21404 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21406 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21460 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21461 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21462 : &AMDGPU::SReg_32RegClass;
21463 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21464 return TRI->getEquivalentSGPRClass(RC);
21465 if (
TRI->isSGPRClass(RC) && isDivergent) {
21466 if (Subtarget->hasGFX90AInsts())
21467 return TRI->getEquivalentAVClass(RC);
21468 return TRI->getEquivalentVGPRClass(RC);
21481 unsigned WaveSize) {
21486 if (!
IT ||
IT->getBitWidth() != WaveSize)
21491 if (!Visited.
insert(V).second)
21493 bool Result =
false;
21494 for (
const auto *U : V->users()) {
21496 if (V == U->getOperand(1)) {
21501 case Intrinsic::amdgcn_if_break:
21502 case Intrinsic::amdgcn_if:
21503 case Intrinsic::amdgcn_else:
21508 if (V == U->getOperand(0)) {
21513 case Intrinsic::amdgcn_end_cf:
21514 case Intrinsic::amdgcn_loop:
21520 Result =
hasCFUser(U, Visited, WaveSize);
21529 const Value *V)
const {
21531 if (CI->isInlineAsm()) {
21540 for (
auto &TC : TargetConstraints) {
21554 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21589 if (
I.getMetadata(
"amdgpu.noclobber"))
21591 if (
I.getMetadata(
"amdgpu.last.use"))
21593 if (
MDNode *
N =
I.getMetadata(
"amdgpu.cfs")) {
21598 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21663 Alignment = RMW->getAlign();
21676 bool FullFlatEmulation =
21678 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21679 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21680 RMW->getType()->isDoubleTy()));
21683 bool ReturnValueIsUsed = !AI->
use_empty();
21692 if (FullFlatEmulation) {
21703 std::prev(BB->
end())->eraseFromParent();
21704 Builder.SetInsertPoint(BB);
21706 Value *LoadedShared =
nullptr;
21707 if (FullFlatEmulation) {
21708 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21709 {Addr},
nullptr,
"is.shared");
21710 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21711 Builder.SetInsertPoint(SharedBB);
21712 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21718 LoadedShared = Clone;
21720 Builder.CreateBr(PhiBB);
21721 Builder.SetInsertPoint(CheckPrivateBB);
21724 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21725 {Addr},
nullptr,
"is.private");
21726 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21728 Builder.SetInsertPoint(PrivateBB);
21730 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21733 Value *LoadedPrivate;
21735 LoadedPrivate = Builder.CreateAlignedLoad(
21736 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21740 LoadedPrivate, RMW->getValOperand());
21742 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21743 RMW->isVolatile());
21751 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21754 Builder.CreateBr(PhiBB);
21756 Builder.SetInsertPoint(GlobalBB);
21760 if (FullFlatEmulation) {
21761 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21770 if (!FullFlatEmulation) {
21775 MDNode *RangeNotPrivate =
21778 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21782 Builder.CreateBr(PhiBB);
21784 Builder.SetInsertPoint(PhiBB);
21786 if (ReturnValueIsUsed) {
21789 if (FullFlatEmulation)
21790 Loaded->addIncoming(LoadedShared, SharedBB);
21791 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21792 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21793 Loaded->takeName(AI);
21796 Builder.CreateBr(ExitBB);
21800 unsigned PtrOpIdx) {
21801 Value *PtrOp =
I->getOperand(PtrOpIdx);
21808 I->setOperand(PtrOpIdx, ASCast);
21820 ConstVal && ConstVal->isNullValue() &&
21851 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21859 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
static bool isMul(MachineInstr *MI)
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
iv Induction Variable Users
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
#define FP_DENORM_FLUSH_NONE
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static AtomicFlushDenormalReason getAtomicFlushDenormalReason(const AtomicRMWInst *RMW)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, Intrinsic::ID IntrinsicID)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static bool isFrexpExp(SDValue V, SDValue &FrexpInput)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static GlobalFPAtomicLegality getGlobalMemoryFPAtomicLegality(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW, GlobalFPAtomicLegality MemLegality, AtomicFlushDenormalReason DenormReason)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void initializeM0ToZeroForClusterLoad(SDValue Op, SelectionDAG &DAG, SDLoc DL)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static constexpr int Concat[]
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > get32BitAbsoluteAddress(const GlobalValue &GV, unsigned AS)
void setUsesDynamicLDS(bool DynLDS)
bool isBottomOfStack() const
uint32_t getLDSSize() const
bool isEntryFunction() const
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
static bool EnableObjectLinking
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned AndSaveExecOpc
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
LLVM_READONLY int getExactLog2Abs() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
bool isMask(unsigned numBits) const
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
const Function * getParent() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getCompareOperand()
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
iterator_range< arg_iterator > args()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Argument * getArg(unsigned i) const
const SIInstrInfo * getInstrInfo() const override
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool hasKernargSegmentPtr() const
bool hasDispatchID() const
bool hasPrivateSegmentBuffer() const
unsigned getNumFreeUserSGPRs()
bool hasImplicitBufferPtr() const
bool hasPrivateSegmentSize() const
bool hasDispatchPtr() const
bool hasFlatScratchInit() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
Evaluate a known-bits query with an explicit worklist instead of recursive descent.
int64_t getOffset() const
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
const MDOperand & getOperand(unsigned I) const
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
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.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
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
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
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
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool isWholeWaveFunction() const
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
unsigned getBytesInStackArgArea() const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
Align getPrefLoopAlignment(MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const override
Return the preferred loop alignment.
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
bool isUniformLoad(const LoadSDNode *Load) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
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 getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
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),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
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.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr, const MachineBasicBlock *BlockToAlign=nullptr) const
Return the preferred loop alignment.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
OSType getOS() const
Get the parsed operating system type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM_ABI void set(Value *Val)
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ TowardZeroF32_TowardNegativeF64
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
unsigned getBarrierMemberCountBitMask(const IsaVersion &Version)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
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.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ 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...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ 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...
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ 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,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
CondCode getUnsignedSetCC(CondCode Code)
Convert a signed integer condition code to unsigned.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
static const MachineMemOperand::Flags MOCFSB1
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given 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...
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
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...
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
ArgDescriptor WorkItemIDZ
ArgDescriptor WorkItemIDY
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
ArgDescriptor WorkItemIDX
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
unsigned AtomicNoRetBaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
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.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const
Return a subset of the known bits from [bitPosition,bitPosition+numBits).
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SDValue ConvergenceControlToken
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalize() const