45#include "llvm/IR/IntrinsicsAMDGPU.h"
46#include "llvm/IR/IntrinsicsR600.h"
59#define DEBUG_TYPE "si-lower"
65 cl::desc(
"Do not align and prefetch loops"),
69 "amdgpu-use-divergent-register-indexing",
cl::Hidden,
70 cl::desc(
"Use indirect register addressing for divergent indexes"),
88 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
89 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
91 return AMDGPU::SGPR0 +
Reg;
107 TRI->getDefaultVectorSuperClassForBitWidth(32);
113 TRI->getDefaultVectorSuperClassForBitWidth(64);
151 TRI->getDefaultVectorSuperClassForBitWidth(320));
155 TRI->getDefaultVectorSuperClassForBitWidth(352));
159 TRI->getDefaultVectorSuperClassForBitWidth(384));
163 TRI->getDefaultVectorSuperClassForBitWidth(512));
170 TRI->getDefaultVectorSuperClassForBitWidth(1024));
172 if (Subtarget->has16BitInsts()) {
173 if (Subtarget->useRealTrue16Insts()) {
203 TRI->getDefaultVectorSuperClassForBitWidth(1024));
219 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
220 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
221 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
222 MVT::i1, MVT::v32i32},
226 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
227 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
228 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
229 MVT::i1, MVT::v32i32},
247 if (Subtarget->hasBF16PackedInsts()) {
311 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
318 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
319 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
320 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
323 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
324 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
325 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
329 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
330 MVT::v3i16, MVT::v4i16, MVT::Other},
335 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
351 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
352 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
353 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
354 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
355 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
356 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
357 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
358 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
391 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
405 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
419 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
433 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
447 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
462 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
463 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
466 if (Subtarget->hasPkMovB32()) {
487 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
488 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
493 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
497 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
498 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
499 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
500 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
524 if (Subtarget->hasSMemRealTime() ||
529 if (Subtarget->has16BitInsts()) {
539 if (Subtarget->hasMadMacF32Insts())
557 if (Subtarget->hasIntClamp())
560 if (Subtarget->hasAddNoCarryInsts())
566 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
569 {MVT::f64, MVT::f32},
Legal);
573 {MVT::f64, MVT::f32},
Custom);
578 {MVT::f64, MVT::f32},
Legal);
581 if (Subtarget->haveRoundOpsF64())
611 if (Subtarget->has16BitInsts()) {
665 if (Subtarget->hasBF16TransInsts())
681 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
682 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
683 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
716 if (Subtarget->hasVCvtPkIU16F32())
719 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
726 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
846 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
847 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
848 MVT::v32f16, MVT::v32bf16},
850 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
857 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
Custom);
868 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
872 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
877 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
878 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
886 if (Subtarget->hasVOP3PInsts()) {
897 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
900 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
901 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
902 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
905 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
913 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
919 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
929 {MVT::v2f16, MVT::v4f16},
Custom);
935 if (Subtarget->hasBF16PackedInsts()) {
941 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
949 if (Subtarget->hasAnyPackedFP32Ops()) {
953 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
956 if (Subtarget->hasAnyPackedFP64Ops()) {
962 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
964 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
971 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
980 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
985 if (Subtarget->hasAnyPackedU64Ops()) {
989 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
996 if (Subtarget->has16BitInsts()) {
1011 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1012 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1013 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1014 MVT::v32f16, MVT::v32bf16},
1019 if (Subtarget->useVMulU64Inst())
1021 else if (Subtarget->hasScalarSMulU64())
1024 if (Subtarget->hasMad64_32())
1027 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1030 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1032 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
1035 if (Subtarget->hasMinimum3Maximum3F32())
1038 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1042 if (!Subtarget->hasMinimum3Maximum3F16())
1048 if (Subtarget->hasVOP3PInsts()) {
1051 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1055 if (Subtarget->useMinMaxI64Insts())
1060 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1061 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1066 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1067 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1068 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1069 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1073 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1074 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1075 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1076 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1091 if (Subtarget->hasBF16ConversionInsts()) {
1093 {MVT::bf16, MVT::v2bf16},
Custom);
1097 if (Subtarget->hasBF16TransInsts()) {
1101 const bool HasE5M3ConversionInsts =
1102 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1103 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1114 if (Subtarget->hasFP8F16ConversionInsts()) {
1119 if (Subtarget->hasCvtPkF16F32Inst()) {
1121 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1173 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1214 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1227 EVT DestVT,
EVT SrcVT)
const {
1229 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1230 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1232 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1239 LLT DestTy,
LLT SrcTy)
const {
1240 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1241 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1243 SrcTy.getScalarSizeInBits() == 16 &&
1264 return Subtarget->has16BitInsts()
1270 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1274 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1296 return (NumElts + 1) / 2;
1302 return NumElts * ((
Size + 31) / 32);
1311 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1320 MVT SimpleIntermediateVT =
1322 IntermediateVT = SimpleIntermediateVT;
1323 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1324 NumIntermediates = (NumElts + 1) / 2;
1325 return (NumElts + 1) / 2;
1330 IntermediateVT = RegisterVT;
1331 NumIntermediates = NumElts;
1332 return NumIntermediates;
1337 RegisterVT = MVT::i16;
1338 IntermediateVT = ScalarVT;
1339 NumIntermediates = NumElts;
1340 return NumIntermediates;
1344 RegisterVT = MVT::i32;
1345 IntermediateVT = ScalarVT;
1346 NumIntermediates = NumElts;
1347 return NumIntermediates;
1351 RegisterVT = MVT::i32;
1352 IntermediateVT = RegisterVT;
1353 NumIntermediates = NumElts * ((
Size + 31) / 32);
1354 return NumIntermediates;
1359 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1364 unsigned MaxNumLanes) {
1365 assert(MaxNumLanes != 0);
1369 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1380 unsigned MaxNumLanes) {
1386 assert(ST->getNumContainedTypes() == 2 &&
1387 ST->getContainedType(1)->isIntegerTy(32));
1401 return MVT::amdgpuBufferFatPointer;
1403 DL.getPointerSizeInBits(AS) == 192)
1404 return MVT::amdgpuBufferStridedPointer;
1413 DL.getPointerSizeInBits(AS) == 160) ||
1415 DL.getPointerSizeInBits(AS) == 192))
1422 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1423 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1424 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1426 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1427 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1428 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1429 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1430 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1431 case Intrinsic::amdgcn_flat_load_monitor_b32:
1432 case Intrinsic::amdgcn_global_load_monitor_b32:
1434 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1435 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1436 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1437 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1438 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1439 case Intrinsic::amdgcn_flat_load_monitor_b64:
1440 case Intrinsic::amdgcn_global_load_monitor_b64:
1442 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1443 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1444 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1445 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1446 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1447 case Intrinsic::amdgcn_flat_load_monitor_b128:
1448 case Intrinsic::amdgcn_global_load_monitor_b128:
1484 unsigned IntrID)
const {
1486 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1500 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1514 if (RsrcIntr->IsImage) {
1529 Info.ptrVal = RsrcArg;
1533 if (RsrcIntr->IsImage) {
1534 unsigned MaxNumLanes = 4;
1549 std::numeric_limits<unsigned>::max());
1559 if (RsrcIntr->IsImage) {
1579 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1581 Info.memVT = MVT::i32;
1588 case Intrinsic::amdgcn_raw_buffer_load_lds:
1589 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1590 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1591 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1592 case Intrinsic::amdgcn_struct_buffer_load_lds:
1593 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1594 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1595 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1609 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1618 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1619 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1620 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1621 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1624 std::numeric_limits<unsigned>::max());
1637 case Intrinsic::amdgcn_ds_ordered_add:
1638 case Intrinsic::amdgcn_ds_ordered_swap: {
1652 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1653 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1656 Info.ptrVal =
nullptr;
1662 case Intrinsic::amdgcn_ds_append:
1663 case Intrinsic::amdgcn_ds_consume: {
1677 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1678 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1679 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1684 Info.memVT = MVT::i64;
1692 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1693 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1694 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1697 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1700 ->getElementType(0));
1709 case Intrinsic::amdgcn_global_atomic_fmin_num:
1710 case Intrinsic::amdgcn_global_atomic_fmax_num:
1711 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1712 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1713 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1724 case Intrinsic::amdgcn_cluster_load_b32:
1725 case Intrinsic::amdgcn_cluster_load_b64:
1726 case Intrinsic::amdgcn_cluster_load_b128:
1727 case Intrinsic::amdgcn_ds_load_tr6_b96:
1728 case Intrinsic::amdgcn_ds_load_tr4_b64:
1729 case Intrinsic::amdgcn_ds_load_tr8_b64:
1730 case Intrinsic::amdgcn_ds_load_tr16_b128:
1731 case Intrinsic::amdgcn_global_load_tr6_b96:
1732 case Intrinsic::amdgcn_global_load_tr4_b64:
1733 case Intrinsic::amdgcn_global_load_tr_b64:
1734 case Intrinsic::amdgcn_global_load_tr_b128:
1735 case Intrinsic::amdgcn_ds_read_tr4_b64:
1736 case Intrinsic::amdgcn_ds_read_tr6_b96:
1737 case Intrinsic::amdgcn_ds_read_tr8_b64:
1738 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1747 case Intrinsic::amdgcn_flat_load_monitor_b32:
1748 case Intrinsic::amdgcn_flat_load_monitor_b64:
1749 case Intrinsic::amdgcn_flat_load_monitor_b128:
1750 case Intrinsic::amdgcn_global_load_monitor_b32:
1751 case Intrinsic::amdgcn_global_load_monitor_b64:
1752 case Intrinsic::amdgcn_global_load_monitor_b128: {
1763 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1764 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1765 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1776 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1777 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1778 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1789 case Intrinsic::amdgcn_ds_gws_init:
1790 case Intrinsic::amdgcn_ds_gws_barrier:
1791 case Intrinsic::amdgcn_ds_gws_sema_v:
1792 case Intrinsic::amdgcn_ds_gws_sema_br:
1793 case Intrinsic::amdgcn_ds_gws_sema_p:
1794 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1804 Info.memVT = MVT::i32;
1806 Info.align =
Align(4);
1808 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1815 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1816 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1817 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1818 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1819 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1820 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1821 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1822 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1837 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1838 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1839 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1840 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1855 case Intrinsic::amdgcn_av_load_b128:
1856 case Intrinsic::amdgcn_av_store_b128: {
1857 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1859 Info.memVT = MVT::v4i32;
1861 Info.align =
Align(16);
1869 unsigned ScopeIdx = CI.
arg_size() - 1;
1873 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1877 case Intrinsic::amdgcn_load_to_lds:
1878 case Intrinsic::amdgcn_load_async_to_lds:
1879 case Intrinsic::amdgcn_global_load_lds:
1880 case Intrinsic::amdgcn_global_load_async_lds: {
1899 Width * 8 * Subtarget->getWavefrontSize());
1905 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1906 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1907 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1908 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1918 Info.memVT = MVT::i32;
1920 Info.align =
Align(4);
1926 case Intrinsic::amdgcn_s_prefetch_data:
1927 case Intrinsic::amdgcn_s_prefetch_inst:
1928 case Intrinsic::amdgcn_flat_prefetch:
1929 case Intrinsic::amdgcn_global_prefetch: {
1944 Type *&AccessTy)
const {
1945 Value *Ptr =
nullptr;
1946 switch (
II->getIntrinsicID()) {
1947 case Intrinsic::amdgcn_cluster_load_b128:
1948 case Intrinsic::amdgcn_cluster_load_b64:
1949 case Intrinsic::amdgcn_cluster_load_b32:
1950 case Intrinsic::amdgcn_ds_append:
1951 case Intrinsic::amdgcn_ds_consume:
1952 case Intrinsic::amdgcn_ds_load_tr8_b64:
1953 case Intrinsic::amdgcn_ds_load_tr16_b128:
1954 case Intrinsic::amdgcn_ds_load_tr4_b64:
1955 case Intrinsic::amdgcn_ds_load_tr6_b96:
1956 case Intrinsic::amdgcn_ds_read_tr4_b64:
1957 case Intrinsic::amdgcn_ds_read_tr6_b96:
1958 case Intrinsic::amdgcn_ds_read_tr8_b64:
1959 case Intrinsic::amdgcn_ds_read_tr16_b64:
1960 case Intrinsic::amdgcn_ds_ordered_add:
1961 case Intrinsic::amdgcn_ds_ordered_swap:
1962 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1963 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1964 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1965 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1966 case Intrinsic::amdgcn_global_atomic_fmax_num:
1967 case Intrinsic::amdgcn_global_atomic_fmin_num:
1968 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1969 case Intrinsic::amdgcn_global_load_tr_b64:
1970 case Intrinsic::amdgcn_global_load_tr_b128:
1971 case Intrinsic::amdgcn_global_load_tr4_b64:
1972 case Intrinsic::amdgcn_global_load_tr6_b96:
1973 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1974 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1975 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1976 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1977 case Intrinsic::amdgcn_av_load_b128:
1978 case Intrinsic::amdgcn_av_store_b128:
1979 Ptr =
II->getArgOperand(0);
1981 case Intrinsic::amdgcn_load_to_lds:
1982 case Intrinsic::amdgcn_load_async_to_lds:
1983 case Intrinsic::amdgcn_global_load_lds:
1984 case Intrinsic::amdgcn_global_load_async_lds:
1985 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1986 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1987 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1988 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1989 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1990 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1991 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1992 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1993 Ptr =
II->getArgOperand(1);
1998 AccessTy =
II->getType();
2004 unsigned AddrSpace)
const {
2005 if (!Subtarget->hasFlatInstOffsets()) {
2012 FlatAddrSpace FlatVariant =
2015 : FlatAddrSpace::FLAT;
2017 return AM.
Scale == 0 &&
2018 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2019 AM.
BaseOffs, AddrSpace, FlatVariant));
2023 if (Subtarget->hasFlatGlobalInsts())
2026 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2039 return isLegalMUBUFAddressingMode(AM);
2042bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2053 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2065 if (AM.HasBaseReg) {
2097 return isLegalMUBUFAddressingMode(AM);
2099 if (!Subtarget->hasScalarSubwordLoads()) {
2104 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2152 return Subtarget->hasFlatScratchEnabled()
2154 : isLegalMUBUFAddressingMode(AM);
2201 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2210 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2213 Align RequiredAlignment(
2215 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2216 Alignment < RequiredAlignment)
2231 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2237 RequiredAlignment =
Align(4);
2239 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2255 *IsFast = (Alignment >= RequiredAlignment) ? 64
2256 : (Alignment <
Align(4)) ? 32
2263 if (!Subtarget->hasDS96AndDS128())
2269 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2278 *IsFast = (Alignment >= RequiredAlignment) ? 96
2279 : (Alignment <
Align(4)) ? 32
2286 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2292 RequiredAlignment =
Align(8);
2294 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2303 *IsFast = (Alignment >= RequiredAlignment) ? 128
2304 : (Alignment <
Align(4)) ? 32
2321 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2323 return Alignment >= RequiredAlignment ||
2324 Subtarget->hasUnalignedDSAccessEnabled();
2332 bool AlignedBy4 = Alignment >=
Align(4);
2333 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2335 *IsFast = AlignedBy4 ?
Size : 1;
2340 *IsFast = AlignedBy4;
2351 return Alignment >=
Align(4) ||
2352 Subtarget->hasUnalignedBufferAccessEnabled();
2365 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2380 return Size >= 32 && Alignment >=
Align(4);
2385 unsigned *IsFast)
const {
2387 Alignment, Flags, IsFast);
2398 if (
Op.size() >= 16 &&
2402 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2420 unsigned DestAS)
const {
2423 Subtarget->hasGloballyAddressableScratch()) {
2454 unsigned Index)
const {
2468 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2473 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2508 auto [InputPtrReg, RC, ArgTy] =
2524 const SDLoc &SL)
const {
2531 const SDLoc &SL)
const {
2534 std::optional<uint32_t> KnownSize =
2536 if (KnownSize.has_value())
2563 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2578SDValue SITargetLowering::lowerKernargMemParameter(
2583 MachinePointerInfo PtrInfo =
2592 int64_t OffsetDiff =
Offset - AlignDownOffset;
2598 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2609 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2614 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2628 const SDLoc &SL)
const {
2697 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2700 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2701 if (ConvertedVal == ArgValue)
2702 return ConvertedVal;
2707SDValue SITargetLowering::lowerWorkGroupId(
2712 if (!Subtarget->hasClusters())
2713 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2721 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2722 SDLoc SL(ClusterIdXYZ);
2723 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2726 SDValue ClusterWorkGroupIdXYZ =
2727 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2737 return ClusterIdXYZ;
2739 using namespace AMDGPU::Hwreg;
2743 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2754SDValue SITargetLowering::getPreloadedValue(
2757 const ArgDescriptor *
Reg =
nullptr;
2762 const ArgDescriptor WorkGroupIDX =
2770 const ArgDescriptor WorkGroupIDZ =
2772 const ArgDescriptor ClusterWorkGroupIDX =
2774 const ArgDescriptor ClusterWorkGroupIDY =
2776 const ArgDescriptor ClusterWorkGroupIDZ =
2778 const ArgDescriptor ClusterWorkGroupMaxIDX =
2780 const ArgDescriptor ClusterWorkGroupMaxIDY =
2782 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2784 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2787 auto LoadConstant = [&](
unsigned N) {
2791 if (Subtarget->hasArchitectedSGPRs() &&
2798 Reg = &WorkGroupIDX;
2799 RC = &AMDGPU::SReg_32RegClass;
2803 Reg = &WorkGroupIDY;
2804 RC = &AMDGPU::SReg_32RegClass;
2808 Reg = &WorkGroupIDZ;
2809 RC = &AMDGPU::SReg_32RegClass;
2813 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2814 return LoadConstant(0);
2815 Reg = &ClusterWorkGroupIDX;
2816 RC = &AMDGPU::SReg_32RegClass;
2820 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2821 return LoadConstant(0);
2822 Reg = &ClusterWorkGroupIDY;
2823 RC = &AMDGPU::SReg_32RegClass;
2827 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2828 return LoadConstant(0);
2829 Reg = &ClusterWorkGroupIDZ;
2830 RC = &AMDGPU::SReg_32RegClass;
2835 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2836 Reg = &ClusterWorkGroupMaxIDX;
2837 RC = &AMDGPU::SReg_32RegClass;
2842 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2843 Reg = &ClusterWorkGroupMaxIDY;
2844 RC = &AMDGPU::SReg_32RegClass;
2849 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2850 Reg = &ClusterWorkGroupMaxIDZ;
2851 RC = &AMDGPU::SReg_32RegClass;
2855 Reg = &ClusterWorkGroupMaxFlatID;
2856 RC = &AMDGPU::SReg_32RegClass;
2887 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2891 "vector type argument should have been split");
2896 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2904 "unexpected vector split in ps argument type");
2918 Info->markPSInputAllocated(PSInputNum);
2920 Info->markPSInputEnabled(PSInputNum);
2936 if (Info.hasWorkItemIDX()) {
2942 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2946 if (Info.hasWorkItemIDY()) {
2947 assert(Info.hasWorkItemIDX());
2948 if (Subtarget->hasPackedTID()) {
2949 Info.setWorkItemIDY(
2952 unsigned Reg = AMDGPU::VGPR1;
2960 if (Info.hasWorkItemIDZ()) {
2961 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2962 if (Subtarget->hasPackedTID()) {
2963 Info.setWorkItemIDZ(
2966 unsigned Reg = AMDGPU::VGPR2;
2986 if (RegIdx == ArgVGPRs.
size()) {
2993 unsigned Reg = ArgVGPRs[RegIdx];
3005 unsigned NumArgRegs) {
3008 if (RegIdx == ArgSGPRs.
size())
3011 unsigned Reg = ArgSGPRs[RegIdx];
3053 const unsigned Mask = 0x3ff;
3056 if (Info.hasWorkItemIDX()) {
3058 Info.setWorkItemIDX(Arg);
3061 if (Info.hasWorkItemIDY()) {
3063 Info.setWorkItemIDY(Arg);
3066 if (Info.hasWorkItemIDZ())
3078 const unsigned Mask = 0x3ff;
3087 auto &
ArgInfo = Info.getArgInfo();
3099 if (Info.hasImplicitArgPtr())
3107 if (Info.hasWorkGroupIDX())
3110 if (Info.hasWorkGroupIDY())
3113 if (Info.hasWorkGroupIDZ())
3116 if (Info.hasLDSKernelId())
3127 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3128 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3134 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3135 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3140 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3141 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3147 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3153 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3162 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3167 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3168 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3173 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3174 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3189 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3191 bool InPreloadSequence =
true;
3193 bool AlignedForImplictArgs =
false;
3194 unsigned ImplicitArgOffset = 0;
3195 for (
auto &Arg :
F.args()) {
3196 if (!InPreloadSequence || !Arg.hasInRegAttr())
3199 unsigned ArgIdx = Arg.getArgNo();
3202 if (InIdx < Ins.
size() &&
3203 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3206 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3207 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3209 assert(ArgLocs[ArgIdx].isMemLoc());
3210 auto &ArgLoc = ArgLocs[InIdx];
3212 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3214 unsigned NumAllocSGPRs =
3215 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3218 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3219 if (!AlignedForImplictArgs) {
3221 alignTo(LastExplicitArgOffset,
3222 Subtarget->getAlignmentForImplicitArgPtr()) -
3223 LastExplicitArgOffset;
3224 AlignedForImplictArgs =
true;
3226 ArgOffset += ImplicitArgOffset;
3230 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3231 assert(InIdx >= 1 &&
"No previous SGPR");
3232 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3233 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3237 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3238 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3241 InPreloadSequence =
false;
3247 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3249 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3251 if (PreloadRegs->
size() > 1)
3252 RC = &AMDGPU::SGPR_32RegClass;
3253 for (
auto &Reg : *PreloadRegs) {
3259 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3268 if (Info.hasLDSKernelId()) {
3269 Register Reg = Info.addLDSKernelId();
3270 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3279 bool IsShader)
const {
3280 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3281 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3287 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3289 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3293 unsigned NumRequiredSystemSGPRs =
3294 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3295 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3296 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3297 Register Reg = Info.addReservedUserSGPR();
3298 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3303 if (!HasArchitectedSGPRs) {
3304 if (Info.hasWorkGroupIDX()) {
3305 Register Reg = Info.addWorkGroupIDX();
3306 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3310 if (Info.hasWorkGroupIDY()) {
3311 Register Reg = Info.addWorkGroupIDY();
3312 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3316 if (Info.hasWorkGroupIDZ()) {
3317 Register Reg = Info.addWorkGroupIDZ();
3318 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3323 if (Info.hasWorkGroupInfo()) {
3324 Register Reg = Info.addWorkGroupInfo();
3325 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3329 if (Info.hasPrivateSegmentWaveByteOffset()) {
3331 unsigned PrivateSegmentWaveByteOffsetReg;
3334 PrivateSegmentWaveByteOffsetReg =
3335 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3339 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3341 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3344 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3346 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3347 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3350 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3351 Info.getNumPreloadedSGPRs() >= 16);
3366 if (HasStackObjects)
3367 Info.setHasNonSpillStackObjects(
true);
3372 HasStackObjects =
true;
3376 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3378 if (!ST.hasFlatScratchEnabled()) {
3379 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3386 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3388 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3398 Info.setScratchRSrcReg(ReservedBufferReg);
3417 if (!MRI.
isLiveIn(AMDGPU::SGPR32)) {
3418 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3425 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3427 Info.setStackPtrOffsetReg(
Reg);
3432 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3439 if (ST.getFrameLowering()->hasFP(MF)) {
3440 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3456 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3465 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3466 RC = &AMDGPU::SGPR_64RegClass;
3467 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3468 RC = &AMDGPU::SGPR_32RegClass;
3474 Entry->addLiveIn(*
I);
3479 for (
auto *Exit : Exits)
3481 TII->get(TargetOpcode::COPY), *
I)
3496 bool IsError =
false;
3500 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3518 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3519 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3521 if (!Subtarget->hasFlatScratchEnabled())
3526 !Subtarget->hasArchitectedSGPRs())
3527 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3528 !Info->hasWorkGroupIDZ());
3531 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3549 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3550 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3553 Info->markPSInputAllocated(0);
3554 Info->markPSInputEnabled(0);
3556 if (Subtarget->isAmdPalOS()) {
3565 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3566 if ((PsInputBits & 0x7F) == 0 ||
3567 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3570 }
else if (IsKernel) {
3571 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3583 if (IsKernel && Subtarget->hasKernargPreload())
3587 }
else if (!IsGraphics) {
3592 if (!Subtarget->hasFlatScratchEnabled())
3604 Info->setNumWaveDispatchSGPRs(
3606 Info->setNumWaveDispatchVGPRs(
3608 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3609 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3614 if (IsWholeWaveFunc) {
3616 {MVT::i1, MVT::Other}, Chain);
3628 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3639 if (IsEntryFunc && VA.
isMemLoc()) {
3662 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3666 int64_t OffsetDiff =
Offset - AlignDownOffset;
3673 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3676 Register VReg = MRI.getLiveInVirtReg(Reg);
3684 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3685 Ins[i].Flags.isSExt(), &Ins[i]);
3693 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3696 if (PreloadRegs.
size() == 1) {
3697 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3702 TRI->getRegSizeInBits(*RC)));
3710 for (
auto Reg : PreloadRegs) {
3711 Register VReg = MRI.getLiveInVirtReg(Reg);
3717 PreloadRegs.size()),
3734 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3735 Ins[i].Flags.isSExt(), &Ins[i]);
3747 "hidden argument in kernel signature was not preloaded",
3753 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3754 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3774 if (!IsEntryFunc && VA.
isMemLoc()) {
3775 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3786 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3787 RC = &AMDGPU::VGPR_32RegClass;
3788 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3789 RC = &AMDGPU::SGPR_32RegClass;
3795 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3801 ReadFirstLane, Val);
3810 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3819 Info->setBytesInStackArgArea(StackArgSize);
3821 return Chains.
empty() ? Chain
3830 const Type *RetTy)
const {
3838 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3843 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3844 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3845 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3846 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3869 Info->setIfReturnsVoid(Outs.
empty());
3870 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3889 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3890 ++
I, ++RealRVLocIdx) {
3894 SDValue Arg = OutVals[RealRVLocIdx];
3917 ReadFirstLane, Arg);
3924 if (!Info->isEntryFunction()) {
3930 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3932 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3945 unsigned Opc = AMDGPUISD::ENDPGM;
3947 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3948 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3949 : AMDGPUISD::RET_GLUE;
4054 const auto [OutgoingArg, ArgRC, ArgTy] =
4059 const auto [IncomingArg, IncomingArgRC, Ty] =
4061 assert(IncomingArgRC == ArgRC);
4064 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4072 InputReg = getImplicitArgPtr(DAG,
DL);
4074 std::optional<uint32_t> Id =
4076 if (Id.has_value()) {
4087 if (OutgoingArg->isRegister()) {
4088 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4089 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4092 unsigned SpecialArgOffset =
4103 auto [OutgoingArg, ArgRC, Ty] =
4106 std::tie(OutgoingArg, ArgRC, Ty) =
4109 std::tie(OutgoingArg, ArgRC, Ty) =
4124 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4125 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4126 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4131 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4139 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4149 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4158 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4159 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4170 : IncomingArgY ? *IncomingArgY
4177 if (OutgoingArg->isRegister()) {
4179 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4205 if (Callee->isDivergent())
4212 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4216 if (!CallerPreserved)
4219 bool CCMatch = CallerCC == CalleeCC;
4232 if (Arg.hasByValAttr())
4246 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4247 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4256 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4269 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4271 if (!CCVA.isRegLoc())
4276 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4278 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4302enum ChainCallArgIdx {
4324 bool UsesDynamicVGPRs =
false;
4325 if (IsChainCallConv) {
4330 auto RequestedExecIt =
4332 return Arg.OrigArgIndex == 2;
4334 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4336 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4339 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4342 "Haven't popped all the special args");
4345 CLI.
Args[ChainCallArgIdx::Exec];
4346 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4354 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4356 ChainCallSpecialArgs.
push_back(Arg.Node);
4359 PushNodeOrTargetConstant(RequestedExecArg);
4365 if (FlagsValue.
isZero()) {
4366 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4368 "no additional args allowed if flags == 0");
4370 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4374 if (!Subtarget->isWave32()) {
4376 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4379 UsesDynamicVGPRs =
true;
4380 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4381 CLI.
Args.end(), PushNodeOrTargetConstant);
4390 bool IsSibCall =
false;
4404 "unsupported call to variadic function ");
4412 "unsupported required tail call to function ");
4417 Outs, OutVals, Ins, DAG);
4421 "site marked musttail or on llvm.amdgcn.cs.chain");
4428 if (!TailCallOpt && IsTailCall)
4452 if (!Subtarget->hasFlatScratchEnabled())
4473 auto *
TRI = Subtarget->getRegisterInfo();
4480 if (!IsSibCall || IsChainCallConv) {
4481 if (!Subtarget->hasFlatScratchEnabled()) {
4487 RegsToPass.emplace_back(IsChainCallConv
4488 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4489 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4496 const unsigned NumSpecialInputs = RegsToPass.size();
4498 MVT PtrVT = MVT::i32;
4501 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4529 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4537 int32_t
Offset = LocMemOffset;
4544 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4550 ? Flags.getNonZeroByValAlign()
4577 if (Outs[i].Flags.isByVal()) {
4579 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4582 Outs[i].Flags.getNonZeroByValAlign(),
4583 Outs[i].Flags.getNonZeroByValAlign(),
4585 nullptr, std::nullopt, DstInfo,
4591 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4597 if (!MemOpChains.
empty())
4613 unsigned ArgIdx = 0;
4614 for (
auto [Reg, Val] : RegsToPass) {
4615 if (ArgIdx++ >= NumSpecialInputs &&
4616 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4642 if (IsTailCall && !IsSibCall) {
4647 std::vector<SDValue>
Ops({Chain});
4653 Ops.push_back(Callee);
4670 Ops.push_back(Callee);
4681 if (IsChainCallConv)
4686 for (
auto &[Reg, Val] : RegsToPass)
4690 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4691 assert(Mask &&
"Missing call preserved mask for calling convention");
4701 MVT::Glue, GlueOps),
4706 Ops.push_back(InGlue);
4712 unsigned OPC = AMDGPUISD::TC_RETURN;
4715 OPC = AMDGPUISD::TC_RETURN_GFX;
4719 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4720 : AMDGPUISD::TC_RETURN_CHAIN;
4726 if (Info->isWholeWaveFunction())
4727 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4734 Chain =
Call.getValue(0);
4735 InGlue =
Call.getValue(1);
4737 uint64_t CalleePopBytes = NumBytes;
4758 EVT VT =
Op.getValueType();
4772 "Stack grows upwards for AMDGPU");
4774 Chain = BaseAddr.getValue(1);
4776 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4777 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4780 if (Alignment > StackAlign) {
4781 uint64_t ScaledAlignment = Alignment.value()
4782 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4783 uint64_t StackAlignMask = ScaledAlignment - 1;
4790 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4799 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4810 if (!HasFlatScratch) {
4813 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4830 if (
Op.getValueType() != MVT::i32)
4849 assert(
Op.getValueType() == MVT::i32);
4858 Op.getOperand(0), IntrinID, GetRoundBothImm);
4892 SDValue RoundModeTimesNumBits =
4912 TableEntry, EnumOffset);
4928 static_cast<uint32_t>(ConstMode->getZExtValue()),
4940 if (UseReducedTable) {
4946 SDValue RoundModeTimesNumBits =
4966 SDValue RoundModeTimesNumBits =
4975 NewMode = TruncTable;
4984 ReadFirstLaneID, NewMode);
4997 IntrinID, RoundBothImm, NewMode);
5003 if (
Op->isDivergent() &&
5004 (!Subtarget->hasVmemPrefInsts() || !
Op.getConstantOperandVal(4)))
5014 if (Subtarget->hasSafeSmemPrefetch())
5022 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5031 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5032 EVT SrcVT = Src.getValueType();
5041 EVT DstVT =
Op.getValueType();
5050 if (
Op.getValueType() != MVT::i64)
5064 Op.getOperand(0), IntrinID, ModeHwRegImm);
5066 Op.getOperand(0), IntrinID, TrapHwRegImm);
5080 if (
Op.getOperand(1).getValueType() != MVT::i64)
5092 ReadFirstLaneID, NewModeReg);
5094 ReadFirstLaneID, NewTrapReg);
5096 unsigned ModeHwReg =
5099 unsigned TrapHwReg =
5107 IntrinID, ModeHwRegImm, NewModeReg);
5110 IntrinID, TrapHwRegImm, NewTrapReg);
5120 .
Case(
"m0", AMDGPU::M0)
5121 .
Case(
"exec", AMDGPU::EXEC)
5122 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5123 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5124 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5125 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5126 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5127 .
Case(
"src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5128 .
Case(
"src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5129 .
Case(
"src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5134 if (!Subtarget->hasFlatScrRegister() &&
5135 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5137 "\" for subtarget."));
5140 if (!Subtarget->hasGloballyAddressableScratch() &&
5141 Subtarget->getRegisterInfo()->regsOverlap(
5142 Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE)) {
5144 "\" for subtarget."));
5149 case AMDGPU::EXEC_LO:
5150 case AMDGPU::EXEC_HI:
5151 case AMDGPU::FLAT_SCR_LO:
5152 case AMDGPU::FLAT_SCR_HI:
5153 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5154 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5159 case AMDGPU::FLAT_SCR:
5160 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5179 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5188static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5210 auto Next = std::next(
I);
5221 MBB.addSuccessor(LoopBB);
5223 return std::pair(LoopBB, RemainderBB);
5230 auto I =
MI.getIterator();
5231 auto E = std::next(
I);
5253 Src->setIsKill(
false);
5263 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5272 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5296 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5297 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5319 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5326 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5330 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5340 if (UseGPRIdxMode) {
5342 SGPRIdxReg = CurrentIdxReg;
5345 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5355 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5386 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5387 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5395 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5414 InitResultReg, DstReg, PhiReg, TmpExec,
5415 Offset, UseGPRIdxMode, SGPRIdxReg);
5421 LoopBB->removeSuccessor(RemainderBB);
5423 LoopBB->addSuccessor(LandingPad);
5434static std::pair<unsigned, int>
5438 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5443 return std::pair(AMDGPU::sub0,
Offset);
5500 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5501 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5507 std::tie(SubReg,
Offset) =
5510 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5513 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5517 if (UseGPRIdxMode) {
5524 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5533 .
addReg(SrcReg, {}, SubReg)
5537 MI.eraseFromParent();
5553 UseGPRIdxMode, SGPRIdxReg);
5557 if (UseGPRIdxMode) {
5559 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5561 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5566 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5567 .
addReg(SrcReg, {}, SubReg)
5571 MI.eraseFromParent();
5588 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5596 std::tie(SubReg,
Offset) =
5598 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5600 if (Idx->
getReg() == AMDGPU::NoRegister) {
5611 MI.eraseFromParent();
5616 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5620 if (UseGPRIdxMode) {
5624 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5633 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5634 TRI.getRegSizeInBits(*VecRC), 32,
false);
5640 MI.eraseFromParent();
5654 UseGPRIdxMode, SGPRIdxReg);
5657 if (UseGPRIdxMode) {
5659 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5661 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5667 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5668 TRI.getRegSizeInBits(*VecRC), 32,
false);
5669 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5675 MI.eraseFromParent();
5691 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5692 if (ST.hasScalarAddSub64()) {
5693 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5703 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5704 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5707 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5709 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5712 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5714 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5716 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5717 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5726 MI.eraseFromParent();
5740 Register SrcCond =
MI.getOperand(3).getReg();
5748 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5750 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5752 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5754 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5757 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5759 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5762 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5764 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5767 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5769 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5791 MI.eraseFromParent();
5796 case AMDGPU::S_MIN_U32:
5797 return std::numeric_limits<uint32_t>::max();
5798 case AMDGPU::S_MIN_I32:
5799 return std::numeric_limits<int32_t>::max();
5800 case AMDGPU::S_MAX_U32:
5801 return std::numeric_limits<uint32_t>::min();
5802 case AMDGPU::S_MAX_I32:
5803 return std::numeric_limits<int32_t>::min();
5804 case AMDGPU::V_ADD_F32_e64:
5806 case AMDGPU::V_SUB_F32_e64:
5808 case AMDGPU::S_ADD_I32:
5809 case AMDGPU::S_SUB_I32:
5810 case AMDGPU::S_OR_B32:
5811 case AMDGPU::S_XOR_B32:
5812 return std::numeric_limits<uint32_t>::min();
5813 case AMDGPU::S_AND_B32:
5814 return std::numeric_limits<uint32_t>::max();
5815 case AMDGPU::V_MIN_F32_e64:
5816 case AMDGPU::V_MAX_F32_e64:
5818 case AMDGPU::V_CMP_LT_U64_e64:
5819 return std::numeric_limits<uint64_t>::max();
5820 case AMDGPU::V_CMP_LT_I64_e64:
5821 return std::numeric_limits<int64_t>::max();
5822 case AMDGPU::V_CMP_GT_U64_e64:
5823 return std::numeric_limits<uint64_t>::min();
5824 case AMDGPU::V_CMP_GT_I64_e64:
5825 return std::numeric_limits<int64_t>::min();
5826 case AMDGPU::V_MIN_F64_e64:
5827 case AMDGPU::V_MAX_F64_e64:
5828 case AMDGPU::V_MIN_NUM_F64_e64:
5829 case AMDGPU::V_MAX_NUM_F64_e64:
5830 return 0x7FF8000000000000;
5831 case AMDGPU::S_ADD_U64_PSEUDO:
5832 case AMDGPU::S_SUB_U64_PSEUDO:
5833 case AMDGPU::S_OR_B64:
5834 case AMDGPU::S_XOR_B64:
5835 return std::numeric_limits<uint64_t>::min();
5836 case AMDGPU::S_AND_B64:
5837 return std::numeric_limits<uint64_t>::max();
5838 case AMDGPU::V_ADD_F64_e64:
5839 case AMDGPU::V_ADD_F64_pseudo_e64:
5840 return 0x8000000000000000;
5847 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5848 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5849 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5850 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5851 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5852 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5853 Opc == AMDGPU::V_SUB_F32_e64;
5857 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5858 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5859 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5860 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5861 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5864static std::tuple<unsigned, unsigned>
5868 case AMDGPU::S_MIN_U32:
5869 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5871 case AMDGPU::S_MIN_I32:
5872 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5874 case AMDGPU::S_MAX_U32:
5875 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5877 case AMDGPU::S_MAX_I32:
5878 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5880 case AMDGPU::S_ADD_I32:
5881 case AMDGPU::S_SUB_I32:
5882 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5883 : AMDGPU::V_ADD_CO_U32_dpp;
5885 case AMDGPU::S_AND_B32:
5886 DPPOpc = AMDGPU::V_AND_B32_dpp;
5888 case AMDGPU::S_OR_B32:
5889 DPPOpc = AMDGPU::V_OR_B32_dpp;
5891 case AMDGPU::S_XOR_B32:
5892 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5894 case AMDGPU::V_ADD_F32_e64:
5895 case AMDGPU::V_SUB_F32_e64:
5896 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5898 case AMDGPU::V_MIN_F32_e64:
5899 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5901 case AMDGPU::V_MAX_F32_e64:
5902 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5904 case AMDGPU::V_CMP_LT_U64_e64:
5905 case AMDGPU::V_CMP_LT_I64_e64:
5906 case AMDGPU::V_CMP_GT_U64_e64:
5907 case AMDGPU::V_CMP_GT_I64_e64:
5908 case AMDGPU::S_ADD_U64_PSEUDO:
5909 case AMDGPU::S_SUB_U64_PSEUDO:
5910 case AMDGPU::S_AND_B64:
5911 case AMDGPU::S_OR_B64:
5912 case AMDGPU::S_XOR_B64:
5913 case AMDGPU::V_MIN_NUM_F64_e64:
5914 case AMDGPU::V_MIN_F64_e64:
5915 case AMDGPU::V_MAX_NUM_F64_e64:
5916 case AMDGPU::V_MAX_F64_e64:
5917 case AMDGPU::V_ADD_F64_pseudo_e64:
5918 case AMDGPU::V_ADD_F64_e64:
5919 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5924 unsigned ClampOpc =
Opc;
5925 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5926 if (
Opc == AMDGPU::S_SUB_I32)
5927 ClampOpc = AMDGPU::S_ADD_I32;
5928 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5929 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5930 else if (
Opc == AMDGPU::S_AND_B64)
5931 ClampOpc = AMDGPU::V_AND_B32_e64;
5932 else if (
Opc == AMDGPU::S_OR_B64)
5933 ClampOpc = AMDGPU::V_OR_B32_e64;
5934 else if (
Opc == AMDGPU::S_XOR_B64)
5935 ClampOpc = AMDGPU::V_XOR_B32_e64;
5937 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5939 return {DPPOpc, ClampOpc};
5942static std::pair<Register, Register>
5949 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5951 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5953 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5954 return {Op1L, Op1H};
5970 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
5971 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
5973 unsigned MIOpc =
MI.getOpcode();
5987 case AMDGPU::S_MIN_U32:
5988 case AMDGPU::S_MIN_I32:
5989 case AMDGPU::V_MIN_F32_e64:
5990 case AMDGPU::S_MAX_U32:
5991 case AMDGPU::S_MAX_I32:
5992 case AMDGPU::V_MAX_F32_e64:
5993 case AMDGPU::S_AND_B32:
5994 case AMDGPU::S_OR_B32: {
6000 case AMDGPU::V_CMP_LT_U64_e64:
6001 case AMDGPU::V_CMP_LT_I64_e64:
6002 case AMDGPU::V_CMP_GT_U64_e64:
6003 case AMDGPU::V_CMP_GT_I64_e64:
6004 case AMDGPU::V_MIN_F64_e64:
6005 case AMDGPU::V_MIN_NUM_F64_e64:
6006 case AMDGPU::V_MAX_F64_e64:
6007 case AMDGPU::V_MAX_NUM_F64_e64:
6008 case AMDGPU::S_AND_B64:
6009 case AMDGPU::S_OR_B64: {
6015 case AMDGPU::S_XOR_B32:
6016 case AMDGPU::S_XOR_B64:
6017 case AMDGPU::S_ADD_I32:
6018 case AMDGPU::S_ADD_U64_PSEUDO:
6019 case AMDGPU::V_ADD_F32_e64:
6020 case AMDGPU::V_ADD_F64_e64:
6021 case AMDGPU::V_ADD_F64_pseudo_e64:
6022 case AMDGPU::S_SUB_I32:
6023 case AMDGPU::S_SUB_U64_PSEUDO:
6024 case AMDGPU::V_SUB_F32_e64: {
6031 bool IsWave32 = ST.isWave32();
6032 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6033 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6034 unsigned BitCountOpc =
6035 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6039 auto NewAccumulator =
6044 case AMDGPU::S_XOR_B32:
6045 case AMDGPU::S_XOR_B64: {
6054 .
addReg(NewAccumulator->getOperand(0).getReg())
6057 if (
Opc == AMDGPU::S_XOR_B32) {
6074 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6078 case AMDGPU::S_SUB_I32: {
6087 .
addReg(NewAccumulator->getOperand(0).getReg());
6090 case AMDGPU::S_ADD_I32: {
6093 .
addReg(NewAccumulator->getOperand(0).getReg());
6096 case AMDGPU::S_ADD_U64_PSEUDO:
6097 case AMDGPU::S_SUB_U64_PSEUDO: {
6113 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6116 .
addReg(NewAccumulator->getOperand(0).getReg())
6126 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6128 : NewAccumulator->getOperand(0).getReg();
6132 if (ST.hasScalarMulHiInsts()) {
6143 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6146 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6153 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6159 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6165 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6168 case AMDGPU::V_ADD_F32_e64:
6169 case AMDGPU::V_ADD_F64_e64:
6170 case AMDGPU::V_ADD_F64_pseudo_e64:
6171 case AMDGPU::V_SUB_F32_e64: {
6178 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6179 : AMDGPU::V_CVT_F64_I32_e64),
6181 .
addReg(NewAccumulator->getOperand(0).getReg())
6186 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6187 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6190 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6192 ? AMDGPU::V_MUL_F64_pseudo_e64
6193 : AMDGPU::V_MUL_F64_e64;
6203 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6220 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6232 bool NeedsMovDPP = !is32BitOpc;
6237 bool IsWave32 = ST.isWave32();
6238 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6239 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6240 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6266 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6270 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6271 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6280 I = ComputeLoop->begin();
6282 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6286 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6290 I = ComputeLoop->end();
6294 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6299 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6300 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6301 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6302 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6304 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6306 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6308 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6309 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6313 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6317 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6319 OpDstReg = VgprResultReg;
6320 LaneValueReg = LaneValVgpr;
6323 if (hasSrc0Modifier)
6325 OpInstr.addReg(AccumulatorReg);
6326 if (hasSrc1Modifier)
6328 OpInstr.addReg(LaneValueReg);
6335 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6336 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6350 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6354 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6358 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6359 LaneValueLoReg, LaneValueHiReg);
6361 case AMDGPU::S_OR_B64:
6362 case AMDGPU::S_AND_B64:
6363 case AMDGPU::S_XOR_B64: {
6366 .
addReg(LaneValue->getOperand(0).getReg())
6370 case AMDGPU::V_CMP_GT_I64_e64:
6371 case AMDGPU::V_CMP_GT_U64_e64:
6372 case AMDGPU::V_CMP_LT_I64_e64:
6373 case AMDGPU::V_CMP_LT_U64_e64: {
6378 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6380 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6384 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6387 .
addReg(LaneValue->getOperand(0).getReg())
6388 .
addReg(AccumulatorVReg);
6390 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6391 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6395 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6396 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6397 .
addReg(LaneValue->getOperand(0).getReg())
6401 case AMDGPU::V_MIN_F64_e64:
6402 case AMDGPU::V_MIN_NUM_F64_e64:
6403 case AMDGPU::V_MAX_F64_e64:
6404 case AMDGPU::V_MAX_NUM_F64_e64:
6405 case AMDGPU::V_ADD_F64_e64:
6406 case AMDGPU::V_ADD_F64_pseudo_e64: {
6408 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6410 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6417 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6420 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6426 .
addReg(LaneValue->getOperand(0).getReg())
6433 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6436 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6438 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6440 ReadLaneLo.addReg(Op1L);
6441 ReadLaneHi.addReg(Op1H);
6443 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6446 case AMDGPU::S_ADD_U64_PSEUDO:
6447 case AMDGPU::S_SUB_U64_PSEUDO: {
6450 .
addReg(LaneValue->getOperand(0).getReg());
6458 unsigned BITSETOpc =
6459 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6460 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6466 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6470 if (!ST.hasScalarCompareEq64()) {
6473 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6475 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6478 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6479 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6481 SetSCCInstr.
addReg(NewActiveBitsReg);
6482 if (ST.hasScalarCompareEq64())
6485 SetSCCInstr.
addReg(NewActiveBitsReg);
6486 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6491 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6508 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6512 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6513 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6516 auto IdentityCopyInstr =
6520 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6521 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6536 if (isFPOp && !NeedsMovDPP)
6539 if (isFPOp && !NeedsMovDPP)
6543 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6552 bool isAddSub =
false,
6553 bool needsCarryIn =
false,
6555 unsigned InstrOpc = ClampOpc;
6558 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6559 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6564 ClampInstr.addReg(CarryOutReg,
6570 ClampInstr.addReg(Src0);
6573 ClampInstr.addReg(Src1);
6576 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6577 ClampInstr.addImm(0);
6579 ClampInstr.addImm(0);
6580 LastBcastInstr = ClampInstr;
6585 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6586 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6587 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6589 if (isAddSubOpc || isBitWiseOpc) {
6596 auto [Src0Lo, Src0Hi] =
6598 auto [Src1Lo, Src1Hi] =
6600 Register CarryReg = BuildClampInstr(
6601 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6602 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6603 isAddSubOpc, CarryReg);
6604 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6633 SrcWithIdentityInstr =
6634 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6641 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6642 auto [SrcReg0Sub0, SrcReg0Sub1] =
6645 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6647 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6648 SrcWithIdentityInstr =
6649 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6656 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6659 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6661 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6664 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6666 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6669 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6671 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6674 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6676 if (ST.hasDPPBroadcasts()) {
6679 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6694 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6715 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6718 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6720 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6723 FinalDPPResult = RowBcast15;
6725 if (ST.hasDPPBroadcasts()) {
6728 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6744 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6748 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6754 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6762 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6767 .
addReg(ShiftedThreadID);
6772 .
addReg(PermuteByteOffset)
6782 auto [RowBcast15Lo, RowBcast15Hi] =
6786 .
addReg(PermuteByteOffset)
6791 .
addReg(PermuteByteOffset)
6794 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6798 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6800 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6802 FinalDPPResult = RowBcast31;
6804 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6805 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6815 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6818 FinalDPPResult = NegatedValVGPR;
6825 .
addImm(ST.getWavefrontSize() - 1);
6840 .
addImm(ST.getWavefrontSize() - 1);
6844 .
addImm(ST.getWavefrontSize() - 1);
6845 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6848 if (
Opc == AMDGPU::S_SUB_I32) {
6849 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6852 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6853 auto NegatedValInstr =
6861 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6867 MI.eraseFromParent();
6882 switch (
MI.getOpcode()) {
6883 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6885 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6887 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6889 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6891 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6893 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6896 ? AMDGPU::V_MIN_NUM_F64_e64
6897 : AMDGPU::V_MIN_F64_e64);
6898 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6900 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6902 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6904 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6906 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6908 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6911 ? AMDGPU::V_MAX_NUM_F64_e64
6912 : AMDGPU::V_MAX_F64_e64);
6913 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6915 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6917 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6919 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6922 ? AMDGPU::V_ADD_F64_pseudo_e64
6923 : AMDGPU::V_ADD_F64_e64);
6924 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6926 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6928 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6930 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6935 ? AMDGPU::V_ADD_F64_pseudo_e64
6936 : AMDGPU::V_ADD_F64_e64);
6937 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
6939 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
6941 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
6943 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
6945 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
6947 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
6949 case AMDGPU::S_UADDO_PSEUDO:
6950 case AMDGPU::S_USUBO_PSEUDO: {
6956 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
6958 : AMDGPU::S_SUB_U32;
6966 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
6969 MI.eraseFromParent();
6972 case AMDGPU::S_ADD_U64_PSEUDO:
6973 case AMDGPU::S_SUB_U64_PSEUDO: {
6976 case AMDGPU::V_ADD_U64_PSEUDO:
6977 case AMDGPU::V_SUB_U64_PSEUDO: {
6978 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
6984 if (ST.hasAddSubU64Insts()) {
6986 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
6987 : AMDGPU::V_SUB_U64_e64),
6992 TII->legalizeOperands(*
I);
6993 MI.eraseFromParent();
6997 if (IsAdd && ST.hasLshlAddU64Inst()) {
7003 TII->legalizeOperands(*
Add);
7004 MI.eraseFromParent();
7008 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7018 : &AMDGPU::VReg_64RegClass;
7021 : &AMDGPU::VReg_64RegClass;
7024 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7026 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7029 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7031 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7034 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7036 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7039 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7046 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7060 TII->legalizeOperands(*LoHalf);
7061 TII->legalizeOperands(*HiHalf);
7062 MI.eraseFromParent();
7065 case AMDGPU::S_ADD_CO_PSEUDO:
7066 case AMDGPU::S_SUB_CO_PSEUDO: {
7078 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7084 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7089 if (
TRI->isVectorRegister(MRI, Src2.
getReg())) {
7090 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7095 if (ST.isWave64()) {
7096 if (ST.hasScalarCompareEq64()) {
7103 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7105 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7107 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7110 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7124 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7125 ? AMDGPU::S_ADDC_U32
7126 : AMDGPU::S_SUBB_U32;
7131 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7137 MI.eraseFromParent();
7140 case AMDGPU::SI_INIT_M0: {
7143 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7146 MI.eraseFromParent();
7149 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7152 TII->get(AMDGPU::S_CMP_EQ_U32))
7157 case AMDGPU::GET_GROUPSTATICSIZE: {
7161 .
add(
MI.getOperand(0))
7163 MI.eraseFromParent();
7166 case AMDGPU::GET_SHADERCYCLESHILO: {
7181 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7184 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7187 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7196 .
add(
MI.getOperand(0))
7201 MI.eraseFromParent();
7204 case AMDGPU::SI_INDIRECT_SRC_V1:
7205 case AMDGPU::SI_INDIRECT_SRC_V2:
7206 case AMDGPU::SI_INDIRECT_SRC_V3:
7207 case AMDGPU::SI_INDIRECT_SRC_V4:
7208 case AMDGPU::SI_INDIRECT_SRC_V5:
7209 case AMDGPU::SI_INDIRECT_SRC_V6:
7210 case AMDGPU::SI_INDIRECT_SRC_V7:
7211 case AMDGPU::SI_INDIRECT_SRC_V8:
7212 case AMDGPU::SI_INDIRECT_SRC_V9:
7213 case AMDGPU::SI_INDIRECT_SRC_V10:
7214 case AMDGPU::SI_INDIRECT_SRC_V11:
7215 case AMDGPU::SI_INDIRECT_SRC_V12:
7216 case AMDGPU::SI_INDIRECT_SRC_V16:
7217 case AMDGPU::SI_INDIRECT_SRC_V32:
7219 case AMDGPU::SI_INDIRECT_DST_V1:
7220 case AMDGPU::SI_INDIRECT_DST_V2:
7221 case AMDGPU::SI_INDIRECT_DST_V3:
7222 case AMDGPU::SI_INDIRECT_DST_V4:
7223 case AMDGPU::SI_INDIRECT_DST_V5:
7224 case AMDGPU::SI_INDIRECT_DST_V6:
7225 case AMDGPU::SI_INDIRECT_DST_V7:
7226 case AMDGPU::SI_INDIRECT_DST_V8:
7227 case AMDGPU::SI_INDIRECT_DST_V9:
7228 case AMDGPU::SI_INDIRECT_DST_V10:
7229 case AMDGPU::SI_INDIRECT_DST_V11:
7230 case AMDGPU::SI_INDIRECT_DST_V12:
7231 case AMDGPU::SI_INDIRECT_DST_V16:
7232 case AMDGPU::SI_INDIRECT_DST_V32:
7234 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7235 case AMDGPU::SI_KILL_I1_PSEUDO:
7237 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7241 case AMDGPU::SI_BR_UNDEF: {
7243 .
add(
MI.getOperand(0));
7245 MI.eraseFromParent();
7248 case AMDGPU::ADJCALLSTACKUP:
7249 case AMDGPU::ADJCALLSTACKDOWN: {
7256 case AMDGPU::SI_CALL_ISEL: {
7257 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7260 MIB =
BuildMI(*BB,
MI,
DL,
TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7266 MI.eraseFromParent();
7269 case AMDGPU::V_ADD_CO_U32_e32:
7270 case AMDGPU::V_SUB_CO_U32_e32:
7271 case AMDGPU::V_SUBREV_CO_U32_e32: {
7273 unsigned Opc =
MI.getOpcode();
7275 bool NeedClampOperand =
false;
7276 if (
TII->pseudoToMCOpcode(
Opc) == -1) {
7278 NeedClampOperand =
true;
7282 if (
TII->isVOP3(*
I)) {
7285 I.add(
MI.getOperand(1)).add(
MI.getOperand(2));
7286 if (NeedClampOperand)
7289 TII->legalizeOperands(*
I);
7291 MI.eraseFromParent();
7294 case AMDGPU::V_ADDC_U32_e32:
7295 case AMDGPU::V_SUBB_U32_e32:
7296 case AMDGPU::V_SUBBREV_U32_e32:
7299 TII->legalizeOperands(
MI);
7301 case AMDGPU::DS_GWS_INIT:
7302 case AMDGPU::DS_GWS_SEMA_BR:
7303 case AMDGPU::DS_GWS_BARRIER:
7304 case AMDGPU::DS_GWS_SEMA_V:
7305 case AMDGPU::DS_GWS_SEMA_P:
7306 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7314 case AMDGPU::S_SETREG_B32: {
7324 auto [ID,
Offset, Width] =
7330 const unsigned SetMask = WidthMask <<
Offset;
7333 unsigned SetDenormOp = 0;
7334 unsigned SetRoundOp = 0;
7342 SetRoundOp = AMDGPU::S_ROUND_MODE;
7343 SetDenormOp = AMDGPU::S_DENORM_MODE;
7345 SetRoundOp = AMDGPU::S_ROUND_MODE;
7347 SetDenormOp = AMDGPU::S_DENORM_MODE;
7350 if (SetRoundOp || SetDenormOp) {
7352 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7353 unsigned ImmVal = Def->getOperand(1).getImm();
7367 MI.eraseFromParent();
7376 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7380 case AMDGPU::S_INVERSE_BALLOT_U32:
7381 case AMDGPU::S_INVERSE_BALLOT_U64:
7384 MI.setDesc(
TII->get(AMDGPU::COPY));
7386 case AMDGPU::ENDPGM_TRAP: {
7388 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7408 MI.eraseFromParent();
7411 case AMDGPU::SIMULATED_TRAP: {
7412 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7414 TII->insertSimulatedTrap(MRI, *BB,
MI,
MI.getDebugLoc());
7415 MI.eraseFromParent();
7418 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7419 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7425 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7426 Register OriginalExec = Setup->getOperand(0).getReg();
7428 MI.getOperand(0).setReg(OriginalExec);
7431 case AMDGPU::V_DOT2_F32_F16:
7432 case AMDGPU::V_DOT2_F32_BF16: {
7473 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7477 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7506 if (!Subtarget->hasMadMacF32Insts())
7507 return Subtarget->hasFastFMAF32();
7513 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7516 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7522 return Subtarget->has16BitInsts() &&
7540 F.getDenormalFPEnv());
7545 switch (Ty.getScalarSizeInBits()) {
7563 return Subtarget->hasMadMacF32Insts() &&
7566 return Subtarget->hasMadF16() &&
7577 if (Ty.getScalarSizeInBits() == 16)
7579 if (Ty.getScalarSizeInBits() == 32)
7594 F.getDenormalFPEnv());
7605 unsigned Opc =
Op.getOpcode();
7606 EVT VT =
Op.getValueType();
7618 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7619 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7632 [[maybe_unused]]
EVT VT =
Op.getValueType();
7634 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7635 VT == MVT::v16i32) &&
7636 "Unexpected ValueType.");
7645 unsigned Opc =
Op.getOpcode();
7646 EVT VT =
Op.getValueType();
7655 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7657 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7664 unsigned Opc =
Op.getOpcode();
7665 EVT VT =
Op.getValueType();
7682 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7684 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7690 switch (
Op.getOpcode()) {
7694 return LowerBRCOND(
Op, DAG);
7696 return LowerRETURNADDR(
Op, DAG);
7698 return LowerSPONENTRY(
Op, DAG);
7701 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7702 "Load should return a value and a chain");
7706 EVT VT =
Op.getValueType();
7708 return lowerFSQRTF32(
Op, DAG);
7710 return lowerFSQRTF64(
Op, DAG);
7715 return LowerTrig(
Op, DAG);
7717 return LowerSELECT(
Op, DAG);
7719 return LowerFDIV(
Op, DAG);
7721 return LowerFFREXP(
Op, DAG);
7723 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7725 return LowerSTORE(
Op, DAG);
7729 return LowerGlobalAddress(MFI,
Op, DAG);
7734 return LowerExternalSymbol(
Op, DAG);
7736 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7738 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7740 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7742 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7744 return LowerINTRINSIC_VOID(
Op, DAG);
7746 return lowerADDRSPACECAST(
Op, DAG);
7748 return lowerINSERT_SUBVECTOR(
Op, DAG);
7750 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7752 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7754 return lowerVECTOR_SHUFFLE(
Op, DAG);
7756 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7758 return lowerBUILD_VECTOR(
Op, DAG);
7761 return lowerFP_ROUND(
Op, DAG);
7763 return lowerTRAP(
Op, DAG);
7765 return lowerDEBUGTRAP(
Op, DAG);
7774 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7775 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7779 if (
Op.getValueType() == MVT::bf16) {
7809 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7812 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7815 return lowerFLDEXP(
Op, DAG);
7820 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7821 Op.getOperand(0).getValueType() == MVT::f32) {
7847 return lowerFCOPYSIGN(
Op, DAG);
7849 return lowerMUL(
Op, DAG);
7852 return lowerXMULO(
Op, DAG);
7855 return lowerXMUL_LOHI(
Op, DAG);
7876 return LowerINLINEASM(
Op, DAG);
7892 EVT FittingLoadVT = LoadVT;
7924SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7927 bool IsIntrinsic)
const {
7930 bool Unpacked = Subtarget->hasUnpackedD16VMem();
7931 EVT LoadVT =
M->getValueType(0);
7933 EVT EquivLoadVT = LoadVT;
7947 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
7951 M->getMemoryVT(),
M->getMemOperand());
7962 EVT LoadVT =
M->getValueType(0);
7971 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
7975 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
7976 bool IsTFE =
M->getNumValues() == 3;
7978 unsigned Opc = IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
7979 : AMDGPUISD::BUFFER_LOAD_FORMAT)
7980 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
7981 : AMDGPUISD::BUFFER_LOAD;
7984 return adjustLoadValueType(AMDGPUISD::BUFFER_LOAD_FORMAT_D16, M, DAG,
Ops);
7989 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
7993 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
7994 M->getMemOperand(), DAG);
7998 SDVTList VTList = DAG.
getVTList(CastVT, MVT::Other);
8000 M->getMemOperand(), DAG);
8008 EVT VT =
N->getValueType(0);
8032 Exec = AMDGPU::EXEC_LO;
8034 Exec = AMDGPU::EXEC;
8051 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8053 EVT VT =
Op.getValueType();
8058 if (VT != MVT::i32) {
8066 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8075 EVT VT =
N->getValueType(0);
8077 unsigned IID =
N->getConstantOperandVal(0);
8078 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8079 IID == Intrinsic::amdgcn_permlanex16;
8080 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8081 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8082 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8083 IID == Intrinsic::amdgcn_permlane_up ||
8084 IID == Intrinsic::amdgcn_permlane_down ||
8085 IID == Intrinsic::amdgcn_permlane_xor;
8090 unsigned SplitSize = 32;
8091 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8092 ST->hasDPALU_DPP() &&
8100 case Intrinsic::amdgcn_permlane16:
8101 case Intrinsic::amdgcn_permlanex16:
8102 case Intrinsic::amdgcn_update_dpp:
8107 case Intrinsic::amdgcn_writelane:
8108 case Intrinsic::amdgcn_permlane_bcast:
8109 case Intrinsic::amdgcn_permlane_up:
8110 case Intrinsic::amdgcn_permlane_down:
8111 case Intrinsic::amdgcn_permlane_xor:
8114 case Intrinsic::amdgcn_readlane:
8115 case Intrinsic::amdgcn_set_inactive:
8116 case Intrinsic::amdgcn_set_inactive_chain_arg:
8117 case Intrinsic::amdgcn_mov_dpp8:
8120 case Intrinsic::amdgcn_readfirstlane:
8121 case Intrinsic::amdgcn_permlane64:
8131 if (
SDNode *GL =
N->getGluedNode()) {
8133 GL = GL->getOperand(0).getNode();
8143 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8144 IID == Intrinsic::amdgcn_mov_dpp8 ||
8145 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8146 IsPermlaneShuffle) {
8147 Src1 =
N->getOperand(2);
8148 if (IID == Intrinsic::amdgcn_writelane ||
8149 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8151 Src2 =
N->getOperand(3);
8154 if (ValSize == SplitSize) {
8164 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8169 if (IID == Intrinsic::amdgcn_writelane) {
8174 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8176 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8179 if (ValSize % SplitSize != 0)
8183 EVT VT =
N->getValueType(0);
8187 unsigned NumOperands =
N->getNumOperands();
8189 SDNode *GL =
N->getGluedNode();
8194 for (
unsigned i = 0; i != NE; ++i) {
8195 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8197 SDValue Operand =
N->getOperand(j);
8227 if (SplitSize == 32) {
8229 return unrollLaneOp(LaneOp.
getNode());
8235 unsigned SubVecNumElt =
8239 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8240 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8244 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8250 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8251 }
else if (IID == Intrinsic::amdgcn_writelane) {
8255 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8257 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8260 EltIdx += SubVecNumElt;
8274 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8277 if (IID == Intrinsic::amdgcn_writelane)
8280 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8287 EVT VT =
N->getValueType(0);
8305 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8315 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8316 {ShiftedIndex, ValueI32});
8326 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8327 {ValueI32, PoisonVal});
8328 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8329 {ShiftedIndex, PoisonVal});
8332 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8335 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8336 {WWMIndex, WWMValue});
8337 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8338 MVT::i32, {WWMIndex, Swapped});
8340 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8348 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8356 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8366 switch (
N->getOpcode()) {
8383 unsigned IID =
N->getConstantOperandVal(0);
8385 case Intrinsic::amdgcn_wave_reduce_min:
8386 case Intrinsic::amdgcn_wave_reduce_umin:
8387 case Intrinsic::amdgcn_wave_reduce_max:
8388 case Intrinsic::amdgcn_wave_reduce_umax:
8389 case Intrinsic::amdgcn_wave_reduce_add:
8390 case Intrinsic::amdgcn_wave_reduce_sub:
8391 case Intrinsic::amdgcn_wave_reduce_and:
8392 case Intrinsic::amdgcn_wave_reduce_or:
8393 case Intrinsic::amdgcn_wave_reduce_xor: {
8394 EVT VT =
N->getValueType(0);
8398 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8399 IID == Intrinsic::amdgcn_wave_reduce_max ||
8400 IID == Intrinsic::amdgcn_wave_reduce_add ||
8401 IID == Intrinsic::amdgcn_wave_reduce_sub;
8405 N->getOperand(0), ExtSrc,
N->getOperand(2));
8409 case Intrinsic::amdgcn_make_buffer_rsrc:
8410 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8412 case Intrinsic::amdgcn_cvt_pkrtz: {
8417 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8421 case Intrinsic::amdgcn_cvt_pknorm_i16:
8422 case Intrinsic::amdgcn_cvt_pknorm_u16:
8423 case Intrinsic::amdgcn_cvt_pk_i16:
8424 case Intrinsic::amdgcn_cvt_pk_u16: {
8430 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8431 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8432 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8433 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8434 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8435 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8437 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8439 EVT VT =
N->getValueType(0);
8448 case Intrinsic::amdgcn_s_buffer_load: {
8454 if (!Subtarget->hasScalarSubwordLoads())
8460 EVT VT =
Op.getValueType();
8461 assert(VT == MVT::i8 &&
"Expected 8-bit s_buffer_load intrinsics.\n");
8473 if (!
Offset->isDivergent()) {
8478 AMDGPUISD::SBUFFER_LOAD_UBYTE,
DL,
8493 LoadVal = handleByteShortBufferLoads(DAG, VT,
DL,
Ops, MMO);
8498 case Intrinsic::amdgcn_dead: {
8499 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8510 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8511 Results.push_back(Res.getOperand(
I));
8515 Results.push_back(Res.getValue(1));
8524 EVT VT =
N->getValueType(0);
8529 EVT SelectVT = NewVT;
8530 if (NewVT.
bitsLT(MVT::i32)) {
8533 SelectVT = MVT::i32;
8539 if (NewVT != SelectVT)
8545 if (
N->getValueType(0) != MVT::v2f16)
8557 if (
N->getValueType(0) != MVT::v2f16)
8569 if (
N->getValueType(0) != MVT::f16)
8584 if (U.get() !=
Value)
8587 if (U.getUser()->getOpcode() == Opcode)
8593unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8596 case Intrinsic::amdgcn_if:
8597 return AMDGPUISD::IF;
8598 case Intrinsic::amdgcn_else:
8599 return AMDGPUISD::ELSE;
8600 case Intrinsic::amdgcn_loop:
8601 return AMDGPUISD::LOOP;
8602 case Intrinsic::amdgcn_end_cf:
8622 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8646 assert(GVar->isDeclaration() &&
8647 "AS 3 & 13 GVs should be declaration here "
8648 "when object linking is enabled");
8663 SDNode *Intr = BRCOND.getOperand(1).getNode();
8680 Intr =
LHS.getNode();
8688 assert(BR &&
"brcond missing unconditional branch user");
8693 unsigned CFNode = isCFIntrinsic(Intr);
8713 Ops.push_back(Target);
8736 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8755 MVT VT =
Op.getSimpleValueType();
8758 if (
Op.getConstantOperandVal(0) != 0)
8762 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8764 if (
Info->isEntryFunction())
8781 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8795 return Op.getValueType().bitsLE(VT)
8803 EVT DstVT =
Op.getValueType();
8810 unsigned Opc =
Op.getOpcode();
8821 bool IsStrict =
Op->isStrictFPOpcode();
8822 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8823 EVT SrcVT = Src.getValueType();
8824 EVT DstVT =
Op.getValueType();
8827 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8830 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8837 if (DstVT == MVT::f16) {
8842 if (!Subtarget->has16BitInsts()) {
8847 if (
Op->getFlags().hasApproximateFuncs()) {
8858 "custom lower FP_ROUND for f16 or bf16");
8859 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8876 EVT VT =
Op.getValueType();
8878 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8879 bool IsIEEEMode =
Info->getMode().IEEE;
8885 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8888 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8889 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8890 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8891 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8897SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8899 EVT VT =
Op.getValueType();
8901 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8902 bool IsIEEEMode =
Info->getMode().IEEE;
8904 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8907 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8908 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8909 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8910 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8917 EVT VT =
Op.getValueType();
8921 EVT ExpVT =
Exp.getValueType();
8922 if (ExpVT == MVT::i16)
8943 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
8950 switch (
Op->getOpcode()) {
8983SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
8984 DAGCombinerInfo &DCI)
const {
8985 EVT OpTy =
Op.getValueType();
8986 SelectionDAG &DAG = DCI.DAG;
8995 Input = DAG.
getNode(ExtOp,
DL, ExtTy, Input);
9003 DAGCombinerInfo &DCI)
const {
9004 const unsigned Opc =
Op.getOpcode();
9013 :
Op->getOperand(0).getValueType();
9014 auto &DAG = DCI.DAG;
9017 if (DCI.isBeforeLegalizeOps() ||
9025 LHS =
Op->getOperand(1);
9026 RHS =
Op->getOperand(2);
9028 LHS =
Op->getOperand(0);
9029 RHS =
Op->getOperand(1);
9073 if (MagVT == SignVT)
9094 EVT VT =
Op.getValueType();
9100 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9127 if (
Op->isDivergent())
9140 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9142 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9145 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9147 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9153 EVT VT =
Op.getValueType();
9160 const APInt &
C = RHSC->getAPIntValue();
9162 if (
C.isPowerOf2()) {
9164 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9191 if (
Op->isDivergent()) {
9195 if (Subtarget->hasSMulHi()) {
9206 if (!Subtarget->hasTrapHandler() ||
9208 return lowerTrapEndpgm(
Op, DAG);
9210 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9211 : lowerTrapHsaQueuePtr(
Op, DAG);
9217 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9221SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9223 ImplicitParameter Param)
const {
9227 MachinePointerInfo PtrInfo =
9244 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9247 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9250 if (UserSGPR == AMDGPU::NoRegister) {
9267 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9276 if (Subtarget->hasPrivEnabledTrap2NopBug())
9277 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9281 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9289 if (!Subtarget->hasTrapHandler() ||
9293 "debugtrap handler not supported",
9301 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9311 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9312 SmallSet<Register, 8> SGPRInputRegs;
9314 unsigned NumVals = 0;
9317 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9318 NumVals =
Flags.getNumOperandRegisters();
9322 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9323 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9325 for (
unsigned J = 0; J < NumVals; ++J) {
9327 if (
const RegisterSDNode *RegNode =
9336 if (SGPRInputRegs.
empty())
9341 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9353 ReadFirstLaneID, SrcVal);
9357 if (
N->getNumOperands() > 3)
9358 Ops.push_back(
N->getOperand(3));
9364 SDNode *
Next =
nullptr;
9365 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9366 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9367 Next =
N->getOperand(
I).getNode();
9377SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9379 unsigned BaseAS = AS;
9384 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9394SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9398 if (Subtarget->hasApertureRegs()) {
9399 const unsigned ApertureRegNo =
9400 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9401 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9402 !Subtarget->hasGloballyAddressableScratch()) &&
9403 "Cannot use src_private_base with globally addressable scratch!");
9423 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9427 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9429 if (UserSGPR == AMDGPU::NoRegister) {
9440 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9474 const AMDGPUTargetMachine &TM =
9478 unsigned SrcAS = ASC->getSrcAddressSpace();
9479 SDValue Src = ASC->getOperand(0);
9480 unsigned DestAS = ASC->getDestAddressSpace();
9481 bool IsNonNull = ASC->getFlags().hasNonNull();
9492 Subtarget->hasGloballyAddressableScratch()) {
9497 AMDGPU::S_MOV_B32, SL, MVT::i32,
9498 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9521 Subtarget->hasGloballyAddressableScratch()) {
9530 if (Subtarget->isWave64())
9536 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9544 AMDGPU::S_MOV_B64, SL, MVT::i64,
9545 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9547 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9549 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9570 Op.getValueType() == MVT::i64) {
9571 const SIMachineFunctionInfo *
Info =
9573 if (
Info->get32BitAddressHighBits() == 0)
9582 Src.getValueType() == MVT::i64)
9610 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9615 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9617 MVT::i32, InsNumElts / 2);
9622 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9624 if (InsNumElts == 2) {
9637 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9660 if (NumElts == 4 && EltSize == 16 && KIdx) {
9671 unsigned Idx = KIdx->getZExtValue();
9672 bool InsertLo = Idx < 2;
9676 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9682 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9695 assert(VecSize <= 64 &&
"Expected target vector size to be <= 64 bits");
9730 EVT ResultVT =
Op.getValueType();
9743 if (
SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9746 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9750 if (VecSize == 128) {
9758 }
else if (VecSize == 256) {
9761 for (
unsigned P = 0;
P < 4; ++
P) {
9767 Parts[0], Parts[1]));
9769 Parts[2], Parts[3]));
9775 for (
unsigned P = 0;
P < 8; ++
P) {
9782 Parts[0], Parts[1], Parts[2], Parts[3]));
9785 Parts[4], Parts[5], Parts[6], Parts[7]));
9805 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9820 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9830 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9835 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9836 !(Mask[Elt + 1] & 1);
9842 EVT ResultVT =
Op.getValueType();
9845 const int NewSrcNumElts = 2;
9847 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9863 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9885 if (ShouldUseConsecutiveExtract &&
9888 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9889 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9901 if (Idx0 >= SrcNumElts) {
9906 if (Idx1 >= SrcNumElts) {
9911 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9912 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9920 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9921 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9926 if (SubVec0 != SubVec1) {
9927 NewMaskIdx1 += NewSrcNumElts;
9934 {NewMaskIdx0, NewMaskIdx1});
9939 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
9940 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
9941 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
9942 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
9961 EVT ResultVT =
Op.getValueType();
9977 EVT VT =
Op.getValueType();
9979 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
9980 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10014 for (
unsigned P = 0;
P < NumParts; ++
P) {
10016 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10042 if (!Subtarget->isAmdHsaOS())
10085 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10094 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10102 EVT PtrVT =
Op.getValueType();
10104 const GlobalValue *GV = GSD->
getGlobal();
10117 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10138 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10141 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10142 if (Subtarget->has64BitLiterals()) {
10151 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10155 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10173 MachinePointerInfo PtrInfo =
10186 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10208 unsigned Offset)
const {
10210 SDValue Param = lowerKernargMemParameter(
10221 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10229 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10237 unsigned NumElts = Elts.
size();
10239 if (NumElts <= 12) {
10243 Type = MVT::v16f32;
10248 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10254 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10263 SDValue Src,
int ExtraElts) {
10264 EVT SrcVT = Src.getValueType();
10274 while (ExtraElts--)
10285 bool Unpacked,
bool IsD16,
int DMaskPop,
10286 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10290 EVT ReqRetVT = ResultTypes[0];
10292 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10293 ? (ReqRetNumElts + 1) / 2
10296 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10299 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10302 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10307 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10311 SDValue(Result, 0), ZeroIdx);
10314 SDValue(Result, 0), ZeroIdx);
10318 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10320 NumDataDwords - MaskPopDwords);
10325 EVT LegalReqRetVT = ReqRetVT;
10327 if (!
Data.getValueType().isInteger())
10329 Data.getValueType().changeTypeToInteger(),
Data);
10350 if (Result->getNumValues() == 1)
10357 SDValue *LWE,
bool &IsTexFail) {
10377 unsigned DimIdx,
unsigned EndIdx,
10378 unsigned NumGradients) {
10380 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10388 if (((
I + 1) >= EndIdx) ||
10389 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10390 I == DimIdx + NumGradients - 1))) {
10422 !
Op.getNode()->hasAnyUseOfValue(0))
10424 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10435 ResultTypes.erase(&ResultTypes[0]);
10437 bool IsD16 =
false;
10438 bool IsG16 =
false;
10439 bool IsA16 =
false;
10441 int NumVDataDwords = 0;
10442 bool AdjustRetType =
false;
10443 bool IsAtomicPacked16Bit =
false;
10446 const unsigned ArgOffset = WithChain ? 2 : 1;
10449 unsigned DMaskLanes = 0;
10451 if (BaseOpcode->
Atomic) {
10452 VData =
Op.getOperand(2);
10454 IsAtomicPacked16Bit =
10455 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10456 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10457 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10458 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10463 "unsupported image atomic data type");
10475 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10477 DMask = Is64Bit ? 0xf : 0x3;
10478 NumVDataDwords = Is64Bit ? 4 : 2;
10480 DMask = Is64Bit ? 0x3 : 0x1;
10481 NumVDataDwords = Is64Bit ? 2 : 1;
10484 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10487 if (BaseOpcode->
Store) {
10488 VData =
Op.getOperand(2);
10492 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10495 "unsupported image store data type");
10497 if (StoreScalarVT == MVT::f16) {
10498 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10502 VData = handleD16VData(VData, DAG,
true);
10505 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10506 }
else if (!BaseOpcode->
NoReturn) {
10511 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10514 "unsupported image load data type");
10516 if (LoadScalarVT == MVT::f16) {
10517 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10525 (!LoadVT.
isVector() && DMaskLanes > 1))
10531 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10532 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10533 NumVDataDwords = (DMaskLanes + 1) / 2;
10535 NumVDataDwords = DMaskLanes;
10537 AdjustRetType =
true;
10541 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10548 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10549 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10551 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10553 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10554 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10558 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10564 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10568 "Bias needs to be converted to 16 bit in A16 mode");
10573 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10577 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10578 "require 16 bit args for both gradients and addresses");
10583 if (!
ST->hasA16()) {
10584 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10585 "support 16 bit addresses\n");
10595 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10597 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10599 IntrOpcode = G16MappingInfo->
G16;
10622 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10640 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10641 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10642 const bool UseNSA =
ST->hasNSAEncoding() &&
10643 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10644 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10645 const bool UsePartialNSA =
10646 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10649 if (UsePartialNSA) {
10651 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10652 }
else if (!UseNSA) {
10663 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10665 Unorm = UnormConst ? True : False;
10671 bool IsTexFail =
false;
10672 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10681 NumVDataDwords = 1;
10683 NumVDataDwords += 1;
10684 AdjustRetType =
true;
10689 if (AdjustRetType) {
10692 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10701 MVT::i32, NumVDataDwords)
10704 ResultTypes[0] = NewVT;
10705 if (ResultTypes.size() == 3) {
10709 ResultTypes.erase(&ResultTypes[1]);
10723 Ops.push_back(VData);
10724 if (UsePartialNSA) {
10726 Ops.push_back(VAddr);
10730 Ops.push_back(VAddr);
10733 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10735 Ops.push_back(Rsrc);
10740 Ops.push_back(Samp);
10745 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10746 Ops.push_back(Unorm);
10748 Ops.push_back(IsA16 &&
10749 ST->hasFeature(AMDGPU::FeatureR128A16)
10753 Ops.push_back(IsA16 ? True : False);
10755 if (!Subtarget->hasGFX90AInsts())
10756 Ops.push_back(TFE);
10760 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10763 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10764 Ops.push_back(LWE);
10766 Ops.push_back(DimInfo->
DA ? True : False);
10768 Ops.push_back(IsD16 ? True : False);
10770 Ops.push_back(
Op.getOperand(0));
10772 int NumVAddrDwords =
10778 NumVDataDwords, NumVAddrDwords);
10779 }
else if (IsGFX12Plus) {
10781 NumVDataDwords, NumVAddrDwords);
10782 }
else if (IsGFX11Plus) {
10784 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10785 : AMDGPU::MIMGEncGfx11Default,
10786 NumVDataDwords, NumVAddrDwords);
10787 }
else if (IsGFX10Plus) {
10789 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10790 : AMDGPU::MIMGEncGfx10Default,
10791 NumVDataDwords, NumVAddrDwords);
10793 if (Subtarget->hasGFX90AInsts()) {
10795 NumVDataDwords, NumVAddrDwords);
10796 if (Opcode == -1) {
10798 DAG,
Op, OrigResultTypes,
DL,
10799 "requested image instruction is not supported on this GPU");
10802 if (Opcode == -1 &&
10805 NumVDataDwords, NumVAddrDwords);
10808 NumVDataDwords, NumVAddrDwords);
10815 MachineMemOperand *MemRef = MemOp->getMemOperand();
10834 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10835 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10844 bool HasChainResult = MMO !=
nullptr;
10846 if (!HasChainResult) {
10858 if (!
Offset->isDivergent()) {
10866 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) ->
SDValue {
10868 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10871 if (HasChainResult)
10875 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10876 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10878 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10879 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10883 !Subtarget->hasScalarDwordx3Loads()) {
10887 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10892 if (HasChainResult)
10914 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10915 Subtarget->hasScalarSubwordLoads()) {
10919 if (HasChainResult)
10925 unsigned NumLoads = 1;
10931 if (NumElts == 8 || NumElts == 16) {
10932 NumLoads = NumElts / 4;
10936 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
10941 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
10945 for (
unsigned i = 0; i < NumLoads; ++i) {
10948 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
10949 LoadVT, LoadMMO, DAG));
10952 if (NumElts == 8 || NumElts == 16) {
10954 if (HasChainResult) {
10969 if (!Subtarget->hasArchitectedSGPRs())
10974 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
10981 unsigned Width)
const {
10983 using namespace AMDGPU::Hwreg;
10985 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11025 EVT DstVT =
Op.getValueType();
11027 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11028 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11032 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11034 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11047SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11056 const bool HasE5M3ConversionInsts =
11057 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11058 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11062 EVT DstVT =
Op.getValueType();
11070 "only the v2f32 vector result is custom lowered");
11076 auto ConvertByte = [&](
unsigned ByteSel) {
11077 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11082 return ConvertByte(0);
11083 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11088 if (Src.getValueType() != MVT::i32) {
11098 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11099 return lowerFromFP8(
Op, IsBF8, DAG);
11107 EVT ResVT =
Op.getValueType();
11108 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11109 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11110 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11112 "only the v2i8 vector result is custom lowered");
11116 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11121 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11122 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11123 : AMDGPUISD::CVT_PK_FP8_F32;
11131 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11143SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11152 const bool HasE5M3ConversionInsts =
11153 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11154 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11164 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11167 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11170 if (SrcEltVT == MVT::f32)
11171 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11172 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11173 Subtarget->hasF16FP8ConversionInsts()) {
11176 if (!
Op.getValueType().isVector())
11178 return lowerToFP8(
Op, IsBF8,
false, DAG);
11186 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11188 EVT VT =
Op.getValueType();
11190 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11194 switch (IntrinsicID) {
11195 case Intrinsic::amdgcn_wave_reduce_min:
11196 case Intrinsic::amdgcn_wave_reduce_umin:
11197 case Intrinsic::amdgcn_wave_reduce_fmin:
11198 case Intrinsic::amdgcn_wave_reduce_max:
11199 case Intrinsic::amdgcn_wave_reduce_umax:
11200 case Intrinsic::amdgcn_wave_reduce_fmax:
11201 case Intrinsic::amdgcn_wave_reduce_add:
11202 case Intrinsic::amdgcn_wave_reduce_fadd:
11203 case Intrinsic::amdgcn_wave_reduce_sub:
11204 case Intrinsic::amdgcn_wave_reduce_fsub:
11205 case Intrinsic::amdgcn_wave_reduce_and:
11206 case Intrinsic::amdgcn_wave_reduce_or:
11207 case Intrinsic::amdgcn_wave_reduce_xor: {
11208 EVT SrcVT =
Op.getOperand(1).getValueType();
11211 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11212 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11213 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11214 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11218 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11219 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11223 Op.getOperand(0), ExtendedSrc, Strategy);
11232 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11235 return getPreloadedValue(DAG, *MFI, VT,
11238 case Intrinsic::amdgcn_dispatch_ptr:
11239 case Intrinsic::amdgcn_queue_ptr: {
11240 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11242 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11243 DL.getDebugLoc()));
11247 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11250 return getPreloadedValue(DAG, *MFI, VT, RegID);
11252 case Intrinsic::amdgcn_implicitarg_ptr: {
11254 return getImplicitArgPtr(DAG,
DL);
11255 return getPreloadedValue(DAG, *MFI, VT,
11258 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11264 return getPreloadedValue(DAG, *MFI, VT,
11267 case Intrinsic::amdgcn_dispatch_id: {
11270 case Intrinsic::amdgcn_rcp:
11271 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11272 case Intrinsic::amdgcn_rsq:
11273 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11274 case Intrinsic::amdgcn_rsq_legacy:
11278 case Intrinsic::amdgcn_rcp_legacy:
11281 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11282 case Intrinsic::amdgcn_fma_legacy:
11283 case Intrinsic::amdgcn_sudot4:
11284 case Intrinsic::amdgcn_sudot8:
11285 case Intrinsic::amdgcn_tanh:
11287 case Intrinsic::amdgcn_rsq_clamp: {
11289 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11301 case Intrinsic::r600_read_ngroups_x:
11302 if (Subtarget->isAmdHsaOS())
11305 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11308 case Intrinsic::r600_read_ngroups_y:
11309 if (Subtarget->isAmdHsaOS())
11312 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11315 case Intrinsic::r600_read_ngroups_z:
11316 if (Subtarget->isAmdHsaOS())
11319 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11322 case Intrinsic::r600_read_local_size_x:
11323 if (Subtarget->isAmdHsaOS())
11326 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11328 case Intrinsic::r600_read_local_size_y:
11329 if (Subtarget->isAmdHsaOS())
11332 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11334 case Intrinsic::r600_read_local_size_z:
11335 if (Subtarget->isAmdHsaOS())
11338 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11340 case Intrinsic::amdgcn_workgroup_id_x:
11341 return lowerWorkGroupId(DAG, *MFI, VT,
11345 case Intrinsic::amdgcn_workgroup_id_y:
11346 return lowerWorkGroupId(DAG, *MFI, VT,
11350 case Intrinsic::amdgcn_workgroup_id_z:
11351 return lowerWorkGroupId(DAG, *MFI, VT,
11355 case Intrinsic::amdgcn_cluster_id_x:
11356 return Subtarget->hasClusters()
11357 ? getPreloadedValue(DAG, *MFI, VT,
11359 : DAG.getPOISON(VT);
11360 case Intrinsic::amdgcn_cluster_id_y:
11361 return Subtarget->hasClusters()
11362 ? getPreloadedValue(DAG, *MFI, VT,
11365 case Intrinsic::amdgcn_cluster_id_z:
11366 return Subtarget->hasClusters()
11367 ? getPreloadedValue(DAG, *MFI, VT,
11370 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11371 return Subtarget->hasClusters()
11372 ? getPreloadedValue(
11376 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11377 return Subtarget->hasClusters()
11378 ? getPreloadedValue(
11382 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11383 return Subtarget->hasClusters()
11384 ? getPreloadedValue(
11388 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11389 return Subtarget->hasClusters()
11392 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11393 return Subtarget->hasClusters()
11394 ? getPreloadedValue(
11398 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11399 return Subtarget->hasClusters()
11400 ? getPreloadedValue(
11404 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11405 return Subtarget->hasClusters()
11406 ? getPreloadedValue(
11410 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11411 return Subtarget->hasClusters()
11412 ? getPreloadedValue(
11416 case Intrinsic::amdgcn_wave_id:
11417 return lowerWaveID(DAG,
Op);
11418 case Intrinsic::amdgcn_lds_kernel_id: {
11420 return getLDSKernelId(DAG,
DL);
11421 return getPreloadedValue(DAG, *MFI, VT,
11424 case Intrinsic::amdgcn_workitem_id_x:
11425 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11426 case Intrinsic::amdgcn_workitem_id_y:
11427 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11428 case Intrinsic::amdgcn_workitem_id_z:
11429 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11430 case Intrinsic::amdgcn_wavefrontsize:
11432 SDLoc(
Op), MVT::i32);
11433 case Intrinsic::amdgcn_s_buffer_load: {
11434 unsigned CPol =
Op.getConstantOperandVal(3);
11442 Op.getOperand(2),
Op.getOperand(3), DAG);
11444 case Intrinsic::amdgcn_fdiv_fast:
11445 return lowerFDIV_FAST(
Op, DAG);
11446 case Intrinsic::amdgcn_sin:
11447 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11449 case Intrinsic::amdgcn_cos:
11450 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11452 case Intrinsic::amdgcn_mul_u24:
11453 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11455 case Intrinsic::amdgcn_mul_i24:
11456 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11459 case Intrinsic::amdgcn_log_clamp: {
11465 case Intrinsic::amdgcn_fract:
11466 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11468 case Intrinsic::amdgcn_class: {
11470 EVT SrcVT = Src.getValueType();
11471 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11472 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11476 "llvm.amdgcn.class only supports f16, f32, and f64",
11477 DL.getDebugLoc()));
11480 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11482 case Intrinsic::amdgcn_div_fmas:
11483 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11484 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11486 case Intrinsic::amdgcn_div_fixup:
11487 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11488 Op.getOperand(2),
Op.getOperand(3));
11490 case Intrinsic::amdgcn_div_scale: {
11496 SDValue Denominator =
Op.getOperand(2);
11503 SDValue Src0 =
Param->isAllOnes() ? Numerator : Denominator;
11505 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11506 Denominator, Numerator);
11508 case Intrinsic::amdgcn_ballot:
11510 case Intrinsic::amdgcn_fmed3:
11511 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11512 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11513 case Intrinsic::amdgcn_fdot2:
11514 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11515 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11516 case Intrinsic::amdgcn_fmul_legacy:
11517 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11519 case Intrinsic::amdgcn_sbfe:
11520 case Intrinsic::amdgcn_ubfe:
11522 case Intrinsic::amdgcn_cvt_pkrtz:
11523 case Intrinsic::amdgcn_cvt_pknorm_i16:
11524 case Intrinsic::amdgcn_cvt_pknorm_u16:
11525 case Intrinsic::amdgcn_cvt_pk_i16:
11526 case Intrinsic::amdgcn_cvt_pk_u16: {
11528 EVT VT =
Op.getValueType();
11531 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11532 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11533 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11534 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11535 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11536 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11537 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11538 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11540 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11543 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11546 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11549 case Intrinsic::amdgcn_fmad_ftz:
11550 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11551 Op.getOperand(2),
Op.getOperand(3));
11553 case Intrinsic::amdgcn_if_break:
11555 Op->getOperand(1),
Op->getOperand(2)),
11558 case Intrinsic::amdgcn_groupstaticsize: {
11564 const GlobalValue *GV =
11570 case Intrinsic::amdgcn_is_shared:
11571 case Intrinsic::amdgcn_is_private: {
11578 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11582 Subtarget->hasGloballyAddressableScratch()) {
11585 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11586 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11595 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11598 case Intrinsic::amdgcn_perm:
11599 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11600 Op.getOperand(2),
Op.getOperand(3));
11601 case Intrinsic::amdgcn_reloc_constant: {
11611 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11612 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11613 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11614 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11615 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11616 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11617 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11618 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11619 if (
Op.getOperand(4).getValueType() == MVT::i32)
11625 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11626 Op.getOperand(3), IndexKeyi32);
11628 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11629 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11630 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11631 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11632 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11633 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11634 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11635 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11636 if (
Op.getOperand(4).getValueType() == MVT::i64)
11641 Op.getOperand(4).getValueType() == MVT::v2i32
11645 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11646 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11647 Op.getOperand(6)});
11649 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11650 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11651 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11652 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11653 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11654 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11655 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11658 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11663 Op.getOperand(6).getValueType().isVector()
11667 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11668 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11669 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11670 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11671 Args.push_back(
Op.getOperand(9));
11674 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11675 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11676 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11677 if (
Op.getOperand(6).getValueType() == MVT::i32)
11683 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11684 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11685 IndexKeyi32, Op.getOperand(7)});
11687 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11688 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11689 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11690 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11691 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11692 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11696 "invalid matrix and scale format combination in wmma call");
11702 case Intrinsic::amdgcn_readlane:
11703 case Intrinsic::amdgcn_readfirstlane:
11704 case Intrinsic::amdgcn_writelane:
11705 case Intrinsic::amdgcn_permlane16:
11706 case Intrinsic::amdgcn_permlanex16:
11707 case Intrinsic::amdgcn_permlane64:
11708 case Intrinsic::amdgcn_set_inactive:
11709 case Intrinsic::amdgcn_set_inactive_chain_arg:
11710 case Intrinsic::amdgcn_mov_dpp8:
11711 case Intrinsic::amdgcn_update_dpp:
11712 case Intrinsic::amdgcn_permlane_bcast:
11713 case Intrinsic::amdgcn_permlane_up:
11714 case Intrinsic::amdgcn_permlane_down:
11715 case Intrinsic::amdgcn_permlane_xor:
11717 case Intrinsic::amdgcn_dead: {
11719 for (
const EVT ValTy :
Op.getNode()->values())
11723 case Intrinsic::amdgcn_wave_shuffle:
11726 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11728 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11738 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(SOffset))
11739 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11745 unsigned NewOpcode)
const {
11752 "unsupported buffer atomic data type");
11754 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11755 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11773 M->getMemOperand());
11778 unsigned NewOpcode)
const {
11785 "unsupported buffer atomic data type");
11787 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11788 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11806 M->getMemOperand());
11813 unsigned NumOperands =
N->getNumOperands();
11814 if (
N->getOperand(NumOperands - 1) == Zero)
11817 Ops[NumOperands - 1] = Zero;
11823 unsigned IntrID =
Op.getConstantOperandVal(1);
11827 case Intrinsic::amdgcn_cluster_load_b32:
11828 case Intrinsic::amdgcn_cluster_load_b64:
11829 case Intrinsic::amdgcn_cluster_load_b128: {
11830 if (Subtarget->hasGFX1250_STRICT())
11834 case Intrinsic::amdgcn_ds_ordered_add:
11835 case Intrinsic::amdgcn_ds_ordered_swap: {
11840 unsigned IndexOperand =
M->getConstantOperandVal(7);
11841 unsigned WaveRelease =
M->getConstantOperandVal(8);
11842 unsigned WaveDone =
M->getConstantOperandVal(9);
11844 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11845 IndexOperand &= ~0x3f;
11846 unsigned CountDw = 0;
11849 CountDw = (IndexOperand >> 24) & 0xf;
11850 IndexOperand &= ~(0xf << 24);
11852 if (CountDw < 1 || CountDw > 4) {
11855 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11856 DL.getDebugLoc()));
11861 if (IndexOperand) {
11864 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11867 if (WaveDone && !WaveRelease) {
11871 Fn,
"ds_ordered_count: wave_done requires wave_release",
11872 DL.getDebugLoc()));
11875 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11876 unsigned ShaderType =
11878 unsigned Offset0 = OrderedCountIndex << 2;
11879 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11882 Offset1 |= (CountDw - 1) << 6;
11885 Offset1 |= ShaderType << 2;
11887 unsigned Offset = Offset0 | (Offset1 << 8);
11894 M->getVTList(),
Ops,
M->getMemoryVT(),
11895 M->getMemOperand());
11897 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11898 unsigned CPol =
Op.getConstantOperandVal(4);
11905 return lowerSBuffer(
11906 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
11907 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
11908 Op.getOperand(4), DAG,
M->getMemOperand());
11910 case Intrinsic::amdgcn_raw_buffer_load:
11911 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11912 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11913 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11914 case Intrinsic::amdgcn_raw_buffer_load_format:
11915 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11916 const bool IsFormat =
11917 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11918 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11920 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11921 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
11935 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
11937 case Intrinsic::amdgcn_struct_buffer_load:
11938 case Intrinsic::amdgcn_struct_ptr_buffer_load:
11939 case Intrinsic::amdgcn_struct_buffer_load_format:
11940 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
11941 case Intrinsic::amdgcn_struct_atomic_buffer_load:
11942 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
11943 const bool IsFormat =
11944 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
11945 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
11947 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11948 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11963 case Intrinsic::amdgcn_raw_tbuffer_load:
11964 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
11966 EVT LoadVT =
Op.getValueType();
11967 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11968 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
11984 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11986 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
11987 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
11990 case Intrinsic::amdgcn_struct_tbuffer_load:
11991 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
11993 EVT LoadVT =
Op.getValueType();
11994 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
11995 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12011 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12013 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12014 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12017 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12018 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12019 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12020 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12021 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12022 return lowerStructBufferAtomicIntrin(
Op, DAG,
12023 AMDGPUISD::BUFFER_ATOMIC_FADD);
12024 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12025 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12026 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12027 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12028 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12029 return lowerStructBufferAtomicIntrin(
Op, DAG,
12030 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12031 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12032 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12033 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12034 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12036 return lowerStructBufferAtomicIntrin(
Op, DAG,
12037 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12038 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12039 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12040 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12041 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12042 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12043 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12044 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12045 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12046 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12047 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12048 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12049 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12050 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12052 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12053 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12054 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12055 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12056 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12057 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12058 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12059 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12060 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12061 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12062 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12063 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12064 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12065 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12066 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12067 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12068 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12069 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12070 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12071 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12072 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12073 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12074 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12075 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12076 return lowerStructBufferAtomicIntrin(
Op, DAG,
12077 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12078 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12079 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12080 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12081 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12082 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12083 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12084 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12085 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12086 return lowerStructBufferAtomicIntrin(
Op, DAG,
12087 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12088 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12089 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12090 return lowerStructBufferAtomicIntrin(
Op, DAG,
12091 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12092 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12093 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12094 return lowerStructBufferAtomicIntrin(
Op, DAG,
12095 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12096 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12097 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12098 return lowerStructBufferAtomicIntrin(
Op, DAG,
12099 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12100 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12101 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12102 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12103 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12104 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12105 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12106 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12107 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12108 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12109 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12110 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12111 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12112 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12113 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12114 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12115 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12116 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12117 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12118 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12119 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12120 return lowerStructBufferAtomicIntrin(
Op, DAG,
12121 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12122 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12123 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12124 return lowerRawBufferAtomicIntrin(
Op, DAG,
12125 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12126 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12127 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12128 return lowerStructBufferAtomicIntrin(
Op, DAG,
12129 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12133 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12136 "unsupported buffer atomic data type");
12138 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12139 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12153 EVT VT =
Op.getValueType();
12157 Op->getVTList(),
Ops, VT,
12158 M->getMemOperand());
12160 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12163 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12166 "unsupported buffer atomic data type");
12168 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12169 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12183 EVT VT =
Op.getValueType();
12187 Op->getVTList(),
Ops, VT,
12188 M->getMemOperand());
12190 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12191 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12193 SDValue NodePtr =
M->getOperand(2);
12194 SDValue RayExtent =
M->getOperand(3);
12195 SDValue InstanceMask =
M->getOperand(4);
12196 SDValue RayOrigin =
M->getOperand(5);
12197 SDValue RayDir =
M->getOperand(6);
12199 SDValue TDescr =
M->getOperand(8);
12204 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12205 const unsigned NumVDataDwords = 10;
12206 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12208 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12209 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12210 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12214 Ops.push_back(NodePtr);
12217 {DAG.getBitcast(MVT::i32, RayExtent),
12218 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12219 Ops.push_back(RayOrigin);
12220 Ops.push_back(RayDir);
12221 Ops.push_back(Offsets);
12222 Ops.push_back(TDescr);
12223 Ops.push_back(
M->getChain());
12226 MachineMemOperand *MemRef =
M->getMemOperand();
12230 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12232 SDValue NodePtr =
M->getOperand(2);
12233 SDValue RayExtent =
M->getOperand(3);
12234 SDValue RayOrigin =
M->getOperand(4);
12235 SDValue RayDir =
M->getOperand(5);
12236 SDValue RayInvDir =
M->getOperand(6);
12237 SDValue TDescr =
M->getOperand(7);
12249 const unsigned NumVDataDwords = 4;
12250 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12251 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12252 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12255 const unsigned BaseOpcodes[2][2] = {
12256 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12257 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12258 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12262 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12263 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12264 : AMDGPU::MIMGEncGfx10NSA,
12265 NumVDataDwords, NumVAddrDwords);
12269 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12270 : AMDGPU::MIMGEncGfx10Default,
12271 NumVDataDwords, NumVAddrDwords);
12277 auto packLanes = [&DAG, &
Ops, &
DL](
SDValue Op,
bool IsAligned) {
12280 if (Lanes[0].getValueSizeInBits() == 32) {
12281 for (
unsigned I = 0;
I < 3; ++
I)
12288 Ops.push_back(Lanes[2]);
12300 if (UseNSA && IsGFX11Plus) {
12301 Ops.push_back(NodePtr);
12303 Ops.push_back(RayOrigin);
12308 for (
unsigned I = 0;
I < 3; ++
I) {
12311 {DirLanes[I], InvDirLanes[I]})));
12315 Ops.push_back(RayDir);
12316 Ops.push_back(RayInvDir);
12323 Ops.push_back(NodePtr);
12326 packLanes(RayOrigin,
true);
12327 packLanes(RayDir,
true);
12328 packLanes(RayInvDir,
false);
12333 if (NumVAddrDwords > 12) {
12341 Ops.push_back(MergedOps);
12344 Ops.push_back(TDescr);
12346 Ops.push_back(
M->getChain());
12349 MachineMemOperand *MemRef =
M->getMemOperand();
12353 case Intrinsic::amdgcn_global_atomic_fmin_num:
12354 case Intrinsic::amdgcn_global_atomic_fmax_num:
12355 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12356 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12363 unsigned Opcode = 0;
12365 case Intrinsic::amdgcn_global_atomic_fmin_num:
12366 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12370 case Intrinsic::amdgcn_global_atomic_fmax_num:
12371 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12378 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12379 Ops,
M->getMemOperand());
12381 case Intrinsic::amdgcn_s_alloc_vgpr: {
12389 ReadFirstLaneID, NumVGPRs);
12392 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12394 case Intrinsic::amdgcn_s_get_barrier_state:
12395 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12402 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12403 BarID = BarID & 0x3F;
12404 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12407 Ops.push_back(Chain);
12409 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12410 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12421 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12422 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12423 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12427 EVT VT =
Op->getValueType(0);
12431 case Intrinsic::amdgcn_av_load_b128: {
12435 EVT VT =
Op->getValueType(0);
12442 case Intrinsic::amdgcn_flat_load_monitor_b32:
12443 case Intrinsic::amdgcn_flat_load_monitor_b64:
12444 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12449 Op->getVTList(), {Chain, Ptr},
12452 case Intrinsic::amdgcn_global_load_monitor_b32:
12453 case Intrinsic::amdgcn_global_load_monitor_b64:
12454 case Intrinsic::amdgcn_global_load_monitor_b128: {
12459 Op->getVTList(), {Chain, Ptr},
12464 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12466 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12474SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12481 EVT VT = VTList.
VTs[0];
12484 bool IsTFE = VTList.
NumVTs == 3;
12487 unsigned NumOpDWords = NumValueDWords + 1;
12489 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12490 MachineMemOperand *OpDWordsMMO =
12492 SDValue Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12493 OpDWordsVT, OpDWordsMMO, DAG);
12498 NumValueDWords == 1
12507 if (!Subtarget->hasDwordx3LoadStores() &&
12508 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12512 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12514 WidenedMemVT, WidenedMMO);
12524 bool ImageStore)
const {
12534 if (Subtarget->hasUnpackedD16VMem()) {
12548 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12559 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12565 if ((NumElements % 2) == 1) {
12567 unsigned I = Elts.
size() / 2;
12583 if (NumElements == 3) {
12602 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12603 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12604 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12605 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12606 case Intrinsic::amdgcn_load_async_to_lds:
12607 case Intrinsic::amdgcn_global_load_async_lds:
12617 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12619 switch (IntrinsicID) {
12620 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12621 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12622 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12623 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12624 if (Subtarget->hasGFX1250_STRICT())
12628 case Intrinsic::amdgcn_exp_compr: {
12649 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12653 case Intrinsic::amdgcn_struct_tbuffer_store:
12654 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12658 VData = handleD16VData(VData, DAG);
12659 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12660 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12674 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12675 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12678 M->getMemoryVT(),
M->getMemOperand());
12681 case Intrinsic::amdgcn_raw_tbuffer_store:
12682 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12686 VData = handleD16VData(VData, DAG);
12687 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12688 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12702 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12703 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12706 M->getMemoryVT(),
M->getMemOperand());
12709 case Intrinsic::amdgcn_raw_buffer_store:
12710 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12711 case Intrinsic::amdgcn_raw_buffer_store_format:
12712 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12713 const bool IsFormat =
12714 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12715 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12725 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12730 VData = handleD16VData(VData, DAG);
12740 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12741 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12755 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12756 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12761 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12764 M->getMemoryVT(),
M->getMemOperand());
12767 case Intrinsic::amdgcn_struct_buffer_store:
12768 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12769 case Intrinsic::amdgcn_struct_buffer_store_format:
12770 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12771 const bool IsFormat =
12772 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12773 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12783 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12788 VData = handleD16VData(VData, DAG);
12798 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12799 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12813 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12814 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12818 EVT VDataType = VData.getValueType().getScalarType();
12820 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12823 M->getMemoryVT(),
M->getMemOperand());
12825 case Intrinsic::amdgcn_raw_buffer_load_lds:
12826 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12827 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12828 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12829 case Intrinsic::amdgcn_struct_buffer_load_lds:
12830 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12831 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12832 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12835 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12836 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12837 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12838 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12839 unsigned OpOffset = HasVIndex ? 1 : 0;
12840 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12842 unsigned Size =
Op->getConstantOperandVal(4);
12848 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12849 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12850 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12851 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12854 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12855 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12856 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12857 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12860 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12861 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12862 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12863 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12866 if (!Subtarget->hasLDSLoadB96_B128())
12868 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12869 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12870 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12871 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12874 if (!Subtarget->hasLDSLoadB96_B128())
12876 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12877 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12878 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12879 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12887 if (HasVIndex && HasVOffset)
12891 else if (HasVIndex)
12892 Ops.push_back(
Op.getOperand(5));
12893 else if (HasVOffset)
12894 Ops.push_back(VOffset);
12896 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12897 Ops.push_back(Rsrc);
12898 Ops.push_back(
Op.getOperand(6 + OpOffset));
12899 Ops.push_back(
Op.getOperand(7 + OpOffset));
12901 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
12924 case Intrinsic::amdgcn_load_to_lds:
12925 case Intrinsic::amdgcn_load_async_to_lds:
12926 case Intrinsic::amdgcn_global_load_lds:
12927 case Intrinsic::amdgcn_global_load_async_lds: {
12928 if (!Subtarget->hasVMemToLDSLoad())
12932 unsigned Size =
Op->getConstantOperandVal(4);
12937 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
12940 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
12943 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
12946 if (!Subtarget->hasLDSLoadB96_B128())
12948 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
12951 if (!Subtarget->hasLDSLoadB96_B128())
12953 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
12969 if (
LHS->isDivergent())
12973 RHS.getOperand(0).getValueType() == MVT::i32) {
12976 VOffset =
RHS.getOperand(0);
12980 Ops.push_back(Addr);
12988 Ops.push_back(VOffset);
12991 Ops.push_back(
Op.getOperand(5));
12993 unsigned Aux =
Op.getConstantOperandVal(6);
13008 case Intrinsic::amdgcn_end_cf:
13010 Op->getOperand(2), Chain),
13012 case Intrinsic::amdgcn_s_barrier_signal_var: {
13019 if (CntC && CntC->isZero()) {
13024 std::optional<uint64_t> BarVal;
13026 BarVal =
C->getZExtValue();
13030 BarVal = *Addr + GA->getOffset();
13033 unsigned BarID = *BarVal & 0x3F;
13035 Ops.push_back(Chain);
13037 Op->getVTList(),
Ops);
13043 case Intrinsic::amdgcn_s_barrier_init: {
13050 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13051 ? AMDGPU::S_BARRIER_INIT_M0
13052 : AMDGPU::S_BARRIER_SIGNAL_M0;
13060 constexpr unsigned ShAmt = 16;
13071 case Intrinsic::amdgcn_s_wakeup_barrier: {
13072 if (!Subtarget->hasSWakeupBarrier())
13076 case Intrinsic::amdgcn_s_barrier_join: {
13085 switch (IntrinsicID) {
13088 case Intrinsic::amdgcn_s_barrier_join:
13089 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13091 case Intrinsic::amdgcn_s_wakeup_barrier:
13092 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13096 unsigned BarID = BarVal & 0x3F;
13099 Ops.push_back(Chain);
13101 switch (IntrinsicID) {
13104 case Intrinsic::amdgcn_s_barrier_join:
13105 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13107 case Intrinsic::amdgcn_s_wakeup_barrier:
13108 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13120 case Intrinsic::amdgcn_s_prefetch_data:
13121 case Intrinsic::amdgcn_s_prefetch_inst: {
13124 return Op.getOperand(0);
13127 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13129 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13136 Op->getVTList(),
Ops,
M->getMemoryVT(),
13137 M->getMemOperand());
13139 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13140 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13141 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13149 case Intrinsic::amdgcn_av_store_b128: {
13157 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13159 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13175 return PtrVT == MVT::i64;
13189std::pair<SDValue, SDValue>
13202 bool CheckNUW = Subtarget->hasGFX1250Insts();
13219 unsigned Overflow = ImmOffset & ~MaxImm;
13220 ImmOffset -= Overflow;
13221 if ((int32_t)Overflow < 0) {
13222 Overflow += ImmOffset;
13227 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13246void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13248 Align Alignment)
const {
13250 SDLoc
DL(CombinedOffset);
13252 uint32_t
Imm =
C->getZExtValue();
13253 uint32_t SOffset, ImmOffset;
13254 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13265 bool CheckNUW = Subtarget->hasGFX1250Insts();
13268 uint32_t SOffset, ImmOffset;
13271 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13279 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13288SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13291 return MaybePointer;
13305 SDValue NumRecords =
Op->getOperand(3);
13311 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13314 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13333 SDValue ExtShiftedStrideVec =
13345 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13347 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13352 auto [LowHalf, HighHalf] =
13353 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13363 NumRecords, Flags);
13375 bool IsTFE)
const {
13380 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13381 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13384 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13396 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13397 : AMDGPUISD::BUFFER_LOAD_USHORT;
13399 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13413 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13417 Ops[1] = BufferStoreExt;
13418 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13419 : AMDGPUISD::BUFFER_STORE_SHORT;
13422 M->getMemOperand());
13447 DAGCombinerInfo &DCI)
const {
13448 SelectionDAG &DAG = DCI.DAG;
13449 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13453 unsigned AS = Ld->getAddressSpace();
13462 EVT MemVT = Ld->getMemoryVT();
13463 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13470 "unexpected vector extload");
13473 SDValue Ptr = Ld->getBasePtr();
13476 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13477 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13482 "unexpected fp extload");
13497 EVT VT = Ld->getValueType(0);
13500 DCI.AddToWorklist(Cvt.
getNode());
13505 DCI.AddToWorklist(Cvt.
getNode());
13516 if (Info.isEntryFunction())
13517 return Info.getUserSGPRInfo().hasFlatScratchInit();
13525 EVT MemVT =
Load->getMemoryVT();
13526 MachineMemOperand *MMO =
Load->getMemOperand();
13538 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13566 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13567 "Custom lowering for non-i32 vectors hasn't been implemented.");
13570 unsigned AS =
Load->getAddressSpace();
13571 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13578 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13582 !Subtarget->hasMultiDwordFlatScratchAddressing())
13592 Subtarget->getScalarizeGlobalBehavior() &&
Load->isSimple() &&
13595 Alignment >=
Align(4) && NumElements < 32) {
13597 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13609 if (NumElements > 4)
13612 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13622 switch (Subtarget->getMaxPrivateElementSize()) {
13628 if (NumElements > 2)
13633 if (NumElements > 4)
13636 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13645 auto Flags =
Load->getMemOperand()->getFlags();
13647 Load->getAlign(), Flags, &
Fast) &&
13656 MemVT, *
Load->getMemOperand())) {
13665 EVT VT =
Op.getValueType();
13702 EVT VT =
Op.getValueType();
13703 const SDNodeFlags
Flags =
Op->getFlags();
13705 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13711 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13714 if (CLHS->isOne()) {
13727 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13731 if (CLHS->isMinusOne()) {
13734 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13740 if (!AllowInaccurateRcp &&
13741 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13755 EVT VT =
Op.getValueType();
13756 const SDNodeFlags
Flags =
Op->getFlags();
13758 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13759 if (!AllowInaccurateDiv)
13783 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13795 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13805 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13809 return DAG.
getNode(Opcode, SL, VTList,
13818 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13828 Opcode = AMDGPUISD::FMA_W_CHAIN;
13832 return DAG.
getNode(Opcode, SL, VTList,
13838 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13839 return FastLowered;
13842 EVT VT =
Op.getValueType();
13849 if (VT == MVT::bf16) {
13872 unsigned FMADOpCode =
13876 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
13879 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13881 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
13882 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13892 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
13898 SDNodeFlags
Flags =
Op->getFlags();
13908 const APFloat K0Val(0x1p+96f);
13911 const APFloat K1Val(0x1p-32f);
13938 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
13939 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
13940 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
13945 if (
SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13946 return FastLowered;
13952 SDNodeFlags
Flags =
Op->getFlags();
13953 Flags.setNoFPExcept(
true);
13961 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
13970 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
13974 using namespace AMDGPU::Hwreg;
13975 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
13979 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
13980 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
13983 const bool HasDynamicDenormals =
13989 if (!PreservesDenormals) {
13994 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
13997 if (HasDynamicDenormals) {
14001 SavedDenormMode =
SDValue(GetReg, 0);
14007 SDNode *EnableDenorm;
14008 if (Subtarget->hasDenormModeInst()) {
14009 const SDValue EnableDenormValue =
14012 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14016 const SDValue EnableDenormValue =
14018 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14019 {EnableDenormValue,
BitField, Glue});
14029 ApproxRcp, One, NegDivScale0, Flags);
14032 ApproxRcp, Fma0, Flags);
14038 NumeratorScaled,
Mul, Flags);
14044 NumeratorScaled, Fma3, Flags);
14046 if (!PreservesDenormals) {
14047 SDNode *DisableDenorm;
14048 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14052 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14054 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14058 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14059 const SDValue DisableDenormValue =
14060 HasDynamicDenormals
14065 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14076 {Fma4, Fma1, Fma3, Scale},
Flags);
14078 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14082 if (
SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14083 return FastLowered;
14091 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14097 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14115 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14145 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14147 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14151 EVT VT =
Op.getValueType();
14153 if (VT == MVT::f32)
14154 return LowerFDIV32(
Op, DAG);
14156 if (VT == MVT::f64)
14157 return LowerFDIV64(
Op, DAG);
14159 if (VT == MVT::f16 || VT == MVT::bf16)
14160 return LowerFDIV16(
Op, DAG);
14169 EVT ResultExpVT =
Op->getValueType(1);
14170 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14180 if (Subtarget->hasFractBug()) {
14198 EVT VT =
Store->getMemoryVT();
14200 if (VT == MVT::i1) {
14204 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14208 Store->getValue().getValueType().getScalarType() == MVT::i32);
14210 unsigned AS =
Store->getAddressSpace();
14211 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14219 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14223 !Subtarget->hasMultiDwordFlatScratchAddressing())
14230 if (NumElements > 4)
14233 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14237 VT, *
Store->getMemOperand()))
14243 switch (Subtarget->getMaxPrivateElementSize()) {
14247 if (NumElements > 2)
14251 if (NumElements > 4 ||
14252 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14260 auto Flags =
Store->getMemOperand()->getFlags();
14279 assert(!Subtarget->has16BitInsts());
14280 SDNodeFlags
Flags =
Op->getFlags();
14294 SDNodeFlags
Flags =
Op->getFlags();
14295 MVT VT =
Op.getValueType().getSimpleVT();
14403 SDNodeFlags
Flags =
Op->getFlags();
14412 if (!
Flags.hasApproximateFuncs()) {
14444 if (!
Flags.hasApproximateFuncs()) {
14453 ScaleDownFactor, ZeroInt);
14460 if (
Flags.hasNoInfs()) {
14476 EVT VT =
Op.getValueType();
14487 if (!
V.getValueType().isVector())
14495 if (Subtarget->hasTrigReducedRange()) {
14497 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14502 switch (
Op.getOpcode()) {
14504 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14507 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14513 return UnrollIfVec(TrigVal);
14533 EVT VT =
Op.getValueType();
14541 Op->getVTList(),
Ops, VT,
14550SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14551 DAGCombinerInfo &DCI)
const {
14552 EVT VT =
N->getValueType(0);
14554 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14557 SelectionDAG &DAG = DCI.DAG;
14561 EVT SrcVT = Src.getValueType();
14567 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14570 DCI.AddToWorklist(Cvt.
getNode());
14573 if (ScalarVT != MVT::f32) {
14585 DAGCombinerInfo &DCI)
const {
14596 SelectionDAG &DAG = DCI.DAG;
14615 for (
unsigned I = 0;
I != NumElts; ++
I) {
14639 if (NewElts.
size() == 1)
14661 for (
unsigned I = 0;
I != NumElts; ++
I) {
14696SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14698 DAGCombinerInfo &DCI)
const {
14715 SelectionDAG &DAG = DCI.DAG;
14728 AM.BaseOffs =
Offset.getSExtValue();
14733 EVT VT =
N->getValueType(0);
14739 Flags.setNoUnsignedWrap(
14740 N->getFlags().hasNoUnsignedWrap() &&
14752 switch (
N->getOpcode()) {
14763 DAGCombinerInfo &DCI)
const {
14764 SelectionDAG &DAG = DCI.DAG;
14771 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14772 N->getMemoryVT(), DCI);
14776 NewOps[PtrIdx] = NewPtr;
14785 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14786 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14795SDValue SITargetLowering::splitBinaryBitConstantOp(
14799 uint32_t ValLo =
Lo_32(Val);
14800 uint32_t ValHi =
Hi_32(Val);
14807 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14821 if (V.getValueType() != MVT::i1)
14823 switch (V.getOpcode()) {
14828 case AMDGPUISD::FP_CLASS:
14840 return V.getResNo() == 1;
14842 unsigned IntrinsicID = V.getConstantOperandVal(0);
14843 switch (IntrinsicID) {
14844 case Intrinsic::amdgcn_is_shared:
14845 case Intrinsic::amdgcn_is_private:
14862 if (!(
C & 0x000000ff))
14863 ZeroByteMask |= 0x000000ff;
14864 if (!(
C & 0x0000ff00))
14865 ZeroByteMask |= 0x0000ff00;
14866 if (!(
C & 0x00ff0000))
14867 ZeroByteMask |= 0x00ff0000;
14868 if (!(
C & 0xff000000))
14869 ZeroByteMask |= 0xff000000;
14870 uint32_t NonZeroByteMask = ~ZeroByteMask;
14871 if ((NonZeroByteMask &
C) != NonZeroByteMask)
14884 assert(V.getValueSizeInBits() == 32);
14886 if (V.getNumOperands() != 2)
14895 switch (V.getOpcode()) {
14900 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14905 return (0x03020100 & ~ConstMask) | ConstMask;
14912 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
14918 return uint32_t(0x0c0c0c0c03020100ull >>
C);
14925 DAGCombinerInfo &DCI)
const {
14926 if (DCI.isBeforeLegalize())
14929 SelectionDAG &DAG = DCI.DAG;
14930 EVT VT =
N->getValueType(0);
14935 if (VT == MVT::i64 && CRHS) {
14937 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
14941 if (CRHS && VT == MVT::i32) {
14951 unsigned Shift = CShift->getZExtValue();
14953 unsigned Offset = NB + Shift;
14954 if ((
Offset & (Bits - 1)) == 0) {
14957 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
14978 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
14980 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
14993 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
14998 if (
X !=
LHS.getOperand(1))
15002 const ConstantFPSDNode *C1 =
15019 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15025 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15028 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15036 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15037 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15039 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15040 :
Mask->getZExtValue() & OrdMask;
15043 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15061 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15064 if (LHSMask != ~0u && RHSMask != ~0u) {
15067 if (LHSMask > RHSMask) {
15074 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15075 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15078 if (!(LHSUsedLanes & RHSUsedLanes) &&
15081 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15087 uint32_t
Mask = LHSMask & RHSMask;
15088 for (
unsigned I = 0;
I < 32;
I += 8) {
15089 uint32_t ByteSel = 0xff <<
I;
15090 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15091 Mask &= (0x0c <<
I) & 0xffffffff;
15096 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15099 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15149static const std::optional<ByteProvider<SDValue>>
15151 unsigned Depth = 0) {
15154 return std::nullopt;
15156 if (
Op.getValueSizeInBits() < 8)
15157 return std::nullopt;
15159 if (
Op.getValueType().isVector())
15162 switch (
Op->getOpcode()) {
15175 NarrowVT = VTSign->getVT();
15178 return std::nullopt;
15181 if (SrcIndex >= NarrowByteWidth)
15182 return std::nullopt;
15190 return std::nullopt;
15192 uint64_t BitShift = ShiftOp->getZExtValue();
15194 if (BitShift % 8 != 0)
15195 return std::nullopt;
15197 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15198 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15199 return std::nullopt;
15218static const std::optional<ByteProvider<SDValue>>
15220 unsigned StartingIndex = 0) {
15224 return std::nullopt;
15226 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15228 return std::nullopt;
15230 return std::nullopt;
15232 bool IsVec =
Op.getValueType().isVector();
15233 switch (
Op.getOpcode()) {
15236 return std::nullopt;
15241 return std::nullopt;
15245 return std::nullopt;
15248 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15249 return std::nullopt;
15250 if (!
LHS ||
LHS->isConstantZero())
15252 if (!
RHS ||
RHS->isConstantZero())
15254 return std::nullopt;
15259 return std::nullopt;
15263 return std::nullopt;
15265 uint32_t BitMask = BitMaskOp->getZExtValue();
15267 uint32_t IndexMask = 0xFF << (Index * 8);
15269 if ((IndexMask & BitMask) != IndexMask) {
15272 if (IndexMask & BitMask)
15273 return std::nullopt;
15282 return std::nullopt;
15286 if (!ShiftOp ||
Op.getValueType().isVector())
15287 return std::nullopt;
15289 uint64_t BitsProvided =
Op.getValueSizeInBits();
15290 if (BitsProvided % 8 != 0)
15291 return std::nullopt;
15293 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15295 return std::nullopt;
15297 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15298 uint64_t ByteShift = BitShift / 8;
15300 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15301 uint64_t BytesProvided = BitsProvided / 8;
15302 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15303 NewIndex %= BytesProvided;
15310 return std::nullopt;
15314 return std::nullopt;
15316 uint64_t BitShift = ShiftOp->getZExtValue();
15318 return std::nullopt;
15320 auto BitsProvided =
Op.getScalarValueSizeInBits();
15321 if (BitsProvided % 8 != 0)
15322 return std::nullopt;
15324 uint64_t BytesProvided = BitsProvided / 8;
15325 uint64_t ByteShift = BitShift / 8;
15326 if (Index + ByteShift < BytesProvided)
15328 Index + ByteShift);
15331 return std::nullopt;
15337 return std::nullopt;
15341 return std::nullopt;
15343 uint64_t BitShift = ShiftOp->getZExtValue();
15344 if (BitShift % 8 != 0)
15345 return std::nullopt;
15346 uint64_t ByteShift = BitShift / 8;
15352 return Index < ByteShift
15355 Depth + 1, StartingIndex);
15364 return std::nullopt;
15372 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15374 if (NarrowBitWidth % 8 != 0)
15375 return std::nullopt;
15376 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15378 if (Index >= NarrowByteWidth)
15380 ? std::optional<ByteProvider<SDValue>>(
15388 return std::nullopt;
15392 if (NarrowByteWidth >= Index) {
15397 return std::nullopt;
15404 return std::nullopt;
15410 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15411 if (NarrowBitWidth % 8 != 0)
15412 return std::nullopt;
15413 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15418 if (Index >= NarrowByteWidth) {
15420 ? std::optional<ByteProvider<SDValue>>(
15425 if (NarrowByteWidth > Index) {
15429 return std::nullopt;
15434 return std::nullopt;
15437 Depth + 1, StartingIndex);
15443 return std::nullopt;
15444 auto VecIdx = IdxOp->getZExtValue();
15445 auto ScalarSize =
Op.getScalarValueSizeInBits();
15446 if (ScalarSize < 32)
15447 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15449 StartingIndex, Index);
15452 case AMDGPUISD::PERM: {
15454 return std::nullopt;
15458 return std::nullopt;
15461 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15462 if (IdxMask > 0x07 && IdxMask != 0x0c)
15463 return std::nullopt;
15465 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15466 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15468 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15474 return std::nullopt;
15489 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15496 auto MemVT = L->getMemoryVT();
15499 return L->getMemoryVT().getSizeInBits() == 16;
15509 int Low8 = Mask & 0xff;
15510 int Hi8 = (Mask & 0xff00) >> 8;
15512 assert(Low8 < 8 && Hi8 < 8);
15514 bool IsConsecutive = (Hi8 - Low8 == 1);
15519 bool Is16Aligned = !(Low8 % 2);
15521 return IsConsecutive && Is16Aligned;
15529 int Low16 = PermMask & 0xffff;
15530 int Hi16 = (PermMask & 0xffff0000) >> 16;
15540 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15542 if (!OtherOpIs16Bit)
15550 unsigned DWordOffset) {
15555 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15560 if (Src.getValueType().isVector()) {
15561 auto ScalarTySize = Src.getScalarValueSizeInBits();
15562 auto ScalarTy = Src.getValueType().getScalarType();
15563 if (ScalarTySize == 32) {
15567 if (ScalarTySize > 32) {
15570 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15571 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15578 assert(ScalarTySize < 32);
15587 auto NumElements =
TypeSize / ScalarTySize;
15588 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15589 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15590 auto NumElementsIn32 = 32 / ScalarTySize;
15591 auto NumAvailElements = DWordOffset < Trunc32Elements
15593 : NumElements - NormalizedTrunc;
15606 auto ShiftVal = 32 * DWordOffset;
15614 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15619 for (
int i = 0; i < 4; i++) {
15621 std::optional<ByteProvider<SDValue>>
P =
15624 if (!
P ||
P->isConstantZero())
15629 if (PermNodes.
size() != 4)
15632 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15633 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15635 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15636 auto PermOp = PermNodes[i];
15639 int SrcByteAdjust = 4;
15643 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15644 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15646 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15647 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15651 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15652 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15655 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15657 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15660 SDValue Op = *PermNodes[FirstSrc.first].Src;
15662 assert(
Op.getValueSizeInBits() == 32);
15666 int Low16 = PermMask & 0xffff;
15667 int Hi16 = (PermMask & 0xffff0000) >> 16;
15669 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15670 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15673 if (WellFormedLow && WellFormedHi)
15677 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15686 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15687 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15692 assert(
Op.getValueType().isByteSized() &&
15703 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15710 DAGCombinerInfo &DCI)
const {
15711 SelectionDAG &DAG = DCI.DAG;
15715 EVT VT =
N->getValueType(0);
15716 if (VT == MVT::i1) {
15718 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15719 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15721 if (Src !=
RHS.getOperand(0))
15726 if (!CLHS || !CRHS)
15730 static const uint32_t MaxMask = 0x3ff;
15735 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15744 LHS.getOpcode() == AMDGPUISD::PERM &&
15750 Sel |=
LHS.getConstantOperandVal(2);
15752 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15759 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15763 auto usesCombinedOperand = [](SDNode *OrUse) {
15766 !OrUse->getValueType(0).isVector())
15770 for (
auto *VUser : OrUse->users()) {
15771 if (!VUser->getValueType(0).isVector())
15778 if (VUser->getOpcode() == VectorwiseOp)
15784 if (!
any_of(
N->users(), usesCombinedOperand))
15790 if (LHSMask != ~0u && RHSMask != ~0u) {
15793 if (LHSMask > RHSMask) {
15800 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15801 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15804 if (!(LHSUsedLanes & RHSUsedLanes) &&
15807 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15809 LHSMask &= ~RHSUsedLanes;
15810 RHSMask &= ~LHSUsedLanes;
15812 LHSMask |= LHSUsedLanes & 0x04040404;
15814 uint32_t Sel = LHSMask | RHSMask;
15817 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15822 if (LHSMask == ~0u || RHSMask == ~0u) {
15863 return IdentitySrc;
15869 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15884 if (SrcVT == MVT::i32) {
15889 DCI.AddToWorklist(LowOr.
getNode());
15890 DCI.AddToWorklist(HiBits.getNode());
15901 N->getOperand(0), CRHS))
15909 DAGCombinerInfo &DCI)
const {
15910 if (
SDValue RV = reassociateScalarOps(
N, DCI.DAG))
15917 SelectionDAG &DAG = DCI.DAG;
15919 EVT VT =
N->getValueType(0);
15920 if (CRHS && VT == MVT::i64) {
15922 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
15929 unsigned Opc =
LHS.getOpcode();
15959 LHS->getOperand(0), FNegLHS, FNegRHS);
15968SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
15969 DAGCombinerInfo &DCI)
const {
15970 if (!Subtarget->has16BitInsts() ||
15974 EVT VT =
N->getValueType(0);
15975 if (VT != MVT::i32)
15979 if (Src.getValueType() != MVT::i16)
15982 if (!Src->hasOneUse())
15989 std::optional<ByteProvider<SDValue>> BP0 =
15991 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
15995 std::optional<ByteProvider<SDValue>> BP1 =
15997 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16005 SelectionDAG &DAG = DCI.DAG;
16007 uint32_t PermMask = 0x0c0c0c0c;
16010 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16015 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16018 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16023SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16024 DAGCombinerInfo &DCI)
const {
16030 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16031 VTSign->getVT() == MVT::i8) ||
16032 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16033 VTSign->getVT() == MVT::i16))) {
16034 assert(Subtarget->hasScalarSubwordLoads() &&
16035 "s_buffer_load_{u8, i8} are supported "
16036 "in GFX12 (or newer) architectures.");
16037 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16038 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16039 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16042 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16050 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16051 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16052 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16054 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16055 VTSign->getVT() == MVT::i8) ||
16056 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16057 VTSign->getVT() == MVT::i16)) &&
16066 Src.getOperand(6), Src.getOperand(7)};
16069 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16070 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16071 ? AMDGPUISD::BUFFER_LOAD_BYTE
16072 : AMDGPUISD::BUFFER_LOAD_SHORT;
16073 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16074 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16075 return DCI.DAG.getMergeValues(
16076 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16082 DAGCombinerInfo &DCI)
const {
16083 SelectionDAG &DAG = DCI.DAG;
16090 if (
N->getOperand(0).isUndef())
16097 DAGCombinerInfo &DCI)
const {
16098 EVT VT =
N->getValueType(0);
16109 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16118 unsigned MaxDepth)
const {
16119 EVT VT =
Op.getValueType();
16121 "expected a floating-point value to query canonicality of");
16127 unsigned MaxDepth)
const {
16129 "QueryVT must be a floating-point scalar type");
16130 EVT VT =
Op.getValueType();
16134 unsigned Opcode =
Op.getOpcode();
16139 const auto &
F = CFP->getValueAPF();
16140 if (
F.isNaN() &&
F.isSignaling())
16142 if (!
F.isDenormal())
16174 case AMDGPUISD::FMUL_LEGACY:
16175 case AMDGPUISD::FMAD_FTZ:
16176 case AMDGPUISD::RCP:
16177 case AMDGPUISD::RSQ:
16178 case AMDGPUISD::RSQ_CLAMP:
16179 case AMDGPUISD::RCP_LEGACY:
16180 case AMDGPUISD::RCP_IFLAG:
16181 case AMDGPUISD::LOG:
16182 case AMDGPUISD::EXP:
16183 case AMDGPUISD::DIV_SCALE:
16184 case AMDGPUISD::DIV_FMAS:
16185 case AMDGPUISD::DIV_FIXUP:
16186 case AMDGPUISD::FRACT:
16187 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16188 case AMDGPUISD::CVT_F32_UBYTE0:
16189 case AMDGPUISD::CVT_F32_UBYTE1:
16190 case AMDGPUISD::CVT_F32_UBYTE2:
16191 case AMDGPUISD::CVT_F32_UBYTE3:
16192 case AMDGPUISD::FP_TO_FP16:
16193 case AMDGPUISD::SIN_HW:
16194 case AMDGPUISD::COS_HW:
16206 if (
Op.getValueType() == MVT::i32) {
16212 if (RHS->getZExtValue() == 0xffff0000) {
16223 return Op.getValueType().getScalarType() != MVT::f16;
16233 case AMDGPUISD::CLAMP:
16234 case AMDGPUISD::FMED3:
16235 case AMDGPUISD::FMAX3:
16236 case AMDGPUISD::FMIN3:
16237 case AMDGPUISD::FMAXIMUM3:
16238 case AMDGPUISD::FMINIMUM3: {
16244 if (Subtarget->supportsMinMaxDenormModes() ||
16254 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16269 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16303 if (
Op.getValueType() == MVT::i16) {
16315 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16317 switch (IntrinsicID) {
16318 case Intrinsic::amdgcn_cvt_pkrtz:
16319 case Intrinsic::amdgcn_cubeid:
16320 case Intrinsic::amdgcn_frexp_mant:
16321 case Intrinsic::amdgcn_fdot2:
16322 case Intrinsic::amdgcn_rcp:
16323 case Intrinsic::amdgcn_rsq:
16324 case Intrinsic::amdgcn_rsq_clamp:
16325 case Intrinsic::amdgcn_rcp_legacy:
16326 case Intrinsic::amdgcn_rsq_legacy:
16327 case Intrinsic::amdgcn_trig_preop:
16328 case Intrinsic::amdgcn_tanh:
16329 case Intrinsic::amdgcn_log:
16330 case Intrinsic::amdgcn_exp2:
16331 case Intrinsic::amdgcn_sqrt:
16349 unsigned MaxDepth)
const {
16352 unsigned Opcode =
MI->getOpcode();
16354 if (Opcode == AMDGPU::G_FCANONICALIZE)
16357 std::optional<FPValueAndVReg> FCR;
16360 if (FCR->Value.isSignaling())
16362 if (!FCR->Value.isDenormal())
16373 case AMDGPU::G_FADD:
16374 case AMDGPU::G_FSUB:
16375 case AMDGPU::G_FMUL:
16376 case AMDGPU::G_FCEIL:
16377 case AMDGPU::G_FFLOOR:
16378 case AMDGPU::G_FRINT:
16379 case AMDGPU::G_FNEARBYINT:
16380 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16381 case AMDGPU::G_INTRINSIC_TRUNC:
16382 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16383 case AMDGPU::G_FMA:
16384 case AMDGPU::G_FMAD:
16385 case AMDGPU::G_FSQRT:
16386 case AMDGPU::G_FDIV:
16387 case AMDGPU::G_FREM:
16388 case AMDGPU::G_FPOW:
16389 case AMDGPU::G_FPEXT:
16390 case AMDGPU::G_FLOG:
16391 case AMDGPU::G_FLOG2:
16392 case AMDGPU::G_FLOG10:
16393 case AMDGPU::G_FPTRUNC:
16394 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16395 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16396 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16397 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16398 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16400 case AMDGPU::G_FNEG:
16401 case AMDGPU::G_FABS:
16402 case AMDGPU::G_FCOPYSIGN:
16404 case AMDGPU::G_FMINNUM:
16405 case AMDGPU::G_FMAXNUM:
16406 case AMDGPU::G_FMINNUM_IEEE:
16407 case AMDGPU::G_FMAXNUM_IEEE:
16408 case AMDGPU::G_FMINIMUM:
16409 case AMDGPU::G_FMAXIMUM:
16410 case AMDGPU::G_FMINIMUMNUM:
16411 case AMDGPU::G_FMAXIMUMNUM: {
16412 if (Subtarget->supportsMinMaxDenormModes() ||
16419 case AMDGPU::G_BUILD_VECTOR:
16424 case AMDGPU::G_INTRINSIC:
16425 case AMDGPU::G_INTRINSIC_CONVERGENT:
16427 case Intrinsic::amdgcn_fmul_legacy:
16428 case Intrinsic::amdgcn_fmad_ftz:
16429 case Intrinsic::amdgcn_sqrt:
16430 case Intrinsic::amdgcn_fmed3:
16431 case Intrinsic::amdgcn_sin:
16432 case Intrinsic::amdgcn_cos:
16433 case Intrinsic::amdgcn_log:
16434 case Intrinsic::amdgcn_exp2:
16435 case Intrinsic::amdgcn_log_clamp:
16436 case Intrinsic::amdgcn_rcp:
16437 case Intrinsic::amdgcn_rcp_legacy:
16438 case Intrinsic::amdgcn_rsq:
16439 case Intrinsic::amdgcn_rsq_clamp:
16440 case Intrinsic::amdgcn_rsq_legacy:
16441 case Intrinsic::amdgcn_div_scale:
16442 case Intrinsic::amdgcn_div_fmas:
16443 case Intrinsic::amdgcn_div_fixup:
16444 case Intrinsic::amdgcn_fract:
16445 case Intrinsic::amdgcn_cvt_pkrtz:
16446 case Intrinsic::amdgcn_cubeid:
16447 case Intrinsic::amdgcn_cubema:
16448 case Intrinsic::amdgcn_cubesc:
16449 case Intrinsic::amdgcn_cubetc:
16450 case Intrinsic::amdgcn_frexp_mant:
16451 case Intrinsic::amdgcn_fdot2:
16452 case Intrinsic::amdgcn_trig_preop:
16453 case Intrinsic::amdgcn_tanh:
16472 if (
C.isDenormal()) {
16485 if (
C.isSignaling()) {
16500SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16501 DAGCombinerInfo &DCI)
const {
16502 SelectionDAG &DAG = DCI.DAG;
16504 EVT VT =
N->getValueType(0);
16513 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16528 EVT EltVT =
Lo.getValueType();
16537 for (
unsigned I = 0;
I != 2; ++
I) {
16541 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16542 }
else if (
Op.isUndef()) {
16577 return AMDGPUISD::FMAX3;
16579 return AMDGPUISD::FMAXIMUM3;
16581 return AMDGPUISD::SMAX3;
16583 return AMDGPUISD::UMAX3;
16587 return AMDGPUISD::FMIN3;
16589 return AMDGPUISD::FMINIMUM3;
16591 return AMDGPUISD::SMIN3;
16593 return AMDGPUISD::UMIN3;
16614 if (!MinK || !MaxK)
16626 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16627 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16628 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16652 bool IsKnownNoNaNs)
const {
16688 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16694 if (
Info->getMode().DX10Clamp) {
16703 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16735 case AMDGPUISD::FMIN_LEGACY:
16736 case AMDGPUISD::FMAX_LEGACY:
16737 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.
hasMin3Max3_16()) ||
16738 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16741 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16742 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16743 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16748 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.
hasMin3Max3_16());
16757 DAGCombinerInfo &DCI)
const {
16758 SelectionDAG &DAG = DCI.DAG;
16769 auto IsTreeWithCombinableChildren = [
Opc](
SDValue Op) {
16770 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16771 Op.getOperand(0).hasOneUse()) ||
16773 Op.getOperand(1).hasOneUse());
16778 bool HasCombinableTreeChild =
16779 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16780 IsTreeWithCombinableChildren(Op1));
16789 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16827 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
16835 if (
SDValue Med3 = performIntMed3ImmCombine(
16840 if (
SDValue Med3 = performIntMed3ImmCombine(
16846 if (
SDValue Med3 = performIntMed3ImmCombine(
16851 if (
SDValue Med3 = performIntMed3ImmCombine(
16864 (
Opc == AMDGPUISD::FMIN_LEGACY &&
16865 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16866 (VT == MVT::f32 || VT == MVT::f64 ||
16867 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16868 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16869 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16870 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16872 if (
SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
16873 N->getFlags().hasNoNaNs()))
16880 const SDNodeFlags
Flags =
N->getFlags();
16882 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16886 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
16896 return (CA->isPosZero() && CB->isOne()) ||
16897 (CA->isOne() && CB->isPosZero());
16906 DAGCombinerInfo &DCI)
const {
16907 EVT VT =
N->getValueType(0);
16911 SelectionDAG &DAG = DCI.DAG;
16922 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16926 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16930 if (
Info->getMode().DX10Clamp) {
16943 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
16950 DAGCombinerInfo &DCI)
const {
16954 return DCI.DAG.getUNDEF(
N->getValueType(0));
16962 bool IsDivergentIdx,
16967 unsigned VecSize = EltSize * NumElem;
16970 if (VecSize <= 64 && EltSize < 32)
16979 if (IsDivergentIdx)
16983 unsigned NumInsts = NumElem +
16984 ((EltSize + 31) / 32) * NumElem ;
16988 if (Subtarget->useVGPRIndexMode())
16989 return NumInsts <= 16;
16993 if (Subtarget->hasMovrel())
16994 return NumInsts <= 15;
17000 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17015SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17016 DAGCombinerInfo &DCI)
const {
17022 EVT ResVT =
N->getValueType(0);
17046 if (!
C ||
C->getZExtValue() != 0x1f)
17062 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17090 DCI.AddToWorklist(Elt0.
getNode());
17091 DCI.AddToWorklist(Elt1.
getNode());
17122 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17123 uint64_t KImmValue = KImm->getZExtValue();
17125 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17128 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17130 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17131 return DAG.
getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17137 if (!DCI.isBeforeLegalize())
17144 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17147 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17148 unsigned EltIdx = BitIndex / 32;
17149 unsigned LeftoverBitIdx = BitIndex % 32;
17153 DCI.AddToWorklist(Cast.
getNode());
17157 DCI.AddToWorklist(Elt.
getNode());
17160 DCI.AddToWorklist(Srl.
getNode());
17164 DCI.AddToWorklist(Trunc.
getNode());
17166 if (VecEltVT == ResVT) {
17178SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17179 DAGCombinerInfo &DCI)
const {
17190 SelectionDAG &DAG = DCI.DAG;
17210 Src.getOperand(0).getValueType() == MVT::f16) {
17211 return Src.getOperand(0);
17215 APFloat Val = CFP->getValueAPF();
17216 bool LosesInfo =
true;
17226 DAGCombinerInfo &DCI)
const {
17227 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17228 "combine only useful on gfx8");
17230 SDValue TruncSrc =
N->getOperand(0);
17231 EVT VT =
N->getValueType(0);
17232 if (VT != MVT::f16)
17235 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17239 SelectionDAG &DAG = DCI.DAG;
17270unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17272 const SDNode *N1)
const {
17277 if (((VT == MVT::f32 &&
17279 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17296 EVT VT =
N->getValueType(0);
17297 if (VT != MVT::i32 && VT != MVT::i64)
17303 unsigned Opc =
N->getOpcode();
17358 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17377 DAGCombinerInfo &DCI)
const {
17380 SelectionDAG &DAG = DCI.DAG;
17381 EVT VT =
N->getValueType(0);
17391 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17395 if (NumBits <= 32 || NumBits > 64)
17406 if (!Subtarget->hasFullRate64Ops()) {
17407 unsigned NumUsers = 0;
17408 for (SDNode *User :
LHS->
users()) {
17411 if (!
User->isAnyAdd())
17435 bool MulSignedLo =
false;
17436 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17445 if (VT != MVT::i64) {
17468 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17470 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17471 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17473 if (!MulLHSUnsigned32) {
17480 if (!MulRHSUnsigned32) {
17491 if (VT != MVT::i64)
17497SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17498 DAGCombinerInfo &DCI)
const {
17508 SelectionDAG &DAG = DCI.DAG;
17523 unsigned Opcode =
N->getOpcode();
17527 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17538static std::optional<ByteProvider<SDValue>>
17541 if (!Byte0 || Byte0->isConstantZero()) {
17542 return std::nullopt;
17545 if (Byte1 && !Byte1->isConstantZero()) {
17546 return std::nullopt;
17552 unsigned FirstCs =
First & 0x0c0c0c0c;
17553 unsigned SecondCs = Second & 0x0c0c0c0c;
17554 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17555 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17557 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17558 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17559 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17560 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17562 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17586 for (
int BPI = 0; BPI < 2; BPI++) {
17589 BPP = {Src1, Src0};
17591 unsigned ZeroMask = 0x0c0c0c0c;
17592 unsigned FMask = 0xFF << (8 * (3 - Step));
17594 unsigned FirstMask =
17595 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17596 unsigned SecondMask =
17597 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17601 int FirstGroup = -1;
17602 for (
int I = 0;
I < 2;
I++) {
17604 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17605 return IterElt.SrcOp == *BPP.first.Src &&
17606 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17610 if (Match != Srcs.
end()) {
17611 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17616 if (FirstGroup != -1) {
17618 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17619 return IterElt.SrcOp == *BPP.second.Src &&
17620 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17623 if (Match != Srcs.
end()) {
17624 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17626 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17634 unsigned ZeroMask = 0x0c0c0c0c;
17635 unsigned FMask = 0xFF << (8 * (3 - Step));
17639 ((Src0.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17643 ((Src1.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17652 if (Srcs.
size() == 1) {
17653 auto *Elt = Srcs.
begin();
17657 if (Elt->PermMask == 0x3020100)
17660 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17664 auto *FirstElt = Srcs.
begin();
17665 auto *SecondElt = std::next(FirstElt);
17672 auto FirstMask = FirstElt->PermMask;
17673 auto SecondMask = SecondElt->PermMask;
17675 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17676 unsigned FirstPlusFour = FirstMask | 0x04040404;
17679 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17691 FirstElt = std::next(SecondElt);
17692 if (FirstElt == Srcs.
end())
17695 SecondElt = std::next(FirstElt);
17698 if (SecondElt == Srcs.
end()) {
17703 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17704 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17710 return Perms.
size() == 2
17716 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17717 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17718 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17719 EntryMask += ZeroMask;
17724 auto Opcode =
Op.getOpcode();
17726 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17727 Opcode == AMDGPUISD::MUL_I24);
17730static std::optional<bool>
17741 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17744 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17746 assert(!(S0IsUnsigned && S0IsSigned));
17747 assert(!(S1IsUnsigned && S1IsSigned));
17755 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17761 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17762 return std::nullopt;
17774 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17775 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17780 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17786 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17787 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17788 return std::nullopt;
17794 DAGCombinerInfo &DCI)
const {
17795 SelectionDAG &DAG = DCI.DAG;
17796 EVT VT =
N->getValueType(0);
17802 if (Subtarget->hasMad64_32()) {
17803 if (
SDValue Folded = tryFoldToMad64_32(
N, DCI))
17808 if (
SDValue V = reassociateScalarOps(
N, DAG)) {
17812 if (VT == MVT::i64) {
17813 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17820 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17822 std::optional<bool> IsSigned;
17828 int ChainLength = 0;
17829 for (
int I = 0;
I < 4;
I++) {
17833 auto Src0 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17836 auto Src1 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17841 TempNode->getOperand(MulIdx), *Src0, *Src1,
17842 TempNode->getOperand(MulIdx)->getOperand(0),
17843 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17847 IsSigned = *IterIsSigned;
17848 if (*IterIsSigned != *IsSigned)
17851 auto AddIdx = 1 - MulIdx;
17854 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
17855 Src2s.
push_back(TempNode->getOperand(AddIdx));
17865 TempNode->getOperand(AddIdx), *Src0, *Src1,
17866 TempNode->getOperand(AddIdx)->getOperand(0),
17867 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17871 if (*IterIsSigned != *IsSigned)
17875 ChainLength =
I + 2;
17879 TempNode = TempNode->getOperand(AddIdx);
17881 ChainLength =
I + 1;
17883 if (TempNode.getOpcode() !=
ISD::ADD)
17885 LHS = TempNode->getOperand(0);
17886 RHS = TempNode->getOperand(1);
17889 if (ChainLength < 2)
17895 if (ChainLength < 4) {
17905 bool UseOriginalSrc =
false;
17906 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
17907 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
17908 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
17909 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
17910 SmallVector<unsigned, 4> SrcBytes;
17911 auto Src0Mask = Src0s.
begin()->PermMask;
17912 SrcBytes.
push_back(Src0Mask & 0xFF000000);
17913 bool UniqueEntries =
true;
17914 for (
auto I = 1;
I < 4;
I++) {
17915 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
17918 UniqueEntries =
false;
17924 if (UniqueEntries) {
17925 UseOriginalSrc =
true;
17927 auto *FirstElt = Src0s.
begin();
17931 auto *SecondElt = Src1s.
begin();
17933 SecondElt->DWordOffset);
17942 if (!UseOriginalSrc) {
17949 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
17952 : Intrinsic::amdgcn_udot4,
17962 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
17967 unsigned Opc =
LHS.getOpcode();
17979 auto Cond =
RHS.getOperand(0);
17984 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18001 DAGCombinerInfo &DCI)
const {
18002 SelectionDAG &DAG = DCI.DAG;
18004 EVT VT =
N->getValueType(0);
18017 SDNodeFlags ShlFlags = N1->
getFlags();
18021 SDNodeFlags NewShlFlags =
18026 DCI.AddToWorklist(Inner.
getNode());
18033 if (Subtarget->hasMad64_32()) {
18034 if (
SDValue Folded = tryFoldToMad64_32(
N, DCI))
18043 if (VT == MVT::i64) {
18044 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18057 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18058 Y->isDivergent() !=
Z->isDivergent()) {
18067 if (
Y->isDivergent())
18070 SDNodeFlags ReassocFlags =
18073 DCI.AddToWorklist(UniformInner.
getNode());
18085 DAGCombinerInfo &DCI)
const {
18086 SelectionDAG &DAG = DCI.DAG;
18087 EVT VT =
N->getValueType(0);
18089 if (VT == MVT::i64) {
18090 if (
SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18094 if (VT != MVT::i32)
18103 unsigned Opc =
RHS.getOpcode();
18110 auto Cond =
RHS.getOperand(0);
18115 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18141 ConstantSDNode *ShiftAmt =
18143 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18154 DAGCombinerInfo &DCI)
const {
18158 SelectionDAG &DAG = DCI.DAG;
18159 EVT VT =
N->getValueType(0);
18171 if (
A ==
LHS.getOperand(1)) {
18172 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18173 if (FusedOp != 0) {
18175 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18183 if (
A ==
RHS.getOperand(1)) {
18184 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18185 if (FusedOp != 0) {
18187 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18196 DAGCombinerInfo &DCI)
const {
18200 SelectionDAG &DAG = DCI.DAG;
18202 EVT VT =
N->getValueType(0);
18215 if (
A ==
LHS.getOperand(1)) {
18216 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18217 if (FusedOp != 0) {
18221 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18230 if (
A ==
RHS.getOperand(1)) {
18231 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18232 if (FusedOp != 0) {
18234 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18243 DAGCombinerInfo &DCI)
const {
18244 SelectionDAG &DAG = DCI.DAG;
18246 EVT VT =
N->getValueType(0);
18248 if (VT != MVT::f16 && VT != MVT::bf16)
18254 SDNodeFlags
Flags =
N->getFlags();
18255 SDNodeFlags RHSFlags =
RHS->getFlags();
18261 bool IsNegative =
false;
18262 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18271 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18272 }
else if (VT == MVT::f16) {
18281 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18298 DAGCombinerInfo &DCI)
const {
18299 SelectionDAG &DAG = DCI.DAG;
18300 EVT VT =
N->getValueType(0);
18304 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18305 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18320 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18325 const ConstantFPSDNode *FalseNode =
18335 if (ScalarVT == MVT::f32 &&
18341 if (TrueNodeExpVal == INT_MIN)
18344 if (FalseNodeExpVal == INT_MIN)
18364 DAGCombinerInfo &DCI)
const {
18365 SelectionDAG &DAG = DCI.DAG;
18366 EVT VT =
N->getValueType(0);
18369 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18397 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18398 FMA->getFlags().hasApproximateFuncs();
18399 if (!AllowInaccuracy) {
18402 if (Subtarget->dot2UnconditionalFlush()) {
18414 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18450 if (Vec1 == Vec2 || Vec3 == Vec4)
18456 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18457 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18500 EVT VT =
LHS.getValueType();
18501 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18533 if (CC ==
ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18537 if (CC ==
ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18541 if (CC ==
ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18545 if (CC ==
ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18548 const std::optional<bool> KnownEq =
18577 if (CC ==
ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18581 if (CC ==
ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18589 const std::optional<bool> KnownUge =
18614 if (CC ==
ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18628 if (CC ==
ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18631 const std::optional<bool> KnownUle =
18654 DAGCombinerInfo &DCI)
const {
18655 SelectionDAG &DAG = DCI.DAG;
18660 EVT VT =
LHS.getValueType();
18689 return LHS.getOperand(0);
18703 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18704 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18709 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18712 return LHS.getOperand(0);
18733 if (VT == MVT::i64) {
18745 const std::optional<bool> KnownEq =
18753 const std::optional<bool> KnownEq =
18764 const std::optional<bool> KnownUge =
18784 const std::optional<bool> KnownUle =
18835 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18840 {Op0Hi, Op1Hi, CarryInHi});
18850 DCI.CombineTo(
LHS.getNode(), Result);
18854 if (VT != MVT::f32 && VT != MVT::f64 &&
18855 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18870 const unsigned IsInfMask =
18872 const unsigned IsFiniteMask =
18877 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
18882 if (VT == MVT::f64) {
18893SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
18894 DAGCombinerInfo &DCI)
const {
18895 SelectionDAG &DAG = DCI.DAG;
18897 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18916 unsigned ShiftOffset = 8 *
Offset;
18918 ShiftOffset -=
C->getZExtValue();
18920 ShiftOffset +=
C->getZExtValue();
18922 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18923 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18924 MVT::f32, Shifted);
18935 DCI.AddToWorklist(
N);
18942 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
18948 DAGCombinerInfo &DCI)
const {
18957 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
18958 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
18963 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
18965 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
18974 if (V.getOpcode() ==
ISD::FFREXP && V.getResNo() == 1) {
18985SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
18986 DAGCombinerInfo &DCI)
const {
18988 if (Subtarget->hasFractBug())
19000 bool CondSelectsZero;
19008 CondSelectsZero =
true;
19009 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19012 CondSelectsZero =
false;
19024 bool IsNonFiniteTest =
false;
19036 bool LHSMatchesFrexp =
19037 (CondLHS == FrexpInput) ||
19038 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19040 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19048 SelectionDAG &DAG = DCI.DAG;
19049 if (LHSMatchesFrexp &&
19051 IsNonFiniteTest = CondSelectsZero;
19053 IsNonFiniteTest = CondSelectsZero;
19060 IsNonFiniteTest = CondSelectsZero;
19067 IsNonFiniteTest = !CondSelectsZero;
19073 SelectionDAG &DAG = DCI.DAG;
19074 if (LHSMatchesFrexp &&
19076 IsNonFiniteTest = !CondSelectsZero;
19078 IsNonFiniteTest = !CondSelectsZero;
19082 if (!IsNonFiniteTest)
19090 DAGCombinerInfo &DCI)
const {
19111 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19112 bool isInteger =
LHS.getValueType().isInteger();
19115 if (!isFloatingPoint && !isInteger)
19120 bool isNonEquality =
19122 if (!isEquality && !isNonEquality)
19139 if (isFloatingPoint) {
19141 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19144 const std::optional<int64_t> Val =
19153 if (!(isEquality && TrueVal == ConstVal) &&
19154 !(isNonEquality && FalseVal == ConstVal))
19158 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19159 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19166 SelectLHS, SelectRHS);
19171 switch (
N->getOpcode()) {
19193 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19203 switch (
N->getOpcode()) {
19205 return performAddCombine(
N, DCI);
19207 return performPtrAddCombine(
N, DCI);
19209 return performSubCombine(
N, DCI);
19211 return performFAddCombine(
N, DCI);
19213 return performFSubCombine(
N, DCI);
19215 return performFDivCombine(
N, DCI);
19217 return performFMulCombine(
N, DCI);
19219 return performSetCCCombine(
N, DCI);
19221 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19223 if (
auto Res = performSelectCombine(
N, DCI))
19238 case AMDGPUISD::FMIN_LEGACY:
19239 case AMDGPUISD::FMAX_LEGACY:
19240 return performMinMaxCombine(
N, DCI);
19242 return performFMACombine(
N, DCI);
19244 return performAndCombine(
N, DCI);
19246 return performOrCombine(
N, DCI);
19249 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19250 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19256 return performXorCombine(
N, DCI);
19259 return performZeroOrAnyExtendCombine(
N, DCI);
19261 return performSignExtendInRegCombine(
N, DCI);
19262 case AMDGPUISD::FP_CLASS:
19263 return performClassCombine(
N, DCI);
19265 return performFCanonicalizeCombine(
N, DCI);
19266 case AMDGPUISD::RCP:
19267 return performRcpCombine(
N, DCI);
19269 case AMDGPUISD::FRACT:
19270 case AMDGPUISD::RSQ:
19271 case AMDGPUISD::RCP_LEGACY:
19272 case AMDGPUISD::RCP_IFLAG:
19273 case AMDGPUISD::RSQ_CLAMP: {
19282 return performUCharToFloatCombine(
N, DCI);
19284 return performFCopySignCombine(
N, DCI);
19285 case AMDGPUISD::CVT_F32_UBYTE0:
19286 case AMDGPUISD::CVT_F32_UBYTE1:
19287 case AMDGPUISD::CVT_F32_UBYTE2:
19288 case AMDGPUISD::CVT_F32_UBYTE3:
19289 return performCvtF32UByteNCombine(
N, DCI);
19290 case AMDGPUISD::FMED3:
19291 return performFMed3Combine(
N, DCI);
19292 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19293 return performCvtPkRTZCombine(
N, DCI);
19294 case AMDGPUISD::CLAMP:
19295 return performClampCombine(
N, DCI);
19298 EVT VT =
N->getValueType(0);
19301 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19304 EVT EltVT = Src.getValueType();
19305 if (EltVT != MVT::i16)
19315 return performExtractVectorEltCombine(
N, DCI);
19317 return performInsertVectorEltCombine(
N, DCI);
19319 return performFPRoundCombine(
N, DCI);
19328 return performMemSDNodeCombine(MemNode, DCI);
19359 unsigned Opcode =
Node->getMachineOpcode();
19362 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19363 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19366 SDNode *
Users[5] = {
nullptr};
19368 unsigned DmaskIdx =
19369 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19370 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19371 unsigned NewDmask = 0;
19372 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19373 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19374 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19375 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19376 unsigned TFCLane = 0;
19377 bool HasChain =
Node->getNumValues() > 1;
19379 if (OldDmask == 0) {
19387 TFCLane = OldBitsSet;
19391 for (SDUse &Use :
Node->uses()) {
19394 if (
Use.getResNo() != 0)
19397 SDNode *
User =
Use.getUser();
19400 if (!
User->isMachineOpcode() ||
19401 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19413 if (UsesTFC && Lane == TFCLane) {
19418 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19420 Dmask &= ~(1 << Comp);
19428 NewDmask |= 1 << Comp;
19433 bool NoChannels = !NewDmask;
19440 if (OldBitsSet == 1)
19446 if (NewDmask == OldDmask)
19455 unsigned NewChannels = BitsSet + UsesTFC;
19459 assert(NewOpcode != -1 &&
19460 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19461 "failed to find equivalent MIMG op");
19469 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19471 MVT ResultVT = NewChannels == 1
19474 : NewChannels == 5 ? 8
19476 SDVTList NewVTList =
19479 MachineSDNode *NewNode =
19488 if (NewChannels == 1) {
19498 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19503 if (i || !NoChannels)
19508 if (NewUser != User) {
19518 Idx = AMDGPU::sub1;
19521 Idx = AMDGPU::sub2;
19524 Idx = AMDGPU::sub3;
19527 Idx = AMDGPU::sub4;
19538 Op =
Op.getOperand(0);
19563 Node->getOperand(0), SL, VReg, SrcVal,
19569 return ToResultReg.
getNode();
19574 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19576 Ops.push_back(
Node->getOperand(i));
19582 Node->getOperand(i).getValueType(),
19583 Node->getOperand(i)),
19595 unsigned Opcode =
Node->getMachineOpcode();
19597 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19598 !
TII->isGather4(Opcode) &&
19600 return adjustWritemask(
Node, DAG);
19603 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19609 case AMDGPU::V_DIV_SCALE_F32_e64:
19610 case AMDGPU::V_DIV_SCALE_F64_e64: {
19620 (Src0 == Src1 || Src0 == Src2))
19676 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19677 unsigned InitIdx = 0;
19679 if (
TII->isImage(
MI)) {
19687 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19688 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19689 unsigned D16Val = D16 ? D16->getImm() : 0;
19691 if (!TFEVal && !LWEVal)
19702 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19704 unsigned dmask = MO_Dmask->
getImm();
19709 bool Packed = !Subtarget->hasUnpackedD16VMem();
19711 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19718 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19719 if (DstSize < InitIdx)
19723 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
19732 unsigned NewDst = 0;
19737 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19738 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19741 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19762 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
19774 if (
TII->isVOP3(
MI.getOpcode())) {
19776 TII->legalizeOperandsVOP3(MRI,
MI);
19778 if (
TII->isMAI(
MI)) {
19783 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19784 AMDGPU::OpName::scale_src0);
19785 if (Src0Idx != -1) {
19786 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19787 AMDGPU::OpName::scale_src1);
19788 if (
TII->usesConstantBus(MRI,
MI, Src0Idx) &&
19789 TII->usesConstantBus(MRI,
MI, Src1Idx))
19790 TII->legalizeOpWithMove(
MI, Src1Idx);
19797 if (
TII->isImage(
MI))
19798 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
19840 uint64_t RsrcDword2And3)
const {
19870std::pair<unsigned, const TargetRegisterClass *>
19877 if (Constraint.
size() == 1) {
19881 if (VT == MVT::Other)
19884 switch (Constraint[0]) {
19891 RC = &AMDGPU::SReg_32RegClass;
19894 RC = &AMDGPU::SGPR_64RegClass;
19899 return std::pair(0U,
nullptr);
19906 return std::pair(0U,
nullptr);
19908 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19909 : &AMDGPU::VGPR_32_Lo256RegClass;
19912 RC = Subtarget->has1024AddressableVGPRs()
19913 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
19916 return std::pair(0U,
nullptr);
19921 if (!Subtarget->hasMAIInsts())
19925 return std::pair(0U,
nullptr);
19927 RC = &AMDGPU::AGPR_32RegClass;
19932 return std::pair(0U,
nullptr);
19937 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
19941 RC = &AMDGPU::AV_32RegClass;
19944 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
19946 return std::pair(0U,
nullptr);
19955 return std::pair(0U, RC);
19958 if (Kind !=
'\0') {
19960 RC = &AMDGPU::VGPR_32_Lo256RegClass;
19961 }
else if (Kind ==
's') {
19962 RC = &AMDGPU::SGPR_32RegClass;
19963 }
else if (Kind ==
'a') {
19964 RC = &AMDGPU::AGPR_32RegClass;
19970 return std::pair(0U,
nullptr);
19976 return std::pair(0U,
nullptr);
19980 RC =
TRI->getVGPRClassForBitWidth(Width);
19982 RC =
TRI->getSGPRClassForBitWidth(Width);
19984 RC =
TRI->getAGPRClassForBitWidth(Width);
19986 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
19991 return std::pair(0U,
nullptr);
19993 return std::pair(Reg, RC);
20002 return std::pair(0U,
nullptr);
20003 if (RC && Idx < RC->getNumRegs())
20005 return std::pair(0U,
nullptr);
20011 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20017 if (Constraint.
size() == 1) {
20018 switch (Constraint[0]) {
20028 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20036 if (Constraint.
size() == 1) {
20037 switch (Constraint[0]) {
20045 }
else if (Constraint.
size() == 2) {
20046 if (Constraint ==
"VA")
20064 std::vector<SDValue> &
Ops,
20079 unsigned Size =
Op.getScalarValueSizeInBits();
20083 if (
Size == 16 && !Subtarget->has16BitInsts())
20087 Val =
C->getSExtValue();
20091 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20095 if (
Size != 16 ||
Op.getNumOperands() != 2)
20097 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20100 Val =
C->getSExtValue();
20104 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20113 uint64_t Val)
const {
20114 if (Constraint.
size() == 1) {
20115 switch (Constraint[0]) {
20130 }
else if (Constraint.
size() == 2) {
20131 if (Constraint ==
"DA") {
20132 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20133 int64_t LoBits =
static_cast<int32_t
>(Val);
20137 if (Constraint ==
"DB") {
20145 unsigned MaxSize)
const {
20146 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20147 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20149 MVT VT =
Op.getSimpleValueType();
20174 switch (UnalignedClassID) {
20175 case AMDGPU::VReg_64RegClassID:
20176 return AMDGPU::VReg_64_Align2RegClassID;
20177 case AMDGPU::VReg_96RegClassID:
20178 return AMDGPU::VReg_96_Align2RegClassID;
20179 case AMDGPU::VReg_128RegClassID:
20180 return AMDGPU::VReg_128_Align2RegClassID;
20181 case AMDGPU::VReg_160RegClassID:
20182 return AMDGPU::VReg_160_Align2RegClassID;
20183 case AMDGPU::VReg_192RegClassID:
20184 return AMDGPU::VReg_192_Align2RegClassID;
20185 case AMDGPU::VReg_224RegClassID:
20186 return AMDGPU::VReg_224_Align2RegClassID;
20187 case AMDGPU::VReg_256RegClassID:
20188 return AMDGPU::VReg_256_Align2RegClassID;
20189 case AMDGPU::VReg_288RegClassID:
20190 return AMDGPU::VReg_288_Align2RegClassID;
20191 case AMDGPU::VReg_320RegClassID:
20192 return AMDGPU::VReg_320_Align2RegClassID;
20193 case AMDGPU::VReg_352RegClassID:
20194 return AMDGPU::VReg_352_Align2RegClassID;
20195 case AMDGPU::VReg_384RegClassID:
20196 return AMDGPU::VReg_384_Align2RegClassID;
20197 case AMDGPU::VReg_512RegClassID:
20198 return AMDGPU::VReg_512_Align2RegClassID;
20199 case AMDGPU::VReg_1024RegClassID:
20200 return AMDGPU::VReg_1024_Align2RegClassID;
20201 case AMDGPU::AReg_64RegClassID:
20202 return AMDGPU::AReg_64_Align2RegClassID;
20203 case AMDGPU::AReg_96RegClassID:
20204 return AMDGPU::AReg_96_Align2RegClassID;
20205 case AMDGPU::AReg_128RegClassID:
20206 return AMDGPU::AReg_128_Align2RegClassID;
20207 case AMDGPU::AReg_160RegClassID:
20208 return AMDGPU::AReg_160_Align2RegClassID;
20209 case AMDGPU::AReg_192RegClassID:
20210 return AMDGPU::AReg_192_Align2RegClassID;
20211 case AMDGPU::AReg_256RegClassID:
20212 return AMDGPU::AReg_256_Align2RegClassID;
20213 case AMDGPU::AReg_512RegClassID:
20214 return AMDGPU::AReg_512_Align2RegClassID;
20215 case AMDGPU::AReg_1024RegClassID:
20216 return AMDGPU::AReg_1024_Align2RegClassID;
20232 if (Info->isEntryFunction()) {
20239 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20241 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20242 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20243 &AMDGPU::SGPR_64RegClass);
20244 Info->setSGPRForEXECCopy(SReg);
20246 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20247 Info->getStackPtrOffsetReg()));
20248 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20249 MRI.
replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20253 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20254 MRI.
replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20256 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20259 Info->limitOccupancy(MF);
20261 if (ST.isWave32() && !MF.
empty()) {
20262 for (
auto &
MBB : MF) {
20263 for (
auto &
MI :
MBB) {
20264 TII->fixImplicitOperands(
MI);
20274 if (ST.needsAlignedVGPRs()) {
20281 if (NewClassID != -1)
20291 const APInt &DemandedElts,
20293 unsigned Depth)
const {
20295 unsigned Opc =
Op.getOpcode();
20298 unsigned IID =
Op.getConstantOperandVal(0);
20300 case Intrinsic::amdgcn_mbcnt_lo:
20301 case Intrinsic::amdgcn_mbcnt_hi: {
20306 Known.Zero.setBitsFrom(
20307 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20333 unsigned MaxValue =
20340 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20344 unsigned Src1Cst = 0;
20345 if (Src1.
isImm()) {
20346 Src1Cst = Src1.
getImm();
20347 }
else if (Src1.
isReg()) {
20351 Src1Cst = Cst->Value.getZExtValue();
20362 if (Width >= BFEWidth)
20379 unsigned Depth)
const {
20382 switch (
MI->getOpcode()) {
20383 case AMDGPU::S_BFE_I32:
20386 case AMDGPU::S_BFE_U32:
20389 case AMDGPU::S_BFE_I64:
20392 case AMDGPU::S_BFE_U64:
20395 case AMDGPU::G_INTRINSIC:
20396 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20399 case Intrinsic::amdgcn_workitem_id_x:
20402 case Intrinsic::amdgcn_workitem_id_y:
20405 case Intrinsic::amdgcn_workitem_id_z:
20408 case Intrinsic::amdgcn_mbcnt_lo:
20409 case Intrinsic::amdgcn_mbcnt_hi: {
20412 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20421 case Intrinsic::amdgcn_groupstaticsize: {
20425 Known.Zero.setHighBits(
20432 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20433 Known.Zero.setHighBits(24);
20435 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20436 Known.Zero.setHighBits(16);
20438 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20441 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20443 case AMDGPU::G_AMDGPU_SMED3:
20444 case AMDGPU::G_AMDGPU_UMED3: {
20445 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20472 unsigned Depth)
const {
20481 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20499 if (Header->getAlignment() != PrefAlign)
20500 return Header->getAlignment();
20501 if (needsFetchWindowAlignment(*Header))
20522 if (Header->getAlignment() != PrefAlign)
20523 return Header->getAlignment();
20525 unsigned LoopSize = 0;
20530 LoopSize +=
MBB->getAlignment().value() / 2;
20533 LoopSize +=
TII->getInstSizeInBytes(
MI);
20534 if (LoopSize > 192)
20539 if (LoopSize <= 64)
20542 if (LoopSize <= 128)
20543 return CacheLineAlign;
20549 auto I = Exit->getFirstNonDebugInstr();
20550 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20551 return CacheLineAlign;
20560 if (PreTerm == Pre->
begin() ||
20561 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20565 auto ExitHead = Exit->getFirstNonDebugInstr();
20566 if (ExitHead == Exit->end() ||
20567 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20572 return CacheLineAlign;
20580 if (needsFetchWindowAlignment(*
MBB))
20585bool SITargetLowering::needsFetchWindowAlignment(
20587 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20591 if (
MI.isMetaInstruction())
20594 return TII->getInstSizeInBytes(
MI) > 4;
20604 N =
N->getOperand(0).getNode();
20614 switch (
N->getOpcode()) {
20622 if (Reg.isPhysical() || MRI.
isLiveIn(Reg))
20623 return !
TRI->isSGPRReg(MRI, Reg);
20629 return !
TRI->isSGPRReg(MRI, Reg);
20633 unsigned AS = L->getAddressSpace();
20643 case AMDGPUISD::ATOMIC_CMP_SWAP:
20644 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20645 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20646 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20647 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20648 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20649 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20650 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20651 case AMDGPUISD::BUFFER_ATOMIC_AND:
20652 case AMDGPUISD::BUFFER_ATOMIC_OR:
20653 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20654 case AMDGPUISD::BUFFER_ATOMIC_INC:
20655 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20656 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20657 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20658 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20659 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20665 return A->readMem() &&
A->writeMem();
20686 switch (Ty.getScalarSizeInBits()) {
20698 const APInt &DemandedElts,
20701 unsigned Depth)
const {
20702 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
20706 if (Info->getMode().DX10Clamp)
20718 if (RMW->
hasMetadata(
"amdgpu.ignore.denormal.mode"))
20738 <<
"Hardware instruction generated for atomic "
20740 <<
" operation at memory scope " << MemScope;
20745 Type *EltTy = VT->getElementType();
20746 return VT->getNumElements() == 2 &&
20766 unsigned BW =
IT->getBitWidth();
20767 return BW == 32 || BW == 64;
20781 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
20782 return BW == 32 || BW == 64;
20785 if (Ty->isFloatTy() || Ty->isDoubleTy())
20789 return VT->getNumElements() == 2 &&
20790 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20800 bool HasSystemScope) {
20807 if (HasSystemScope) {
20808 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20811 if (Subtarget.hasEmulatedSystemScopeAtomics())
20813 }
else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20816 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory");
20829 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
20837 return STI.hasGloballyAddressableScratch()
20855 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
20868 bool HasSystemScope =
20902 if (!
IT ||
IT->getBitWidth() != 32)
20908 if (Subtarget->hasEmulatedSystemScopeAtomics())
20924 if (!HasSystemScope &&
20925 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
20937 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
20946 ConstVal && ConstVal->isNullValue() &&
20985 if (Ty->isFloatTy()) {
20990 if (Ty->isDoubleTy()) {
21011 if (Ty->isFloatTy() &&
21012 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
21025 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21029 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21033 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21038 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21043 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21047 if (Ty->isFloatTy()) {
21050 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21053 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21058 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21066 if (Subtarget->hasFlatAtomicFaddF32Inst())
21075 if (Subtarget->hasLDSFPAtomicAddF32()) {
21076 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21078 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21106 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21108 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21112 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21114 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21168 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21169 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21170 : &AMDGPU::SReg_32RegClass;
21171 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21172 return TRI->getEquivalentSGPRClass(RC);
21173 if (
TRI->isSGPRClass(RC) && isDivergent) {
21174 if (Subtarget->hasGFX90AInsts())
21175 return TRI->getEquivalentAVClass(RC);
21176 return TRI->getEquivalentVGPRClass(RC);
21189 unsigned WaveSize) {
21194 if (!
IT ||
IT->getBitWidth() != WaveSize)
21199 if (!Visited.
insert(V).second)
21201 bool Result =
false;
21202 for (
const auto *U : V->users()) {
21204 if (V == U->getOperand(1)) {
21209 case Intrinsic::amdgcn_if_break:
21210 case Intrinsic::amdgcn_if:
21211 case Intrinsic::amdgcn_else:
21216 if (V == U->getOperand(0)) {
21221 case Intrinsic::amdgcn_end_cf:
21222 case Intrinsic::amdgcn_loop:
21228 Result =
hasCFUser(U, Visited, WaveSize);
21237 const Value *V)
const {
21239 if (CI->isInlineAsm()) {
21248 for (
auto &TC : TargetConstraints) {
21262 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21297 if (
I.getMetadata(
"amdgpu.noclobber"))
21299 if (
I.getMetadata(
"amdgpu.last.use"))
21363 Alignment = RMW->getAlign();
21376 bool FullFlatEmulation =
21378 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21379 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21380 RMW->getType()->isDoubleTy()));
21383 bool ReturnValueIsUsed = !AI->
use_empty();
21392 if (FullFlatEmulation) {
21403 std::prev(BB->
end())->eraseFromParent();
21404 Builder.SetInsertPoint(BB);
21406 Value *LoadedShared =
nullptr;
21407 if (FullFlatEmulation) {
21408 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21409 {Addr},
nullptr,
"is.shared");
21410 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21411 Builder.SetInsertPoint(SharedBB);
21412 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21418 LoadedShared = Clone;
21420 Builder.CreateBr(PhiBB);
21421 Builder.SetInsertPoint(CheckPrivateBB);
21424 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21425 {Addr},
nullptr,
"is.private");
21426 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21428 Builder.SetInsertPoint(PrivateBB);
21430 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21433 Value *LoadedPrivate;
21435 LoadedPrivate = Builder.CreateAlignedLoad(
21436 RMW->getType(), CastToPrivate, RMW->getAlign(),
"loaded.private");
21439 LoadedPrivate, RMW->getValOperand());
21441 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign());
21443 auto [ResultLoad, Equal] =
21449 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21452 Builder.CreateBr(PhiBB);
21454 Builder.SetInsertPoint(GlobalBB);
21458 if (FullFlatEmulation) {
21459 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21468 if (!FullFlatEmulation) {
21473 MDNode *RangeNotPrivate =
21476 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21480 Builder.CreateBr(PhiBB);
21482 Builder.SetInsertPoint(PhiBB);
21484 if (ReturnValueIsUsed) {
21487 if (FullFlatEmulation)
21488 Loaded->addIncoming(LoadedShared, SharedBB);
21489 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21490 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21491 Loaded->takeName(AI);
21494 Builder.CreateBr(ExitBB);
21498 unsigned PtrOpIdx) {
21499 Value *PtrOp =
I->getOperand(PtrOpIdx);
21506 I->setOperand(PtrOpIdx, ASCast);
21518 ConstVal && ConstVal->isNullValue() &&
21549 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21557 "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 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 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 bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
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 OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW)
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 ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask=~0u, ArgDescriptor Arg=ArgDescriptor())
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::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 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 bool atomicIgnoresDenormalModeOrFPModeIsFTZ(const AtomicRMWInst *RMW)
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(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