46#include "llvm/IR/IntrinsicsAMDGPU.h"
47#include "llvm/IR/IntrinsicsR600.h"
60#define DEBUG_TYPE "si-lower"
66 cl::desc(
"Do not align and prefetch loops"),
70 "amdgpu-use-divergent-register-indexing",
cl::Hidden,
71 cl::desc(
"Use indirect register addressing for divergent indexes"),
89 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
90 for (
unsigned Reg = 0;
Reg < NumSGPRs; ++
Reg) {
92 return AMDGPU::SGPR0 +
Reg;
108 TRI->getDefaultVectorSuperClassForBitWidth(32);
114 TRI->getDefaultVectorSuperClassForBitWidth(64);
152 TRI->getDefaultVectorSuperClassForBitWidth(320));
156 TRI->getDefaultVectorSuperClassForBitWidth(352));
160 TRI->getDefaultVectorSuperClassForBitWidth(384));
164 TRI->getDefaultVectorSuperClassForBitWidth(512));
171 TRI->getDefaultVectorSuperClassForBitWidth(1024));
173 if (Subtarget->has16BitInsts()) {
174 if (Subtarget->useRealTrue16Insts()) {
204 TRI->getDefaultVectorSuperClassForBitWidth(1024));
220 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
221 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
222 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
223 MVT::i1, MVT::v32i32},
227 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
228 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
229 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
230 MVT::i1, MVT::v32i32},
248 if (Subtarget->hasBF16PackedInsts()) {
312 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1},
Expand);
319 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
320 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
321 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
324 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
325 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
326 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
330 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
331 MVT::v3i16, MVT::v4i16, MVT::Other},
336 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64},
Expand);
352 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
353 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
354 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
355 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
356 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
357 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
358 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
359 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
392 for (
MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
406 for (
MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
420 for (
MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
434 for (
MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
448 for (
MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
463 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
464 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
467 if (Subtarget->hasPkMovB32()) {
488 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
489 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
494 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32},
Custom);
498 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
499 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
500 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
501 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
525 if (Subtarget->hasSMemRealTime() ||
530 if (Subtarget->has16BitInsts()) {
540 if (Subtarget->hasMadMacF32Insts())
558 if (Subtarget->hasIntClamp())
561 if (Subtarget->hasAddNoCarryInsts())
567 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
570 {MVT::f64, MVT::f32},
Legal);
574 {MVT::f64, MVT::f32},
Custom);
579 {MVT::f64, MVT::f32},
Legal);
582 if (Subtarget->haveRoundOpsF64())
612 if (Subtarget->has16BitInsts()) {
666 if (Subtarget->hasBF16TransInsts())
682 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
683 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
684 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
717 if (Subtarget->hasVCvtPkIU16F32())
720 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
727 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Legal);
847 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
848 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
849 MVT::v32f16, MVT::v32bf16},
851 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
858 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
Custom);
869 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
873 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
878 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
879 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
887 if (Subtarget->hasVOP3PInsts()) {
898 {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
Custom);
901 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
902 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
903 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
906 for (
MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
914 for (
MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
920 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
930 {MVT::v2f16, MVT::v4f16},
Custom);
936 if (Subtarget->hasBF16PackedInsts()) {
942 for (
MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
950 if (Subtarget->hasAnyPackedFP32Ops()) {
954 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
957 if (Subtarget->hasAnyPackedFP64Ops()) {
963 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
965 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
972 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
Custom);
981 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
986 if (Subtarget->hasAnyPackedU64Ops()) {
990 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
997 if (Subtarget->has16BitInsts()) {
1012 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1013 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1014 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1015 MVT::v32f16, MVT::v32bf16},
1020 if (Subtarget->useVMulU64Inst())
1022 else if (Subtarget->hasScalarSMulU64())
1025 if (Subtarget->hasMad64_32())
1028 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1031 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1033 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16},
Legal);
1036 if (Subtarget->hasMinimum3Maximum3F32())
1039 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1043 if (!Subtarget->hasMinimum3Maximum3F16())
1049 if (Subtarget->hasVOP3PInsts()) {
1052 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1056 if (Subtarget->useMinMaxI64Insts())
1061 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1062 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1067 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1068 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1069 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1070 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1085 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1090 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1091 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1092 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1093 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1108 if (Subtarget->hasBF16ConversionInsts()) {
1110 {MVT::bf16, MVT::v2bf16},
Custom);
1114 if (Subtarget->hasBF16TransInsts()) {
1118 const bool HasE5M3ConversionInsts =
1119 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1120 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1131 if (Subtarget->hasFP8F16ConversionInsts()) {
1136 if (Subtarget->hasCvtPkF16F32Inst()) {
1138 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1190 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1231 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1244 EVT DestVT,
EVT SrcVT)
const {
1246 ((((Opcode ==
ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1247 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1249 (Opcode ==
ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1256 LLT DestTy,
LLT SrcTy)
const {
1257 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1258 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1260 SrcTy.getScalarSizeInBits() == 16 &&
1281 return Subtarget->has16BitInsts()
1287 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1291 if (!Subtarget->has16BitInsts() && VT.
getSizeInBits() == 16)
1313 return (NumElts + 1) / 2;
1319 return NumElts * ((
Size + 31) / 32);
1328 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
1337 MVT SimpleIntermediateVT =
1339 IntermediateVT = SimpleIntermediateVT;
1340 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1341 NumIntermediates = (NumElts + 1) / 2;
1342 return (NumElts + 1) / 2;
1347 IntermediateVT = RegisterVT;
1348 NumIntermediates = NumElts;
1349 return NumIntermediates;
1354 RegisterVT = MVT::i16;
1355 IntermediateVT = ScalarVT;
1356 NumIntermediates = NumElts;
1357 return NumIntermediates;
1361 RegisterVT = MVT::i32;
1362 IntermediateVT = ScalarVT;
1363 NumIntermediates = NumElts;
1364 return NumIntermediates;
1368 RegisterVT = MVT::i32;
1369 IntermediateVT = RegisterVT;
1370 NumIntermediates = NumElts * ((
Size + 31) / 32);
1371 return NumIntermediates;
1376 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1381 unsigned MaxNumLanes) {
1382 assert(MaxNumLanes != 0);
1386 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1397 unsigned MaxNumLanes) {
1403 assert(ST->getNumContainedTypes() == 2 &&
1404 ST->getContainedType(1)->isIntegerTy(32));
1418 return MVT::amdgpuBufferFatPointer;
1420 DL.getPointerSizeInBits(AS) == 192)
1421 return MVT::amdgpuBufferStridedPointer;
1430 DL.getPointerSizeInBits(AS) == 160) ||
1432 DL.getPointerSizeInBits(AS) == 192))
1439 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1440 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1441 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1443 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1444 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1445 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1446 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1447 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1448 case Intrinsic::amdgcn_flat_load_monitor_b32:
1449 case Intrinsic::amdgcn_global_load_monitor_b32:
1451 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1452 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1453 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1454 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1455 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1456 case Intrinsic::amdgcn_flat_load_monitor_b64:
1457 case Intrinsic::amdgcn_global_load_monitor_b64:
1459 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1460 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1461 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1462 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1463 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1464 case Intrinsic::amdgcn_flat_load_monitor_b128:
1465 case Intrinsic::amdgcn_global_load_monitor_b128:
1501 unsigned IntrID)
const {
1503 if (CI.
hasMetadata(LLVMContext::MD_invariant_load))
1517 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1531 if (RsrcIntr->IsImage) {
1546 Info.ptrVal = RsrcArg;
1550 if (RsrcIntr->IsImage) {
1551 unsigned MaxNumLanes = 4;
1566 std::numeric_limits<unsigned>::max());
1576 if (RsrcIntr->IsImage) {
1596 if ((RsrcIntr->IsImage && BaseOpcode->
NoReturn) || IsSPrefetch) {
1598 Info.memVT = MVT::i32;
1605 case Intrinsic::amdgcn_raw_buffer_load_lds:
1606 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1607 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1608 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1609 case Intrinsic::amdgcn_struct_buffer_load_lds:
1610 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1611 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1612 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1626 CI.
getContext(), Width * 8 * Subtarget->getWavefrontSize());
1635 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1636 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1637 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1638 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1641 std::numeric_limits<unsigned>::max());
1654 case Intrinsic::amdgcn_ds_ordered_add:
1655 case Intrinsic::amdgcn_ds_ordered_swap: {
1669 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1670 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1673 Info.ptrVal =
nullptr;
1679 case Intrinsic::amdgcn_ds_append:
1680 case Intrinsic::amdgcn_ds_consume: {
1694 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1695 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1696 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1701 Info.memVT = MVT::i64;
1709 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1710 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1711 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1714 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1717 ->getElementType(0));
1726 case Intrinsic::amdgcn_global_atomic_fmin_num:
1727 case Intrinsic::amdgcn_global_atomic_fmax_num:
1728 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1729 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1730 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1741 case Intrinsic::amdgcn_cluster_load_b32:
1742 case Intrinsic::amdgcn_cluster_load_b64:
1743 case Intrinsic::amdgcn_cluster_load_b128:
1744 case Intrinsic::amdgcn_ds_load_tr6_b96:
1745 case Intrinsic::amdgcn_ds_load_tr4_b64:
1746 case Intrinsic::amdgcn_ds_load_tr8_b64:
1747 case Intrinsic::amdgcn_ds_load_tr16_b128:
1748 case Intrinsic::amdgcn_global_load_tr6_b96:
1749 case Intrinsic::amdgcn_global_load_tr4_b64:
1750 case Intrinsic::amdgcn_global_load_tr_b64:
1751 case Intrinsic::amdgcn_global_load_tr_b128:
1752 case Intrinsic::amdgcn_ds_read_tr4_b64:
1753 case Intrinsic::amdgcn_ds_read_tr6_b96:
1754 case Intrinsic::amdgcn_ds_read_tr8_b64:
1755 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1764 case Intrinsic::amdgcn_flat_load_monitor_b32:
1765 case Intrinsic::amdgcn_flat_load_monitor_b64:
1766 case Intrinsic::amdgcn_flat_load_monitor_b128:
1767 case Intrinsic::amdgcn_global_load_monitor_b32:
1768 case Intrinsic::amdgcn_global_load_monitor_b64:
1769 case Intrinsic::amdgcn_global_load_monitor_b128: {
1780 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1781 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1782 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1793 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1794 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1795 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1806 case Intrinsic::amdgcn_ds_gws_init:
1807 case Intrinsic::amdgcn_ds_gws_barrier:
1808 case Intrinsic::amdgcn_ds_gws_sema_v:
1809 case Intrinsic::amdgcn_ds_gws_sema_br:
1810 case Intrinsic::amdgcn_ds_gws_sema_p:
1811 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1821 Info.memVT = MVT::i32;
1823 Info.align =
Align(4);
1825 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1832 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1833 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1834 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1835 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1836 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1837 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1838 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1839 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1854 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1855 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1856 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1857 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1872 case Intrinsic::amdgcn_av_load_b128:
1873 case Intrinsic::amdgcn_av_store_b128: {
1874 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1876 Info.memVT = MVT::v4i32;
1878 Info.align =
Align(16);
1886 unsigned ScopeIdx = CI.
arg_size() - 1;
1890 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1894 case Intrinsic::amdgcn_load_to_lds:
1895 case Intrinsic::amdgcn_load_async_to_lds:
1896 case Intrinsic::amdgcn_global_load_lds:
1897 case Intrinsic::amdgcn_global_load_async_lds: {
1916 Width * 8 * Subtarget->getWavefrontSize());
1922 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1923 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1924 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1925 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1935 Info.memVT = MVT::i32;
1937 Info.align =
Align(4);
1943 case Intrinsic::amdgcn_s_prefetch_data:
1944 case Intrinsic::amdgcn_s_prefetch_inst:
1945 case Intrinsic::amdgcn_flat_prefetch:
1946 case Intrinsic::amdgcn_global_prefetch: {
1961 Type *&AccessTy)
const {
1962 Value *Ptr =
nullptr;
1963 switch (
II->getIntrinsicID()) {
1964 case Intrinsic::amdgcn_cluster_load_b128:
1965 case Intrinsic::amdgcn_cluster_load_b64:
1966 case Intrinsic::amdgcn_cluster_load_b32:
1967 case Intrinsic::amdgcn_ds_append:
1968 case Intrinsic::amdgcn_ds_consume:
1969 case Intrinsic::amdgcn_ds_load_tr8_b64:
1970 case Intrinsic::amdgcn_ds_load_tr16_b128:
1971 case Intrinsic::amdgcn_ds_load_tr4_b64:
1972 case Intrinsic::amdgcn_ds_load_tr6_b96:
1973 case Intrinsic::amdgcn_ds_read_tr4_b64:
1974 case Intrinsic::amdgcn_ds_read_tr6_b96:
1975 case Intrinsic::amdgcn_ds_read_tr8_b64:
1976 case Intrinsic::amdgcn_ds_read_tr16_b64:
1977 case Intrinsic::amdgcn_ds_ordered_add:
1978 case Intrinsic::amdgcn_ds_ordered_swap:
1979 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1980 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1981 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1982 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1983 case Intrinsic::amdgcn_global_atomic_fmax_num:
1984 case Intrinsic::amdgcn_global_atomic_fmin_num:
1985 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1986 case Intrinsic::amdgcn_global_load_tr_b64:
1987 case Intrinsic::amdgcn_global_load_tr_b128:
1988 case Intrinsic::amdgcn_global_load_tr4_b64:
1989 case Intrinsic::amdgcn_global_load_tr6_b96:
1990 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1991 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1992 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1993 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1994 case Intrinsic::amdgcn_av_load_b128:
1995 case Intrinsic::amdgcn_av_store_b128:
1996 Ptr =
II->getArgOperand(0);
1998 case Intrinsic::amdgcn_load_to_lds:
1999 case Intrinsic::amdgcn_load_async_to_lds:
2000 case Intrinsic::amdgcn_global_load_lds:
2001 case Intrinsic::amdgcn_global_load_async_lds:
2002 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2003 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2004 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2005 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2006 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2007 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2008 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2009 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2010 Ptr =
II->getArgOperand(1);
2015 AccessTy =
II->getType();
2021 unsigned AddrSpace)
const {
2022 if (!Subtarget->hasFlatInstOffsets()) {
2029 FlatAddrSpace FlatVariant =
2032 : FlatAddrSpace::FLAT;
2034 return AM.
Scale == 0 &&
2035 (AM.
BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2036 AM.
BaseOffs, AddrSpace, FlatVariant));
2040 if (Subtarget->hasFlatGlobalInsts())
2043 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2056 return isLegalMUBUFAddressingMode(AM);
2059bool SITargetLowering::isLegalMUBUFAddressingMode(
const AddrMode &AM)
const {
2070 if (!
TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2082 if (AM.HasBaseReg) {
2114 return isLegalMUBUFAddressingMode(AM);
2116 if (!Subtarget->hasScalarSubwordLoads()) {
2121 if (Ty->isSized() &&
DL.getTypeStoreSize(Ty) < 4)
2169 return Subtarget->hasFlatScratchEnabled()
2171 : isLegalMUBUFAddressingMode(AM);
2218 unsigned Size,
unsigned AddrSpace,
Align Alignment,
2227 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment <
Align(4))
2230 Align RequiredAlignment(
2232 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
Size > 32 &&
2233 Alignment < RequiredAlignment)
2248 if (!Subtarget->hasUsableDSOffset() && Alignment <
Align(8))
2254 RequiredAlignment =
Align(4);
2256 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2272 *IsFast = (Alignment >= RequiredAlignment) ? 64
2273 : (Alignment <
Align(4)) ? 32
2280 if (!Subtarget->hasDS96AndDS128())
2286 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2295 *IsFast = (Alignment >= RequiredAlignment) ? 96
2296 : (Alignment <
Align(4)) ? 32
2303 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2309 RequiredAlignment =
Align(8);
2311 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2320 *IsFast = (Alignment >= RequiredAlignment) ? 128
2321 : (Alignment <
Align(4)) ? 32
2338 *IsFast = (Alignment >= RequiredAlignment) ?
Size : 0;
2340 return Alignment >= RequiredAlignment ||
2341 Subtarget->hasUnalignedDSAccessEnabled();
2349 bool AlignedBy4 = Alignment >=
Align(4);
2350 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2352 *IsFast = AlignedBy4 ?
Size : 1;
2357 *IsFast = AlignedBy4;
2368 return Alignment >=
Align(4) ||
2369 Subtarget->hasUnalignedBufferAccessEnabled();
2382 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2397 return Size >= 32 && Alignment >=
Align(4);
2402 unsigned *IsFast)
const {
2404 Alignment, Flags, IsFast);
2415 if (
Op.size() >= 16 &&
2419 if (
Op.size() >= 8 &&
Op.isDstAligned(
Align(4)))
2437 unsigned DestAS)
const {
2440 Subtarget->hasGloballyAddressableScratch()) {
2471 unsigned Index)
const {
2485 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2490 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2525 auto [InputPtrReg, RC, ArgTy] =
2541 const SDLoc &SL)
const {
2548 const SDLoc &SL)
const {
2551 std::optional<uint32_t> KnownSize =
2553 if (KnownSize.has_value())
2580 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2595SDValue SITargetLowering::lowerKernargMemParameter(
2600 MachinePointerInfo PtrInfo =
2609 int64_t OffsetDiff =
Offset - AlignDownOffset;
2615 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2616 SDValue
Load = DAG.
getLoad(MVT::i32, SL, Chain, Ptr,
2621 SDValue ShiftAmt = DAG.
getConstant(OffsetDiff * 8, SL, MVT::i32);
2626 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal,
Signed, Arg);
2631 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain,
Offset);
2636 SDValue Val = convertArgType(DAG, VT, MemVT, SL,
Load,
Signed, Arg);
2645 const SDLoc &SL)
const {
2714 ExtType, SL, VA.
getLocVT(), Chain, FIN,
2717 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2718 if (ConvertedVal == ArgValue)
2719 return ConvertedVal;
2724SDValue SITargetLowering::lowerWorkGroupId(
2729 if (!Subtarget->hasClusters())
2730 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2738 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2739 SDLoc SL(ClusterIdXYZ);
2740 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2742 SDValue ClusterSizeXYZ = DAG.
getNode(
ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2743 SDValue ClusterWorkGroupIdXYZ =
2744 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2745 SDValue GlobalIdXYZ =
2754 return ClusterIdXYZ;
2756 using namespace AMDGPU::Hwreg;
2757 SDValue ClusterIdField =
2760 DAG.
getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2761 SDValue ClusterId(GetReg, 0);
2771SDValue SITargetLowering::getPreloadedValue(
2774 const ArgDescriptor *
Reg =
nullptr;
2779 const ArgDescriptor WorkGroupIDX =
2787 const ArgDescriptor WorkGroupIDZ =
2789 const ArgDescriptor ClusterWorkGroupIDX =
2791 const ArgDescriptor ClusterWorkGroupIDY =
2793 const ArgDescriptor ClusterWorkGroupIDZ =
2795 const ArgDescriptor ClusterWorkGroupMaxIDX =
2797 const ArgDescriptor ClusterWorkGroupMaxIDY =
2799 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2801 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2804 auto LoadConstant = [&](
unsigned N) {
2808 if (Subtarget->hasArchitectedSGPRs() &&
2815 Reg = &WorkGroupIDX;
2816 RC = &AMDGPU::SReg_32RegClass;
2820 Reg = &WorkGroupIDY;
2821 RC = &AMDGPU::SReg_32RegClass;
2825 Reg = &WorkGroupIDZ;
2826 RC = &AMDGPU::SReg_32RegClass;
2830 if (HasFixedDims && ClusterDims.
getDims()[0] == 1)
2831 return LoadConstant(0);
2832 Reg = &ClusterWorkGroupIDX;
2833 RC = &AMDGPU::SReg_32RegClass;
2837 if (HasFixedDims && ClusterDims.
getDims()[1] == 1)
2838 return LoadConstant(0);
2839 Reg = &ClusterWorkGroupIDY;
2840 RC = &AMDGPU::SReg_32RegClass;
2844 if (HasFixedDims && ClusterDims.
getDims()[2] == 1)
2845 return LoadConstant(0);
2846 Reg = &ClusterWorkGroupIDZ;
2847 RC = &AMDGPU::SReg_32RegClass;
2852 return LoadConstant(ClusterDims.
getDims()[0] - 1);
2853 Reg = &ClusterWorkGroupMaxIDX;
2854 RC = &AMDGPU::SReg_32RegClass;
2859 return LoadConstant(ClusterDims.
getDims()[1] - 1);
2860 Reg = &ClusterWorkGroupMaxIDY;
2861 RC = &AMDGPU::SReg_32RegClass;
2866 return LoadConstant(ClusterDims.
getDims()[2] - 1);
2867 Reg = &ClusterWorkGroupMaxIDZ;
2868 RC = &AMDGPU::SReg_32RegClass;
2872 Reg = &ClusterWorkGroupMaxFlatID;
2873 RC = &AMDGPU::SReg_32RegClass;
2904 for (
unsigned I = 0,
E = Ins.
size(), PSInputNum = 0;
I !=
E; ++
I) {
2908 "vector type argument should have been split");
2913 bool SkipArg = !Arg->
Used && !Info->isPSInputAllocated(PSInputNum);
2921 "unexpected vector split in ps argument type");
2935 Info->markPSInputAllocated(PSInputNum);
2937 Info->markPSInputEnabled(PSInputNum);
2953 if (Info.hasWorkItemIDX()) {
2959 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2963 if (Info.hasWorkItemIDY()) {
2964 assert(Info.hasWorkItemIDX());
2965 if (Subtarget->hasPackedTID()) {
2966 Info.setWorkItemIDY(
2969 unsigned Reg = AMDGPU::VGPR1;
2977 if (Info.hasWorkItemIDZ()) {
2978 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2979 if (Subtarget->hasPackedTID()) {
2980 Info.setWorkItemIDZ(
2983 unsigned Reg = AMDGPU::VGPR2;
3003 if (RegIdx == ArgVGPRs.
size()) {
3010 unsigned Reg = ArgVGPRs[RegIdx];
3022 unsigned NumArgRegs) {
3025 if (RegIdx == ArgSGPRs.
size())
3028 unsigned Reg = ArgSGPRs[RegIdx];
3070 const unsigned Mask = 0x3ff;
3073 if (Info.hasWorkItemIDX()) {
3075 Info.setWorkItemIDX(Arg);
3078 if (Info.hasWorkItemIDY()) {
3080 Info.setWorkItemIDY(Arg);
3083 if (Info.hasWorkItemIDZ())
3095 const unsigned Mask = 0x3ff;
3104 auto &
ArgInfo = Info.getArgInfo();
3116 if (Info.hasImplicitArgPtr())
3124 if (Info.hasWorkGroupIDX())
3127 if (Info.hasWorkGroupIDY())
3130 if (Info.hasWorkGroupIDZ())
3133 if (Info.hasLDSKernelId())
3144 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(
TRI);
3145 MF.
addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3151 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(
TRI);
3152 MF.
addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3157 Register DispatchPtrReg = Info.addDispatchPtr(
TRI);
3158 MF.
addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3164 MF.
addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3170 Register InputPtrReg = Info.addKernargSegmentPtr(
TRI);
3179 MF.
addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3184 Register FlatScratchInitReg = Info.addFlatScratchInit(
TRI);
3185 MF.
addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3190 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(
TRI);
3191 MF.
addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3206 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3208 bool InPreloadSequence =
true;
3210 bool AlignedForImplictArgs =
false;
3211 unsigned ImplicitArgOffset = 0;
3212 for (
auto &Arg :
F.args()) {
3213 if (!InPreloadSequence || !Arg.hasInRegAttr())
3216 unsigned ArgIdx = Arg.getArgNo();
3219 if (InIdx < Ins.
size() &&
3220 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3223 for (; InIdx < Ins.
size() && Ins[InIdx].isOrigArg() &&
3224 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3226 assert(ArgLocs[ArgIdx].isMemLoc());
3227 auto &ArgLoc = ArgLocs[InIdx];
3229 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3231 unsigned NumAllocSGPRs =
3232 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3235 if (Arg.hasAttribute(
"amdgpu-hidden-argument")) {
3236 if (!AlignedForImplictArgs) {
3238 alignTo(LastExplicitArgOffset,
3239 Subtarget->getAlignmentForImplicitArgPtr()) -
3240 LastExplicitArgOffset;
3241 AlignedForImplictArgs =
true;
3243 ArgOffset += ImplicitArgOffset;
3247 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3248 assert(InIdx >= 1 &&
"No previous SGPR");
3249 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3250 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3254 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3255 unsigned PaddingSGPRs =
alignTo(Padding, 4) / 4;
3258 InPreloadSequence =
false;
3264 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3266 Info.addPreloadedKernArg(
TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3268 if (PreloadRegs->
size() > 1)
3269 RC = &AMDGPU::SGPR_32RegClass;
3270 for (
auto &Reg : *PreloadRegs) {
3276 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3285 if (Info.hasLDSKernelId()) {
3286 Register Reg = Info.addLDSKernelId();
3287 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3296 bool IsShader)
const {
3297 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3298 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3304 assert(!HasArchitectedSGPRs &&
"Unhandled feature for the subtarget");
3306 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3310 unsigned NumRequiredSystemSGPRs =
3311 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3312 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3313 for (
unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3314 Register Reg = Info.addReservedUserSGPR();
3315 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3320 if (!HasArchitectedSGPRs) {
3321 if (Info.hasWorkGroupIDX()) {
3322 Register Reg = Info.addWorkGroupIDX();
3323 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3327 if (Info.hasWorkGroupIDY()) {
3328 Register Reg = Info.addWorkGroupIDY();
3329 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3333 if (Info.hasWorkGroupIDZ()) {
3334 Register Reg = Info.addWorkGroupIDZ();
3335 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3340 if (Info.hasWorkGroupInfo()) {
3341 Register Reg = Info.addWorkGroupInfo();
3342 MF.
addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3346 if (Info.hasPrivateSegmentWaveByteOffset()) {
3348 unsigned PrivateSegmentWaveByteOffsetReg;
3351 PrivateSegmentWaveByteOffsetReg =
3352 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3356 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3358 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3361 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3363 MF.
addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3364 CCInfo.
AllocateReg(PrivateSegmentWaveByteOffsetReg);
3367 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3368 Info.getNumPreloadedSGPRs() >= 16);
3383 if (HasStackObjects)
3384 Info.setHasNonSpillStackObjects(
true);
3389 HasStackObjects =
true;
3393 bool RequiresStackAccess = HasStackObjects || MFI.
hasCalls();
3395 if (!ST.hasFlatScratchEnabled()) {
3396 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.
getFunction())) {
3403 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3405 unsigned ReservedBufferReg =
TRI.reservedPrivateSegmentBufferReg(MF);
3415 Info.setScratchRSrcReg(ReservedBufferReg);
3434 if (!MRI.
isLiveIn(AMDGPU::SGPR32)) {
3435 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3442 for (
unsigned Reg : AMDGPU::SGPR_32RegClass) {
3444 Info.setStackPtrOffsetReg(
Reg);
3449 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3456 if (ST.getFrameLowering()->hasFP(MF)) {
3457 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3473 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3482 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3483 RC = &AMDGPU::SGPR_64RegClass;
3484 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3485 RC = &AMDGPU::SGPR_32RegClass;
3491 Entry->addLiveIn(*
I);
3496 for (
auto *Exit : Exits)
3498 TII->get(TargetOpcode::COPY), *
I)
3513 bool IsError =
false;
3517 Fn,
"unsupported non-compute shaders with HSA",
DL.getDebugLoc()));
3535 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3536 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3538 if (!Subtarget->hasFlatScratchEnabled())
3543 !Subtarget->hasArchitectedSGPRs())
3544 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3545 !Info->hasWorkGroupIDZ());
3548 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3566 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3567 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3570 Info->markPSInputAllocated(0);
3571 Info->markPSInputEnabled(0);
3573 if (Subtarget->isAmdPalOS()) {
3582 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3583 if ((PsInputBits & 0x7F) == 0 ||
3584 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3587 }
else if (IsKernel) {
3588 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3600 if (IsKernel && Subtarget->hasKernargPreload())
3604 }
else if (!IsGraphics) {
3609 if (!Subtarget->hasFlatScratchEnabled())
3621 Info->setNumWaveDispatchSGPRs(
3623 Info->setNumWaveDispatchVGPRs(
3625 }
else if (Info->getNumKernargPreloadedSGPRs()) {
3626 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3631 if (IsWholeWaveFunc) {
3633 {MVT::i1, MVT::Other}, Chain);
3645 for (
unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.
size(), ArgIdx = 0; i != e;
3656 if (IsEntryFunc && VA.
isMemLoc()) {
3679 if (Arg.
isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3683 int64_t OffsetDiff =
Offset - AlignDownOffset;
3690 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3693 Register VReg = MRI.getLiveInVirtReg(Reg);
3701 NewArg = convertArgType(DAG, VT, MemVT,
DL, ArgVal,
3702 Ins[i].Flags.isSExt(), &Ins[i]);
3710 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3713 if (PreloadRegs.
size() == 1) {
3714 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3719 TRI->getRegSizeInBits(*RC)));
3727 for (
auto Reg : PreloadRegs) {
3728 Register VReg = MRI.getLiveInVirtReg(Reg);
3734 PreloadRegs.size()),
3751 NewArg = convertArgType(DAG, VT, MemVT,
DL, NewArg,
3752 Ins[i].Flags.isSExt(), &Ins[i]);
3764 "hidden argument in kernel signature was not preloaded",
3770 lowerKernargMemParameter(DAG, VT, MemVT,
DL, Chain,
Offset,
3771 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3791 if (!IsEntryFunc && VA.
isMemLoc()) {
3792 SDValue Val = lowerStackParameter(DAG, VA,
DL, Chain, Arg);
3803 if (AMDGPU::VGPR_32RegClass.
contains(Reg))
3804 RC = &AMDGPU::VGPR_32RegClass;
3805 else if (AMDGPU::SGPR_32RegClass.
contains(Reg))
3806 RC = &AMDGPU::SGPR_32RegClass;
3812 if (Arg.
Flags.
isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3818 ReadFirstLane, Val);
3827 Val = convertABITypeToValueType(DAG, Val, VA,
DL);
3836 Info->setBytesInStackArgArea(StackArgSize);
3838 return Chains.
empty() ? Chain
3847 const Type *RetTy)
const {
3855 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3860 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3861 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3862 for (
unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3863 if (CCInfo.
isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3886 Info->setIfReturnsVoid(Outs.
empty());
3887 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3906 for (
unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.
size();
I != E;
3907 ++
I, ++RealRVLocIdx) {
3911 SDValue Arg = OutVals[RealRVLocIdx];
3934 ReadFirstLane, Arg);
3941 if (!Info->isEntryFunction()) {
3947 if (AMDGPU::SReg_64RegClass.
contains(*
I))
3949 else if (AMDGPU::SReg_32RegClass.
contains(*
I))
3962 unsigned Opc = AMDGPUISD::ENDPGM;
3964 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3965 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3966 : AMDGPUISD::RET_GLUE;
4071 const auto [OutgoingArg, ArgRC, ArgTy] =
4076 const auto [IncomingArg, IncomingArgRC, Ty] =
4078 assert(IncomingArgRC == ArgRC);
4081 EVT ArgVT =
TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4089 InputReg = getImplicitArgPtr(DAG,
DL);
4091 std::optional<uint32_t> Id =
4093 if (Id.has_value()) {
4104 if (OutgoingArg->isRegister()) {
4105 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4106 if (!CCInfo.
AllocateReg(OutgoingArg->getRegister()))
4109 unsigned SpecialArgOffset =
4120 auto [OutgoingArg, ArgRC, Ty] =
4123 std::tie(OutgoingArg, ArgRC, Ty) =
4126 std::tie(OutgoingArg, ArgRC, Ty) =
4141 const bool NeedWorkItemIDX = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-x");
4142 const bool NeedWorkItemIDY = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-y");
4143 const bool NeedWorkItemIDZ = !CLI.
CB->
hasFnAttr(
"amdgpu-no-workitem-id-z");
4148 if (Subtarget->getMaxWorkitemID(
F, 0) != 0) {
4156 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(
F, 1) != 0) {
4166 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(
F, 2) != 0) {
4175 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4176 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4187 : IncomingArgY ? *IncomingArgY
4194 if (OutgoingArg->isRegister()) {
4196 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4222 if (Callee->isDivergent())
4229 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
4233 if (!CallerPreserved)
4236 bool CCMatch = CallerCC == CalleeCC;
4249 if (Arg.hasByValAttr())
4263 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
4264 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4273 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4286 for (
const auto &[CCVA, ArgVal] :
zip_equal(ArgLocs, OutVals)) {
4288 if (!CCVA.isRegLoc())
4293 if (ArgVal->
isDivergent() &&
TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4295 dbgs() <<
"Cannot tail call due to divergent outgoing argument in "
4319enum ChainCallArgIdx {
4341 bool UsesDynamicVGPRs =
false;
4342 if (IsChainCallConv) {
4347 auto RequestedExecIt =
4349 return Arg.OrigArgIndex == 2;
4351 assert(RequestedExecIt != CLI.
Outs.end() &&
"No node for EXEC");
4353 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.
Outs.begin();
4356 CLI.
Outs.erase(RequestedExecIt, CLI.
Outs.end());
4359 "Haven't popped all the special args");
4362 CLI.
Args[ChainCallArgIdx::Exec];
4363 if (!RequestedExecArg.
Ty->
isIntegerTy(Subtarget->getWavefrontSize()))
4371 ArgNode->getAPIntValue(),
DL, ArgNode->getValueType(0)));
4373 ChainCallSpecialArgs.
push_back(Arg.Node);
4376 PushNodeOrTargetConstant(RequestedExecArg);
4382 if (FlagsValue.
isZero()) {
4383 if (CLI.
Args.size() > ChainCallArgIdx::Flags + 1)
4385 "no additional args allowed if flags == 0");
4387 if (CLI.
Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4391 if (!Subtarget->isWave32()) {
4393 CLI, InVals,
"dynamic VGPR mode is only supported for wave32");
4396 UsesDynamicVGPRs =
true;
4397 std::for_each(CLI.
Args.begin() + ChainCallArgIdx::NumVGPRs,
4398 CLI.
Args.end(), PushNodeOrTargetConstant);
4407 bool IsSibCall =
false;
4421 "unsupported call to variadic function ");
4429 "unsupported required tail call to function ");
4434 Outs, OutVals, Ins, DAG);
4438 "site marked musttail or on llvm.amdgcn.cs.chain");
4445 if (!TailCallOpt && IsTailCall)
4469 if (!Subtarget->hasFlatScratchEnabled())
4490 auto *
TRI = Subtarget->getRegisterInfo();
4497 if (!IsSibCall || IsChainCallConv) {
4498 if (!Subtarget->hasFlatScratchEnabled()) {
4504 RegsToPass.emplace_back(IsChainCallConv
4505 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4506 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4513 const unsigned NumSpecialInputs = RegsToPass.size();
4515 MVT PtrVT = MVT::i32;
4518 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
4546 RegsToPass.push_back(std::pair(VA.
getLocReg(), Arg));
4554 int32_t
Offset = LocMemOffset;
4561 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4567 ? Flags.getNonZeroByValAlign()
4594 if (Outs[i].Flags.isByVal()) {
4596 DAG.
getConstant(Outs[i].Flags.getByValSize(),
DL, MVT::i32);
4599 Outs[i].Flags.getNonZeroByValAlign(),
4600 Outs[i].Flags.getNonZeroByValAlign(),
4602 nullptr, std::nullopt, DstInfo,
4608 DAG.
getStore(Chain,
DL, Arg, DstAddr, DstInfo, Alignment);
4614 if (!MemOpChains.
empty())
4630 unsigned ArgIdx = 0;
4631 for (
auto [Reg, Val] : RegsToPass) {
4632 if (ArgIdx++ >= NumSpecialInputs &&
4633 (IsChainCallConv || !Val->
isDivergent()) &&
TRI->isSGPRPhysReg(Reg)) {
4659 if (IsTailCall && !IsSibCall) {
4664 std::vector<SDValue>
Ops({Chain});
4670 Ops.push_back(Callee);
4687 Ops.push_back(Callee);
4698 if (IsChainCallConv)
4703 for (
auto &[Reg, Val] : RegsToPass)
4707 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
4708 assert(Mask &&
"Missing call preserved mask for calling convention");
4718 MVT::Glue, GlueOps),
4723 Ops.push_back(InGlue);
4729 unsigned OPC = AMDGPUISD::TC_RETURN;
4732 OPC = AMDGPUISD::TC_RETURN_GFX;
4736 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4737 : AMDGPUISD::TC_RETURN_CHAIN;
4743 if (Info->isWholeWaveFunction())
4744 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4751 Chain =
Call.getValue(0);
4752 InGlue =
Call.getValue(1);
4754 uint64_t CalleePopBytes = NumBytes;
4775 EVT VT =
Op.getValueType();
4789 "Stack grows upwards for AMDGPU");
4791 Chain = BaseAddr.getValue(1);
4793 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4794 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4797 if (Alignment > StackAlign) {
4798 uint64_t ScaledAlignment = Alignment.value()
4799 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4800 uint64_t StackAlignMask = ScaledAlignment - 1;
4807 assert(
Size.getValueType() == MVT::i32 &&
"Size must be 32-bit");
4816 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4827 if (!HasFlatScratch) {
4830 DAG.
getConstant(WavefrontSizeLog2, dl, MVT::i32));
4847 if (
Op.getValueType() != MVT::i32)
4866 assert(
Op.getValueType() == MVT::i32);
4875 Op.getOperand(0), IntrinID, GetRoundBothImm);
4909 SDValue RoundModeTimesNumBits =
4929 TableEntry, EnumOffset);
4945 static_cast<uint32_t>(ConstMode->getZExtValue()),
4957 if (UseReducedTable) {
4963 SDValue RoundModeTimesNumBits =
4983 SDValue RoundModeTimesNumBits =
4992 NewMode = TruncTable;
5001 ReadFirstLaneID, NewMode);
5014 IntrinID, RoundBothImm, NewMode);
5020 if (
Op->isDivergent() &&
5021 (!Subtarget->hasVmemPrefInsts() || !
Op.getConstantOperandVal(4)))
5031 if (Subtarget->hasSafeSmemPrefetch())
5039 if (!Subtarget->hasSafeSmemPrefetch() && !
Op.getConstantOperandVal(4))
5048 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
5049 EVT SrcVT = Src.getValueType();
5058 EVT DstVT =
Op.getValueType();
5067 if (
Op.getValueType() != MVT::i64)
5081 Op.getOperand(0), IntrinID, ModeHwRegImm);
5083 Op.getOperand(0), IntrinID, TrapHwRegImm);
5097 if (
Op.getOperand(1).getValueType() != MVT::i64)
5109 ReadFirstLaneID, NewModeReg);
5111 ReadFirstLaneID, NewTrapReg);
5113 unsigned ModeHwReg =
5116 unsigned TrapHwReg =
5124 IntrinID, ModeHwRegImm, NewModeReg);
5127 IntrinID, TrapHwRegImm, NewTrapReg);
5137 .
Case(
"m0", AMDGPU::M0)
5138 .
Case(
"exec", AMDGPU::EXEC)
5139 .
Case(
"exec_lo", AMDGPU::EXEC_LO)
5140 .
Case(
"exec_hi", AMDGPU::EXEC_HI)
5141 .
Case(
"flat_scratch", AMDGPU::FLAT_SCR)
5142 .
Case(
"flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5143 .
Case(
"flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5144 .
Case(
"src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5145 .
Case(
"src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5146 .
Case(
"src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5151 if (!Subtarget->hasFlatScrRegister() &&
5152 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5154 "\" for subtarget."));
5157 if (!Subtarget->hasGloballyAddressableScratch() &&
5158 Subtarget->getRegisterInfo()->regsOverlap(
5159 Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE)) {
5161 "\" for subtarget."));
5166 case AMDGPU::EXEC_LO:
5167 case AMDGPU::EXEC_HI:
5168 case AMDGPU::FLAT_SCR_LO:
5169 case AMDGPU::FLAT_SCR_HI:
5170 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5171 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5176 case AMDGPU::FLAT_SCR:
5177 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5196 MI.setDesc(
TII->getKillTerminatorFromPseudo(
MI.getOpcode()));
5205static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5227 auto Next = std::next(
I);
5238 MBB.addSuccessor(LoopBB);
5240 return std::pair(LoopBB, RemainderBB);
5247 auto I =
MI.getIterator();
5248 auto E = std::next(
I);
5270 Src->setIsKill(
false);
5280 BuildMI(*LoopBB, LoopBB->begin(),
DL,
TII->get(AMDGPU::S_SETREG_IMM32_B32))
5289 BuildMI(*LoopBB,
I,
DL,
TII->get(AMDGPU::S_GETREG_B32), Reg)
5313 unsigned InitReg,
unsigned ResultReg,
unsigned PhiReg,
5314 unsigned InitSaveExecReg,
int Offset,
bool UseGPRIdxMode,
5336 BuildMI(LoopBB,
I,
DL,
TII->get(TargetOpcode::PHI), PhiExec)
5343 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5347 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5357 if (UseGPRIdxMode) {
5359 SGPRIdxReg = CurrentIdxReg;
5362 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5372 BuildMI(LoopBB,
I,
DL,
TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5403 unsigned InitResultReg,
unsigned PhiReg,
int Offset,
5404 bool UseGPRIdxMode,
Register &SGPRIdxReg) {
5412 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
5431 InitResultReg, DstReg, PhiReg, TmpExec,
5432 Offset, UseGPRIdxMode, SGPRIdxReg);
5438 LoopBB->removeSuccessor(RemainderBB);
5440 LoopBB->addSuccessor(LandingPad);
5451static std::pair<unsigned, int>
5455 int NumElts =
TRI.getRegSizeInBits(*SuperRC) / 32;
5460 return std::pair(AMDGPU::sub0,
Offset);
5517 Register SrcReg =
TII->getNamedOperand(
MI, AMDGPU::OpName::src)->getReg();
5518 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5524 std::tie(SubReg,
Offset) =
5527 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5530 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5534 if (UseGPRIdxMode) {
5541 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5550 .
addReg(SrcReg, {}, SubReg)
5554 MI.eraseFromParent();
5570 UseGPRIdxMode, SGPRIdxReg);
5574 if (UseGPRIdxMode) {
5576 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
true);
5578 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5583 BuildMI(*LoopBB, InsPt,
DL,
TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5584 .
addReg(SrcReg, {}, SubReg)
5588 MI.eraseFromParent();
5605 int Offset =
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm();
5613 std::tie(SubReg,
Offset) =
5615 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5617 if (Idx->
getReg() == AMDGPU::NoRegister) {
5628 MI.eraseFromParent();
5633 if (
TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5637 if (UseGPRIdxMode) {
5641 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5650 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5651 TRI.getRegSizeInBits(*VecRC), 32,
false);
5657 MI.eraseFromParent();
5671 UseGPRIdxMode, SGPRIdxReg);
5674 if (UseGPRIdxMode) {
5676 TII->getIndirectGPRIDXPseudo(
TRI.getRegSizeInBits(*VecRC),
false);
5678 BuildMI(*LoopBB, InsPt,
DL, GPRIDXDesc, Dst)
5684 const MCInstrDesc &MovRelDesc =
TII->getIndirectRegWriteMovRelPseudo(
5685 TRI.getRegSizeInBits(*VecRC), 32,
false);
5686 BuildMI(*LoopBB, InsPt,
DL, MovRelDesc, Dst)
5692 MI.eraseFromParent();
5708 bool IsAdd = (
MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5709 if (ST.hasScalarAddSub64()) {
5711 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5721 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5722 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5725 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5727 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5730 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5732 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5737 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5738 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5744 Hi.setOperandDead(3);
5751 MI.eraseFromParent();
5765 Register SrcCond =
MI.getOperand(3).getReg();
5773 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
5775 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src1);
5777 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src0Idx));
5779 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), Src1Idx));
5782 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5784 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5787 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5789 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5792 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5794 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5816 MI.eraseFromParent();
5821 case AMDGPU::S_MIN_U32:
5822 return std::numeric_limits<uint32_t>::max();
5823 case AMDGPU::S_MIN_I32:
5824 return std::numeric_limits<int32_t>::max();
5825 case AMDGPU::S_MAX_U32:
5826 return std::numeric_limits<uint32_t>::min();
5827 case AMDGPU::S_MAX_I32:
5828 return std::numeric_limits<int32_t>::min();
5829 case AMDGPU::V_ADD_F32_e64:
5831 case AMDGPU::V_SUB_F32_e64:
5833 case AMDGPU::S_ADD_I32:
5834 case AMDGPU::S_SUB_I32:
5835 case AMDGPU::S_OR_B32:
5836 case AMDGPU::S_XOR_B32:
5837 return std::numeric_limits<uint32_t>::min();
5838 case AMDGPU::S_AND_B32:
5839 return std::numeric_limits<uint32_t>::max();
5840 case AMDGPU::V_MIN_F32_e64:
5841 case AMDGPU::V_MAX_F32_e64:
5843 case AMDGPU::V_CMP_LT_U64_e64:
5844 return std::numeric_limits<uint64_t>::max();
5845 case AMDGPU::V_CMP_LT_I64_e64:
5846 return std::numeric_limits<int64_t>::max();
5847 case AMDGPU::V_CMP_GT_U64_e64:
5848 return std::numeric_limits<uint64_t>::min();
5849 case AMDGPU::V_CMP_GT_I64_e64:
5850 return std::numeric_limits<int64_t>::min();
5851 case AMDGPU::V_MIN_F64_e64:
5852 case AMDGPU::V_MAX_F64_e64:
5853 case AMDGPU::V_MIN_NUM_F64_e64:
5854 case AMDGPU::V_MAX_NUM_F64_e64:
5855 return 0x7FF8000000000000;
5856 case AMDGPU::S_ADD_U64_PSEUDO:
5857 case AMDGPU::S_SUB_U64_PSEUDO:
5858 case AMDGPU::S_OR_B64:
5859 case AMDGPU::S_XOR_B64:
5860 return std::numeric_limits<uint64_t>::min();
5861 case AMDGPU::S_AND_B64:
5862 return std::numeric_limits<uint64_t>::max();
5863 case AMDGPU::V_ADD_F64_e64:
5864 case AMDGPU::V_ADD_F64_pseudo_e64:
5865 return 0x8000000000000000;
5872 return Opc == AMDGPU::S_MIN_U32 ||
Opc == AMDGPU::S_MIN_I32 ||
5873 Opc == AMDGPU::S_MAX_U32 ||
Opc == AMDGPU::S_MAX_I32 ||
5874 Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32 ||
5875 Opc == AMDGPU::S_AND_B32 ||
Opc == AMDGPU::S_OR_B32 ||
5876 Opc == AMDGPU::S_XOR_B32 ||
Opc == AMDGPU::V_MIN_F32_e64 ||
5877 Opc == AMDGPU::V_MAX_F32_e64 ||
Opc == AMDGPU::V_ADD_F32_e64 ||
5878 Opc == AMDGPU::V_SUB_F32_e64;
5882 return Opc == AMDGPU::V_MIN_F32_e64 ||
Opc == AMDGPU::V_MAX_F32_e64 ||
5883 Opc == AMDGPU::V_ADD_F32_e64 ||
Opc == AMDGPU::V_SUB_F32_e64 ||
5884 Opc == AMDGPU::V_MIN_F64_e64 ||
Opc == AMDGPU::V_MAX_F64_e64 ||
5885 Opc == AMDGPU::V_MIN_NUM_F64_e64 ||
Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5886 Opc == AMDGPU::V_ADD_F64_e64 ||
Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5889static std::tuple<unsigned, unsigned>
5893 case AMDGPU::S_MIN_U32:
5894 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5896 case AMDGPU::S_MIN_I32:
5897 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5899 case AMDGPU::S_MAX_U32:
5900 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5902 case AMDGPU::S_MAX_I32:
5903 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5905 case AMDGPU::S_ADD_I32:
5906 case AMDGPU::S_SUB_I32:
5907 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5908 : AMDGPU::V_ADD_CO_U32_dpp;
5910 case AMDGPU::S_AND_B32:
5911 DPPOpc = AMDGPU::V_AND_B32_dpp;
5913 case AMDGPU::S_OR_B32:
5914 DPPOpc = AMDGPU::V_OR_B32_dpp;
5916 case AMDGPU::S_XOR_B32:
5917 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5919 case AMDGPU::V_ADD_F32_e64:
5920 case AMDGPU::V_SUB_F32_e64:
5921 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5923 case AMDGPU::V_MIN_F32_e64:
5924 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5926 case AMDGPU::V_MAX_F32_e64:
5927 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5929 case AMDGPU::V_CMP_LT_U64_e64:
5930 case AMDGPU::V_CMP_LT_I64_e64:
5931 case AMDGPU::V_CMP_GT_U64_e64:
5932 case AMDGPU::V_CMP_GT_I64_e64:
5933 case AMDGPU::S_ADD_U64_PSEUDO:
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 case AMDGPU::S_AND_B64:
5936 case AMDGPU::S_OR_B64:
5937 case AMDGPU::S_XOR_B64:
5938 case AMDGPU::V_MIN_NUM_F64_e64:
5939 case AMDGPU::V_MIN_F64_e64:
5940 case AMDGPU::V_MAX_NUM_F64_e64:
5941 case AMDGPU::V_MAX_F64_e64:
5942 case AMDGPU::V_ADD_F64_pseudo_e64:
5943 case AMDGPU::V_ADD_F64_e64:
5944 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5949 unsigned ClampOpc =
Opc;
5950 if (!ST.getInstrInfo()->isVALU(
Opc,
true)) {
5951 if (
Opc == AMDGPU::S_SUB_I32)
5952 ClampOpc = AMDGPU::S_ADD_I32;
5953 if (
Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO)
5954 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5955 else if (
Opc == AMDGPU::S_AND_B64)
5956 ClampOpc = AMDGPU::V_AND_B32_e64;
5957 else if (
Opc == AMDGPU::S_OR_B64)
5958 ClampOpc = AMDGPU::V_OR_B32_e64;
5959 else if (
Opc == AMDGPU::S_XOR_B64)
5960 ClampOpc = AMDGPU::V_XOR_B32_e64;
5962 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5964 return {DPPOpc, ClampOpc};
5967static std::pair<Register, Register>
5974 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5976 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5978 TII->buildExtractSubReg(
MI, MRI,
Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5979 return {Op1L, Op1H};
5995 unsigned Stratergy =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
5996 enum WAVE_REDUCE_STRATEGY :
unsigned {
DEFAULT = 0, ITERATIVE = 1,
DPP = 2 };
5998 unsigned MIOpc =
MI.getOpcode();
6012 case AMDGPU::S_MIN_U32:
6013 case AMDGPU::S_MIN_I32:
6014 case AMDGPU::V_MIN_F32_e64:
6015 case AMDGPU::S_MAX_U32:
6016 case AMDGPU::S_MAX_I32:
6017 case AMDGPU::V_MAX_F32_e64:
6018 case AMDGPU::S_AND_B32:
6019 case AMDGPU::S_OR_B32: {
6025 case AMDGPU::V_CMP_LT_U64_e64:
6026 case AMDGPU::V_CMP_LT_I64_e64:
6027 case AMDGPU::V_CMP_GT_U64_e64:
6028 case AMDGPU::V_CMP_GT_I64_e64:
6029 case AMDGPU::V_MIN_F64_e64:
6030 case AMDGPU::V_MIN_NUM_F64_e64:
6031 case AMDGPU::V_MAX_F64_e64:
6032 case AMDGPU::V_MAX_NUM_F64_e64:
6033 case AMDGPU::S_AND_B64:
6034 case AMDGPU::S_OR_B64: {
6040 case AMDGPU::S_XOR_B32:
6041 case AMDGPU::S_XOR_B64:
6042 case AMDGPU::S_ADD_I32:
6043 case AMDGPU::S_ADD_U64_PSEUDO:
6044 case AMDGPU::V_ADD_F32_e64:
6045 case AMDGPU::V_ADD_F64_e64:
6046 case AMDGPU::V_ADD_F64_pseudo_e64:
6047 case AMDGPU::S_SUB_I32:
6048 case AMDGPU::S_SUB_U64_PSEUDO:
6049 case AMDGPU::V_SUB_F32_e64: {
6056 bool IsWave32 = ST.isWave32();
6057 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6058 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6059 unsigned BitCountOpc =
6060 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6064 auto NewAccumulator =
6070 case AMDGPU::S_XOR_B32:
6071 case AMDGPU::S_XOR_B64: {
6079 .
addReg(NewAccumulator->getOperand(0).getReg())
6087 if (
Opc == AMDGPU::S_XOR_B32) {
6094 BuildRegSequence(BB,
MI, DstReg, ParityRegister, DstHi);
6099 if (
Opc == AMDGPU::S_XOR_B32) {
6116 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6120 case AMDGPU::S_SUB_I32: {
6129 .
addReg(NewAccumulator->getOperand(0).getReg());
6132 case AMDGPU::S_ADD_I32: {
6139 .
addReg(NewAccumulator->getOperand(0).getReg());
6145 .
addReg(NewAccumulator->getOperand(0).getReg());
6148 case AMDGPU::S_ADD_U64_PSEUDO:
6149 case AMDGPU::S_SUB_U64_PSEUDO: {
6169 if (
Imm == 1 &&
Opc == AMDGPU::S_ADD_U64_PSEUDO) {
6174 BuildRegSequence(BB,
MI, DstReg,
6175 NewAccumulator->getOperand(0).getReg(), DstHi);
6179 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6182 .
addReg(NewAccumulator->getOperand(0).getReg())
6192 Register LowOpcode =
Opc == AMDGPU::S_SUB_U64_PSEUDO
6194 : NewAccumulator->getOperand(0).getReg();
6198 if (ST.hasScalarMulHiInsts()) {
6209 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6212 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6219 Register HiVal =
Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6225 if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6231 BuildRegSequence(BB,
MI, DstReg, DestSub0, DestSub1);
6234 case AMDGPU::V_ADD_F32_e64:
6235 case AMDGPU::V_ADD_F64_e64:
6236 case AMDGPU::V_ADD_F64_pseudo_e64:
6237 case AMDGPU::V_SUB_F32_e64: {
6244 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6245 : AMDGPU::V_CVT_F64_I32_e64),
6247 .
addReg(NewAccumulator->getOperand(0).getReg())
6252 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6253 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6256 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6258 ? AMDGPU::V_MUL_F64_pseudo_e64
6259 : AMDGPU::V_MUL_F64_e64;
6269 BuildMI(BB,
MI,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6286 BuildRegSequence(BB,
MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6298 bool NeedsMovDPP = !is32BitOpc;
6303 bool IsWave32 = ST.isWave32();
6304 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6305 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6306 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6332 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6336 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6337 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6346 I = ComputeLoop->begin();
6348 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), AccumulatorReg)
6352 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::PHI), ActiveBitsReg)
6356 I = ComputeLoop->end();
6360 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6365 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6366 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6367 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6368 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6370 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::clamp) != -1;
6372 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::op_sel) != -1;
6374 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::omod) != -1;
6375 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6379 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6383 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), LaneValVgpr)
6385 OpDstReg = VgprResultReg;
6386 LaneValueReg = LaneValVgpr;
6389 if (hasSrc0Modifier)
6391 OpInstr.addReg(AccumulatorReg);
6392 if (hasSrc1Modifier)
6394 OpInstr.addReg(LaneValueReg);
6402 OpInstr.setOperandDead(3);
6403 if (ST.getInstrInfo()->isVALU(
Opc,
true)) {
6404 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32),
6418 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6422 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::V_READLANE_B32),
6426 auto LaneValue = BuildRegSequence(*ComputeLoop,
I, LaneValReg,
6427 LaneValueLoReg, LaneValueHiReg);
6429 case AMDGPU::S_OR_B64:
6430 case AMDGPU::S_AND_B64:
6431 case AMDGPU::S_XOR_B64: {
6434 .
addReg(LaneValue->getOperand(0).getReg())
6438 case AMDGPU::V_CMP_GT_I64_e64:
6439 case AMDGPU::V_CMP_GT_U64_e64:
6440 case AMDGPU::V_CMP_LT_I64_e64:
6441 case AMDGPU::V_CMP_LT_U64_e64: {
6446 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6448 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6452 BuildRegSequence(*ComputeLoop,
I, AccumulatorVReg, SrcReg0Sub0,
6455 .
addReg(LaneValue->getOperand(0).getReg())
6456 .
addReg(AccumulatorVReg);
6458 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6459 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AndOpc), ComparisonResultReg)
6463 NewAccumulator =
BuildMI(*ComputeLoop,
I,
DL,
6464 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6465 .
addReg(LaneValue->getOperand(0).getReg())
6469 case AMDGPU::V_MIN_F64_e64:
6470 case AMDGPU::V_MIN_NUM_F64_e64:
6471 case AMDGPU::V_MAX_F64_e64:
6472 case AMDGPU::V_MAX_NUM_F64_e64:
6473 case AMDGPU::V_ADD_F64_e64:
6474 case AMDGPU::V_ADD_F64_pseudo_e64: {
6476 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src);
6478 TRI->getAllocatableClass(
TII->getRegClass(
MI.getDesc(), SrcIdx));
6485 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::COPY), AccumulatorVReg)
6488 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6494 .
addReg(LaneValue->getOperand(0).getReg())
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6504 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6506 auto [Op1L, Op1H] =
ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6508 ReadLaneLo.addReg(Op1L);
6509 ReadLaneHi.addReg(Op1H);
6511 BuildRegSequence(*ComputeLoop,
I, DstReg, LaneValLo, LaneValHi);
6514 case AMDGPU::S_ADD_U64_PSEUDO:
6515 case AMDGPU::S_SUB_U64_PSEUDO: {
6518 .
addReg(LaneValue->getOperand(0).getReg())
6527 unsigned BITSETOpc =
6528 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6529 BuildMI(*ComputeLoop,
I,
DL,
TII->get(BITSETOpc), NewActiveBitsReg)
6535 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6539 if (!ST.hasScalarCompareEq64()) {
6542 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6544 BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc), LaneMaskReg);
6547 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6548 SetSCCInstr =
BuildMI(*ComputeLoop,
I,
DL,
TII->get(CMPOpc));
6550 SetSCCInstr.
addReg(NewActiveBitsReg);
6551 if (ST.hasScalarCompareEq64())
6554 SetSCCInstr.
addReg(NewActiveBitsReg);
6555 BuildMI(*ComputeLoop,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_SCC1))
6560 assert(ST.hasDPP() &&
"Sub Target does not support DPP Operations");
6577 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6581 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6582 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6585 auto IdentityCopyInstr =
6589 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6590 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6605 if (isFPOp && !NeedsMovDPP)
6608 if (isFPOp && !NeedsMovDPP)
6612 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6621 bool isAddSub =
false,
6622 bool needsCarryIn =
false,
6624 unsigned InstrOpc = ClampOpc;
6627 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6628 auto ClampInstr =
BuildMI(*CurrBB,
MI,
DL,
TII->get(InstrOpc), Dst);
6633 ClampInstr.addReg(CarryOutReg,
6639 ClampInstr.addReg(Src0);
6642 ClampInstr.addReg(Src1);
6645 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6646 ClampInstr.addImm(0);
6648 ClampInstr.addImm(0);
6649 LastBcastInstr = ClampInstr;
6654 Opc == AMDGPU::S_ADD_U64_PSEUDO ||
Opc == AMDGPU::S_SUB_U64_PSEUDO;
6655 bool isBitWiseOpc =
Opc == AMDGPU::S_AND_B64 ||
6656 Opc == AMDGPU::S_OR_B64 ||
Opc == AMDGPU::S_XOR_B64;
6658 if (isAddSubOpc || isBitWiseOpc) {
6665 auto [Src0Lo, Src0Hi] =
6667 auto [Src1Lo, Src1Hi] =
6669 Register CarryReg = BuildClampInstr(
6670 ResLo, Src0Lo, Src1Lo, isAddSubOpc,
false);
6671 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6672 isAddSubOpc, CarryReg);
6673 BuildRegSequence(*CurrBB,
MI, ReturnReg, ResLo, ResHi);
6702 SrcWithIdentityInstr =
6703 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6710 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6711 auto [SrcReg0Sub0, SrcReg0Sub1] =
6714 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6716 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6717 SrcWithIdentityInstr =
6718 BuildRegSequence(*CurrBB,
MI, SrcWithIdentity,
6725 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6728 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6730 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6733 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6735 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6738 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6740 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6743 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6745 if (ST.hasDPPBroadcasts()) {
6748 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6763 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6784 BuildRegSequence(*CurrBB,
MI, SwizzledValue64, SwizzledValuelo,
6787 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6789 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6792 FinalDPPResult = RowBcast15;
6794 if (ST.hasDPPBroadcasts()) {
6797 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6813 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6817 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6823 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6831 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6836 .
addReg(ShiftedThreadID);
6841 .
addReg(PermuteByteOffset)
6851 auto [RowBcast15Lo, RowBcast15Hi] =
6855 .
addReg(PermuteByteOffset)
6860 .
addReg(PermuteByteOffset)
6863 BuildRegSequence(*CurrBB,
MI, PermutedValue, PermutedValuelo,
6867 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6869 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6871 FinalDPPResult = RowBcast31;
6873 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6874 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6884 .
addReg(IsWave32 ? RowBcast15 : RowBcast31)
6887 FinalDPPResult = NegatedValVGPR;
6894 .
addImm(ST.getWavefrontSize() - 1);
6909 .
addImm(ST.getWavefrontSize() - 1);
6913 .
addImm(ST.getWavefrontSize() - 1);
6914 BuildRegSequence(*CurrBB,
MI, ReducedValSGPR, LaneValueLoReg,
6917 if (
Opc == AMDGPU::S_SUB_I32) {
6918 BuildMI(*CurrBB,
MI,
DL,
TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6922 }
else if (
Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6923 auto NegatedValInstr =
6932 .
addReg(
Opc == AMDGPU::S_SUB_I32 ||
Opc == AMDGPU::S_SUB_U64_PSEUDO
6938 MI.eraseFromParent();
6953 switch (
MI.getOpcode()) {
6954 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6956 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6958 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6960 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6962 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6964 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6967 ? AMDGPU::V_MIN_NUM_F64_e64
6968 : AMDGPU::V_MIN_F64_e64);
6969 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6971 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6973 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6975 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6977 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6979 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6982 ? AMDGPU::V_MAX_NUM_F64_e64
6983 : AMDGPU::V_MAX_F64_e64);
6984 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6986 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6988 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6990 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6993 ? AMDGPU::V_ADD_F64_pseudo_e64
6994 : AMDGPU::V_ADD_F64_e64);
6995 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6997 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6999 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
7001 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7006 ? AMDGPU::V_ADD_F64_pseudo_e64
7007 : AMDGPU::V_ADD_F64_e64);
7008 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7010 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7012 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7014 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7016 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7018 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7020 case AMDGPU::S_UADDO_PSEUDO:
7021 case AMDGPU::S_USUBO_PSEUDO: {
7027 unsigned Opc = (
MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7029 : AMDGPU::S_SUB_U32;
7037 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7040 MI.eraseFromParent();
7043 case AMDGPU::S_ADD_U64_PSEUDO:
7044 case AMDGPU::S_SUB_U64_PSEUDO: {
7047 case AMDGPU::V_ADD_U64_PSEUDO:
7048 case AMDGPU::V_SUB_U64_PSEUDO: {
7049 bool IsAdd = (
MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7055 if (ST.hasAddSubU64Insts()) {
7057 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7058 : AMDGPU::V_SUB_U64_e64),
7063 TII->legalizeOperands(*
I);
7064 MI.eraseFromParent();
7068 if (IsAdd && ST.hasLshlAddU64Inst()) {
7074 TII->legalizeOperands(*
Add);
7075 MI.eraseFromParent();
7079 const auto *CarryRC =
TRI->getWaveMaskRegClass();
7089 : &AMDGPU::VReg_64RegClass;
7092 : &AMDGPU::VReg_64RegClass;
7095 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7097 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7100 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7102 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7105 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7107 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7110 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7117 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7131 TII->legalizeOperands(*LoHalf);
7132 TII->legalizeOperands(*HiHalf);
7133 MI.eraseFromParent();
7136 case AMDGPU::S_ADD_CO_PSEUDO:
7137 case AMDGPU::S_SUB_CO_PSEUDO: {
7149 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7155 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7160 if (
TRI->isVectorRegister(MRI, Src2.
getReg())) {
7161 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7166 if (ST.isWave64()) {
7167 if (ST.hasScalarCompareEq64()) {
7174 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7176 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7178 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7181 BuildMI(*BB, MII,
DL,
TII->get(AMDGPU::S_OR_B32), Src2_32)
7195 unsigned Opc =
MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7196 ? AMDGPU::S_ADDC_U32
7197 : AMDGPU::S_SUBB_U32;
7202 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7208 MI.eraseFromParent();
7211 case AMDGPU::SI_INIT_M0: {
7214 TII->get(M0Init.
isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7217 MI.eraseFromParent();
7220 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7223 TII->get(AMDGPU::S_CMP_EQ_U32))
7228 case AMDGPU::GET_GROUPSTATICSIZE: {
7232 .
add(
MI.getOperand(0))
7234 MI.eraseFromParent();
7237 case AMDGPU::GET_SHADERCYCLESHILO: {
7252 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7255 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7258 .
addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7267 .
add(
MI.getOperand(0))
7272 MI.eraseFromParent();
7275 case AMDGPU::SI_INDIRECT_SRC_V1:
7276 case AMDGPU::SI_INDIRECT_SRC_V2:
7277 case AMDGPU::SI_INDIRECT_SRC_V3:
7278 case AMDGPU::SI_INDIRECT_SRC_V4:
7279 case AMDGPU::SI_INDIRECT_SRC_V5:
7280 case AMDGPU::SI_INDIRECT_SRC_V6:
7281 case AMDGPU::SI_INDIRECT_SRC_V7:
7282 case AMDGPU::SI_INDIRECT_SRC_V8:
7283 case AMDGPU::SI_INDIRECT_SRC_V9:
7284 case AMDGPU::SI_INDIRECT_SRC_V10:
7285 case AMDGPU::SI_INDIRECT_SRC_V11:
7286 case AMDGPU::SI_INDIRECT_SRC_V12:
7287 case AMDGPU::SI_INDIRECT_SRC_V16:
7288 case AMDGPU::SI_INDIRECT_SRC_V32:
7290 case AMDGPU::SI_INDIRECT_DST_V1:
7291 case AMDGPU::SI_INDIRECT_DST_V2:
7292 case AMDGPU::SI_INDIRECT_DST_V3:
7293 case AMDGPU::SI_INDIRECT_DST_V4:
7294 case AMDGPU::SI_INDIRECT_DST_V5:
7295 case AMDGPU::SI_INDIRECT_DST_V6:
7296 case AMDGPU::SI_INDIRECT_DST_V7:
7297 case AMDGPU::SI_INDIRECT_DST_V8:
7298 case AMDGPU::SI_INDIRECT_DST_V9:
7299 case AMDGPU::SI_INDIRECT_DST_V10:
7300 case AMDGPU::SI_INDIRECT_DST_V11:
7301 case AMDGPU::SI_INDIRECT_DST_V12:
7302 case AMDGPU::SI_INDIRECT_DST_V16:
7303 case AMDGPU::SI_INDIRECT_DST_V32:
7305 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7306 case AMDGPU::SI_KILL_I1_PSEUDO:
7308 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7312 case AMDGPU::SI_BR_UNDEF: {
7314 .
add(
MI.getOperand(0));
7316 MI.eraseFromParent();
7319 case AMDGPU::ADJCALLSTACKUP:
7320 case AMDGPU::ADJCALLSTACKDOWN: {
7327 case AMDGPU::SI_CALL_ISEL: {
7328 unsigned ReturnAddrReg =
TII->getRegisterInfo().getReturnAddressReg(*MF);
7331 MIB =
BuildMI(*BB,
MI,
DL,
TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7337 MI.eraseFromParent();
7340 case AMDGPU::V_ADDC_U32_e32:
7341 case AMDGPU::V_SUBB_U32_e32:
7342 case AMDGPU::V_SUBBREV_U32_e32:
7345 TII->legalizeOperands(
MI);
7347 case AMDGPU::DS_GWS_INIT:
7348 case AMDGPU::DS_GWS_SEMA_BR:
7349 case AMDGPU::DS_GWS_BARRIER:
7350 case AMDGPU::DS_GWS_SEMA_V:
7351 case AMDGPU::DS_GWS_SEMA_P:
7352 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7360 case AMDGPU::S_SETREG_B32: {
7370 auto [ID,
Offset, Width] =
7376 const unsigned SetMask = WidthMask <<
Offset;
7379 unsigned SetDenormOp = 0;
7380 unsigned SetRoundOp = 0;
7388 SetRoundOp = AMDGPU::S_ROUND_MODE;
7389 SetDenormOp = AMDGPU::S_DENORM_MODE;
7391 SetRoundOp = AMDGPU::S_ROUND_MODE;
7393 SetDenormOp = AMDGPU::S_DENORM_MODE;
7396 if (SetRoundOp || SetDenormOp) {
7398 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7399 unsigned ImmVal = Def->getOperand(1).getImm();
7413 MI.eraseFromParent();
7422 MI.setDesc(
TII->get(AMDGPU::S_SETREG_B32_mode));
7426 case AMDGPU::S_INVERSE_BALLOT_U32:
7427 case AMDGPU::S_INVERSE_BALLOT_U64:
7430 MI.setDesc(
TII->get(AMDGPU::COPY));
7432 case AMDGPU::ENDPGM_TRAP: {
7434 MI.setDesc(
TII->get(AMDGPU::S_ENDPGM));
7454 MI.eraseFromParent();
7457 case AMDGPU::SIMULATED_TRAP: {
7458 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7460 TII->insertSimulatedTrap(MRI, *BB,
MI,
MI.getDebugLoc());
7461 MI.eraseFromParent();
7464 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7465 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7471 assert(Setup &&
"Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7472 Register OriginalExec = Setup->getOperand(0).getReg();
7474 MI.getOperand(0).setReg(OriginalExec);
7477 case AMDGPU::V_DOT2_F32_F16:
7478 case AMDGPU::V_DOT2_F32_BF16: {
7485 case AMDGPU::SCHED_BARRIER:
7486 case AMDGPU::SCHED_GROUP_BARRIER:
7487 MI.getOperand(0).setImm(
MI.getOperand(0).getImm() &
7524 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7528 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7557 if (!Subtarget->hasMadMacF32Insts())
7558 return Subtarget->hasFastFMAF32();
7564 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7567 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7573 return Subtarget->has16BitInsts() &&
7591 F.getDenormalFPEnv());
7596 switch (Ty.getScalarSizeInBits()) {
7614 return Subtarget->hasMadMacF32Insts() &&
7617 return Subtarget->hasMadF16() &&
7628 if (Ty.getScalarSizeInBits() == 16)
7630 if (Ty.getScalarSizeInBits() == 32)
7645 F.getDenormalFPEnv());
7656 unsigned Opc =
Op.getOpcode();
7657 EVT VT =
Op.getValueType();
7669 LoOps.
append(TrailingOps.begin(), TrailingOps.end());
7670 HiOps.
append(TrailingOps.begin(), TrailingOps.end());
7683 [[maybe_unused]]
EVT VT =
Op.getValueType();
7685 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7686 VT == MVT::v16i32) &&
7687 "Unexpected ValueType.");
7696 unsigned Opc =
Op.getOpcode();
7697 EVT VT =
Op.getValueType();
7706 DAG.
getNode(
Opc, SL, Lo0.getValueType(), Lo0, Lo1,
Op->getFlags());
7708 DAG.
getNode(
Opc, SL, Hi0.getValueType(), Hi0, Hi1,
Op->getFlags());
7715 unsigned Opc =
Op.getOpcode();
7716 EVT VT =
Op.getValueType();
7733 DAG.
getNode(
Opc, SL, ResVT.first, Lo0, Lo1, Lo2,
Op->getFlags());
7735 DAG.
getNode(
Opc, SL, ResVT.second, Hi0, Hi1, Hi2,
Op->getFlags());
7741 switch (
Op.getOpcode()) {
7745 return LowerBRCOND(
Op, DAG);
7747 return LowerRETURNADDR(
Op, DAG);
7749 return LowerSPONENTRY(
Op, DAG);
7752 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7753 "Load should return a value and a chain");
7757 EVT VT =
Op.getValueType();
7759 return lowerFSQRTF32(
Op, DAG);
7761 return lowerFSQRTF64(
Op, DAG);
7766 return LowerTrig(
Op, DAG);
7768 return LowerSELECT(
Op, DAG);
7770 return LowerFDIV(
Op, DAG);
7772 return LowerFFREXP(
Op, DAG);
7774 return LowerATOMIC_CMP_SWAP(
Op, DAG);
7776 return LowerSTORE(
Op, DAG);
7780 return LowerGlobalAddress(MFI,
Op, DAG);
7785 return LowerExternalSymbol(
Op, DAG);
7787 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7789 return LowerCONVERT_FROM_ARBITRARY_FP(
Op, DAG);
7791 return LowerCONVERT_TO_ARBITRARY_FP(
Op, DAG);
7793 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7795 return LowerINTRINSIC_VOID(
Op, DAG);
7797 return lowerADDRSPACECAST(
Op, DAG);
7799 return lowerINSERT_SUBVECTOR(
Op, DAG);
7801 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7803 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7805 return lowerVECTOR_SHUFFLE(
Op, DAG);
7807 return lowerSCALAR_TO_VECTOR(
Op, DAG);
7809 return lowerBUILD_VECTOR(
Op, DAG);
7812 return lowerFP_ROUND(
Op, DAG);
7814 return lowerTRAP(
Op, DAG);
7816 return lowerDEBUGTRAP(
Op, DAG);
7825 if (
Op.getValueType().isVector() &&
Op.getValueType() != MVT::v2i16 &&
7826 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7830 if (
Op.getValueType() == MVT::bf16) {
7860 return lowerFMINNUM_FMAXNUM(
Op, DAG);
7863 return lowerFMINIMUMNUM_FMAXIMUMNUM(
Op, DAG);
7866 return lowerFLDEXP(
Op, DAG);
7871 if (Subtarget->hasVCvtPkIU16F32() &&
Op.getValueType() == MVT::i16 &&
7872 Op.getOperand(0).getValueType() == MVT::f32) {
7898 return lowerFCOPYSIGN(
Op, DAG);
7900 return lowerMUL(
Op, DAG);
7903 return lowerXMULO(
Op, DAG);
7906 return lowerXMUL_LOHI(
Op, DAG);
7927 return LowerINLINEASM(
Op, DAG);
7933static std::pair<SDValue, SDValue>
7963 EVT FittingLoadVT = LoadVT;
7995SDValue SITargetLowering::adjustLoadValueType(
unsigned Opcode,
MemSDNode *M,
7998 bool IsIntrinsic)
const {
8001 bool IsTFE =
M->getNumValues() == 3;
8002 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8003 EVT LoadVT =
M->getValueType(0);
8005 EVT EquivLoadVT = LoadVT;
8022 SDVTList VTList = DAG.
getVTList(LoadDWordsVT, MVT::Other);
8024 Opcode,
DL, VTList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
8032 SDVTList VTList = DAG.
getVTList(EquivLoadVT, MVT::Other);
8036 M->getMemoryVT(),
M->getMemOperand());
8047 EVT LoadVT =
M->getValueType(0);
8056 "unsupported sub-dword format buffer load",
DL.getDebugLoc()));
8060 assert(
M->getNumValues() == 2 ||
M->getNumValues() == 3);
8061 bool IsTFE =
M->getNumValues() == 3;
8063 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8066 "TFE D16 format buffer load is not supported on this GPU",
8069 M->getOperand(0),
DL);
8072 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8073 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8074 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8075 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8076 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8077 : AMDGPUISD::BUFFER_LOAD;
8080 return adjustLoadValueType(
Opc, M, DAG,
Ops);
8084 return handleByteShortBufferLoads(DAG, LoadVT,
DL,
Ops,
M->getMemOperand(),
8088 return getMemIntrinsicNode(
Opc,
DL,
M->getVTList(),
Ops, IntVT,
8089 M->getMemOperand(), DAG);
8093 SDVTList VTList = IsTFE ? DAG.
getVTList(CastVT, MVT::i32, MVT::Other)
8095 SDValue MemNode = getMemIntrinsicNode(
Opc,
DL, VTList,
Ops, CastVT,
8096 M->getMemOperand(), DAG);
8106 EVT VT =
N->getValueType(0);
8130 Exec = AMDGPU::EXEC_LO;
8132 Exec = AMDGPU::EXEC;
8149 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8151 EVT VT =
Op.getValueType();
8156 if (VT != MVT::i32) {
8164 return DAG.
getNode(
Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32,
DL, VT,
8173 EVT VT =
N->getValueType(0);
8175 unsigned IID =
N->getConstantOperandVal(0);
8176 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8177 IID == Intrinsic::amdgcn_permlanex16;
8178 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8179 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8180 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8181 IID == Intrinsic::amdgcn_permlane_up ||
8182 IID == Intrinsic::amdgcn_permlane_down ||
8183 IID == Intrinsic::amdgcn_permlane_xor;
8188 unsigned SplitSize = 32;
8189 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8190 ST->hasDPALU_DPP() &&
8198 case Intrinsic::amdgcn_permlane16:
8199 case Intrinsic::amdgcn_permlanex16:
8200 case Intrinsic::amdgcn_update_dpp:
8205 case Intrinsic::amdgcn_writelane:
8206 case Intrinsic::amdgcn_permlane_bcast:
8207 case Intrinsic::amdgcn_permlane_up:
8208 case Intrinsic::amdgcn_permlane_down:
8209 case Intrinsic::amdgcn_permlane_xor:
8212 case Intrinsic::amdgcn_readlane:
8213 case Intrinsic::amdgcn_set_inactive:
8214 case Intrinsic::amdgcn_set_inactive_chain_arg:
8215 case Intrinsic::amdgcn_mov_dpp8:
8218 case Intrinsic::amdgcn_readfirstlane:
8219 case Intrinsic::amdgcn_permlane64:
8229 if (
SDNode *GL =
N->getGluedNode()) {
8231 GL = GL->getOperand(0).getNode();
8241 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8242 IID == Intrinsic::amdgcn_mov_dpp8 ||
8243 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8244 IsPermlaneShuffle) {
8245 Src1 =
N->getOperand(2);
8246 if (IID == Intrinsic::amdgcn_writelane ||
8247 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8249 Src2 =
N->getOperand(3);
8252 if (ValSize == SplitSize) {
8262 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8267 if (IID == Intrinsic::amdgcn_writelane) {
8272 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8274 return IsFloat ? DAG.
getBitcast(VT, Trunc) : Trunc;
8277 if (ValSize % SplitSize != 0)
8281 EVT VT =
N->getValueType(0);
8285 unsigned NumOperands =
N->getNumOperands();
8287 SDNode *GL =
N->getGluedNode();
8292 for (
unsigned i = 0; i != NE; ++i) {
8293 for (
unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8295 SDValue Operand =
N->getOperand(j);
8325 if (SplitSize == 32) {
8327 return unrollLaneOp(LaneOp.
getNode());
8333 unsigned SubVecNumElt =
8337 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8338 for (
unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8342 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8348 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8349 }
else if (IID == Intrinsic::amdgcn_writelane) {
8353 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8355 Pieces.
push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8358 EltIdx += SubVecNumElt;
8372 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8375 if (IID == Intrinsic::amdgcn_writelane)
8378 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8385 EVT VT =
N->getValueType(0);
8403 auto MakeIntrinsic = [&DAG, &SL](
unsigned IID,
MVT RetVT,
8413 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8414 {ShiftedIndex, ValueI32});
8424 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8425 {ValueI32, PoisonVal});
8426 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8427 {ShiftedIndex, PoisonVal});
8430 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8433 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8434 {WWMIndex, WWMValue});
8435 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8436 MVT::i32, {WWMIndex, Swapped});
8438 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8446 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8454 DAG.
getSetCC(SL, MVT::i1, SameOrOtherHalf,
8464 switch (
N->getOpcode()) {
8481 unsigned IID =
N->getConstantOperandVal(0);
8483 case Intrinsic::amdgcn_wave_reduce_min:
8484 case Intrinsic::amdgcn_wave_reduce_umin:
8485 case Intrinsic::amdgcn_wave_reduce_max:
8486 case Intrinsic::amdgcn_wave_reduce_umax:
8487 case Intrinsic::amdgcn_wave_reduce_add:
8488 case Intrinsic::amdgcn_wave_reduce_sub:
8489 case Intrinsic::amdgcn_wave_reduce_and:
8490 case Intrinsic::amdgcn_wave_reduce_or:
8491 case Intrinsic::amdgcn_wave_reduce_xor: {
8492 EVT VT =
N->getValueType(0);
8496 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8497 IID == Intrinsic::amdgcn_wave_reduce_max ||
8498 IID == Intrinsic::amdgcn_wave_reduce_add ||
8499 IID == Intrinsic::amdgcn_wave_reduce_sub;
8503 N->getOperand(0), ExtSrc,
N->getOperand(2));
8507 case Intrinsic::amdgcn_make_buffer_rsrc:
8508 Results.push_back(lowerPointerAsRsrcIntrin(
N, DAG));
8510 case Intrinsic::amdgcn_cvt_pkrtz: {
8515 DAG.
getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8519 case Intrinsic::amdgcn_cvt_pknorm_i16:
8520 case Intrinsic::amdgcn_cvt_pknorm_u16:
8521 case Intrinsic::amdgcn_cvt_pk_i16:
8522 case Intrinsic::amdgcn_cvt_pk_u16: {
8528 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8529 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8530 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8531 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8532 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8533 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8535 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8537 EVT VT =
N->getValueType(0);
8546 case Intrinsic::amdgcn_s_buffer_load: {
8548 EVT VT =
Op.getValueType();
8550 Op.getOperand(1),
Op.getOperand(2),
8551 Op.getOperand(3), DAG));
8554 case Intrinsic::amdgcn_dead: {
8555 for (
unsigned I = 0, E =
N->getNumValues();
I < E; ++
I)
8563 if (
N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8564 N->getValueType(0).isSimple() &&
8565 SBufferLoadDiagnosticVTs[
N->getSimpleValueType(0).SimpleTy])
8570 for (
unsigned I = 0;
I < Res.getNumOperands();
I++) {
8571 Results.push_back(Res.getOperand(
I));
8574 for (
unsigned I = 0;
I <
N->getNumValues(); ++
I)
8575 Results.push_back(Res.getValue(
I));
8584 EVT VT =
N->getValueType(0);
8589 EVT SelectVT = NewVT;
8590 if (NewVT.
bitsLT(MVT::i32)) {
8593 SelectVT = MVT::i32;
8599 if (NewVT != SelectVT)
8605 if (
N->getValueType(0) != MVT::v2f16)
8617 if (
N->getValueType(0) != MVT::v2f16)
8629 if (
N->getValueType(0) != MVT::f16)
8644 if (U.get() !=
Value)
8647 if (U.getUser()->getOpcode() == Opcode)
8653unsigned SITargetLowering::isCFIntrinsic(
const SDNode *Intr)
const {
8656 case Intrinsic::amdgcn_if:
8657 return AMDGPUISD::IF;
8658 case Intrinsic::amdgcn_else:
8659 return AMDGPUISD::ELSE;
8660 case Intrinsic::amdgcn_loop:
8661 return AMDGPUISD::LOOP;
8662 case Intrinsic::amdgcn_end_cf:
8682 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8706 assert(GVar->isDeclaration() &&
8707 "AS 3 & 13 GVs should be declaration here "
8708 "when object linking is enabled");
8723 SDNode *Intr = BRCOND.getOperand(1).getNode();
8740 Intr =
LHS.getNode();
8748 assert(BR &&
"brcond missing unconditional branch user");
8753 unsigned CFNode = isCFIntrinsic(Intr);
8773 Ops.push_back(Target);
8781 SDValue
Ops[] = {SDValue(Result, 0),
BRCOND.getOperand(0)};
8788 SDValue
Ops[] = {
BR->getOperand(0),
BRCOND.getOperand(2)};
8793 SDValue Chain = SDValue(Result,
Result->getNumValues() - 1);
8796 for (
unsigned i = 1, e = Intr->
getNumValues() - 1; i != e; ++i) {
8802 SDValue(Result, i - 1), SDValue());
8815 MVT VT =
Op.getSimpleValueType();
8818 if (
Op.getConstantOperandVal(0) != 0)
8822 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8824 if (
Info->isEntryFunction())
8841 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
8855 return Op.getValueType().bitsLE(VT)
8863 EVT DstVT =
Op.getValueType();
8870 unsigned Opc =
Op.getOpcode();
8871 SDValue
Flags =
Op.getOperand(1);
8881 bool IsStrict =
Op->isStrictFPOpcode();
8882 SDValue Src =
Op.getOperand(IsStrict ? 1 : 0);
8883 EVT SrcVT = Src.getValueType();
8884 EVT DstVT =
Op.getValueType();
8887 assert(Subtarget->hasCvtPkF16F32Inst() &&
"support v_cvt_pk_f16_f32");
8890 return SrcVT == MVT::v2f32 ?
Op : splitFP_ROUNDVectorOp(
Op, DAG);
8897 if (DstVT == MVT::f16) {
8902 if (!Subtarget->has16BitInsts()) {
8907 if (
Op->getFlags().hasApproximateFuncs()) {
8908 SDValue
Flags =
Op.getOperand(1);
8918 "custom lower FP_ROUND for f16 or bf16");
8919 assert(Subtarget->hasBF16ConversionInsts() &&
"f32 -> bf16 is legal");
8936 EVT VT =
Op.getValueType();
8938 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8939 bool IsIEEEMode =
Info->getMode().IEEE;
8945 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8948 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8949 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8950 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8951 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8957SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(
SDValue Op,
8959 EVT VT =
Op.getValueType();
8961 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
8962 bool IsIEEEMode =
Info->getMode().IEEE;
8964 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8967 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8968 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8969 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8970 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8977 EVT VT =
Op.getValueType();
8980 SDValue
Exp =
Op.getOperand(IsStrict ? 2 : 1);
8981 EVT ExpVT =
Exp.getValueType();
8982 if (ExpVT == MVT::i16)
9003 {
Op.getOperand(0),
Op.getOperand(1), TruncExp});
9010 switch (
Op->getOpcode()) {
9043SITargetLowering::promoteUniformUnaryOpToI32(
SDValue Op,
9044 DAGCombinerInfo &DCI)
const {
9045 EVT OpTy =
Op.getValueType();
9046 SelectionDAG &DAG = DCI.DAG;
9053 SDValue Input =
Op.getOperand(0);
9055 Input = DAG.
getNode(ExtOp,
DL, ExtTy, Input);
9057 SDValue NewVal = DAG.
getNode(
Op.getOpcode(),
DL, ExtTy, Input);
9063 DAGCombinerInfo &DCI)
const {
9064 const unsigned Opc =
Op.getOpcode();
9073 :
Op->getOperand(0).getValueType();
9074 auto &DAG = DCI.DAG;
9077 if (DCI.isBeforeLegalizeOps() ||
9085 LHS =
Op->getOperand(1);
9086 RHS =
Op->getOperand(2);
9088 LHS =
Op->getOperand(0);
9089 RHS =
Op->getOperand(1);
9124 SDValue Mag =
Op.getOperand(0);
9130 SDValue Sign =
Op.getOperand(1);
9133 if (MagVT == SignVT)
9143 SDValue SignShifted =
9154 EVT VT =
Op.getValueType();
9160 assert(VT == MVT::i64 &&
"The following code is a special for s_mul_u64");
9187 if (
Op->isDivergent())
9190 SDValue Op0 =
Op.getOperand(0);
9191 SDValue Op1 =
Op.getOperand(1);
9200 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9202 DAG.
getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9205 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9207 DAG.
getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9213 EVT VT =
Op.getValueType();
9215 SDValue
LHS =
Op.getOperand(0);
9216 SDValue
RHS =
Op.getOperand(1);
9220 const APInt &
C = RHSC->getAPIntValue();
9222 if (
C.isPowerOf2()) {
9224 bool UseArithShift =
isSigned && !
C.isMinSignedValue();
9225 SDValue ShiftAmt = DAG.
getConstant(
C.logBase2(), SL, MVT::i32);
9251 if (
Op->isDivergent()) {
9255 if (Subtarget->hasSMulHi()) {
9266 if (!Subtarget->hasTrapHandler() ||
9268 return lowerTrapEndpgm(
Op, DAG);
9270 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(
Op, DAG)
9271 : lowerTrapHsaQueuePtr(
Op, DAG);
9276 SDValue Chain =
Op.getOperand(0);
9277 return DAG.
getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9281SITargetLowering::loadImplicitKernelArgument(
SelectionDAG &DAG,
MVT VT,
9283 ImplicitParameter Param)
const {
9287 MachinePointerInfo PtrInfo =
9297 SDValue Chain =
Op.getOperand(0);
9304 loadImplicitKernelArgument(DAG, MVT::i64, SL,
Align(8),
QUEUE_PTR);
9307 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9310 if (UserSGPR == AMDGPU::NoRegister) {
9321 SDValue SGPR01 = DAG.
getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9322 SDValue ToReg = DAG.
getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9327 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9332 SDValue Chain =
Op.getOperand(0);
9336 if (Subtarget->hasPrivEnabledTrap2NopBug())
9337 return DAG.
getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9341 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9346 SDValue Chain =
Op.getOperand(0);
9349 if (!Subtarget->hasTrapHandler() ||
9353 "debugtrap handler not supported",
9361 return DAG.
getNode(AMDGPUISD::TRAP, SL, MVT::Other,
Ops);
9371 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
9372 SmallSet<Register, 8> SGPRInputRegs;
9374 unsigned NumVals = 0;
9377 const InlineAsm::Flag
Flags(
Op.getConstantOperandVal(
I));
9378 NumVals =
Flags.getNumOperandRegisters();
9382 NumVals > 0 &&
Flags.hasRegClassConstraint(RCID) &&
9383 TRI->isSGPRClass(
TRI->getRegClass(RCID));
9385 for (
unsigned J = 0; J < NumVals; ++J) {
9386 SDValue Val =
Op.getOperand(
I + 1 + J);
9387 if (
const RegisterSDNode *RegNode =
9396 if (SGPRInputRegs.
empty())
9401 SDNode *
N =
Op.getOperand(
NumOps - 1).getNode();
9405 SDValue SrcVal =
N->getOperand(2);
9409 SDValue ReadFirstLaneID =
9411 SDValue ReadFirstLane =
9413 ReadFirstLaneID, SrcVal);
9417 if (
N->getNumOperands() > 3)
9418 Ops.push_back(
N->getOperand(3));
9424 SDNode *
Next =
nullptr;
9425 for (
unsigned I = 0,
E =
N->getNumOperands();
I !=
E; ++
I) {
9426 if (
N->getOperand(
I).getValueType() == MVT::Glue) {
9427 Next =
N->getOperand(
I).getNode();
9437SDValue SITargetLowering::getSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9439 unsigned BaseAS = AS;
9444 SDValue Aperture = getBaseSegmentAperture(BaseAS,
DL, DAG);
9454SDValue SITargetLowering::getBaseSegmentAperture(
unsigned AS,
const SDLoc &
DL,
9458 if (Subtarget->hasApertureRegs()) {
9459 const unsigned ApertureRegNo =
9460 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9461 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9462 !Subtarget->hasGloballyAddressableScratch()) &&
9463 "Cannot use src_private_base with globally addressable scratch!");
9483 return loadImplicitKernelArgument(DAG, MVT::i32,
DL,
Align(4), Param);
9487 SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
9489 if (UserSGPR == AMDGPU::NoRegister) {
9500 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9534 const AMDGPUTargetMachine &TM =
9538 unsigned SrcAS = ASC->getSrcAddressSpace();
9539 SDValue Src = ASC->getOperand(0);
9540 unsigned DestAS = ASC->getDestAddressSpace();
9541 bool IsNonNull = ASC->getFlags().hasNonNull();
9543 SDValue FlatNullPtr = DAG.
getConstant(0, SL, MVT::i64);
9552 Subtarget->hasGloballyAddressableScratch()) {
9555 SDValue FlatScratchBaseLo(
9557 AMDGPU::S_MOV_B32, SL, MVT::i32,
9558 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9567 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9581 Subtarget->hasGloballyAddressableScratch()) {
9585 SDValue ThreadID = DAG.
getConstant(0, SL, MVT::i32);
9590 if (Subtarget->isWave64())
9596 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9602 SDValue FlatScratchBase = {
9604 AMDGPU::S_MOV_B64, SL, MVT::i64,
9605 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9607 CvtPtr = DAG.
getNode(
ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9609 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9619 SDValue SegmentNullPtr = DAG.
getConstant(NullVal, SL, MVT::i32);
9630 Op.getValueType() == MVT::i64) {
9631 const SIMachineFunctionInfo *
Info =
9633 if (
Info->get32BitAddressHighBits() == 0)
9642 Src.getValueType() == MVT::i64)
9658 SDValue Vec =
Op.getOperand(0);
9659 SDValue Ins =
Op.getOperand(1);
9660 SDValue Idx =
Op.getOperand(2);
9670 assert(InsNumElts % 2 == 0 &&
"expect legal vector types");
9675 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9677 MVT::i32, InsNumElts / 2);
9682 for (
unsigned I = 0;
I != InsNumElts / 2; ++
I) {
9684 if (InsNumElts == 2) {
9697 for (
unsigned I = 0;
I != InsNumElts; ++
I) {
9708 SDValue Vec =
Op.getOperand(0);
9709 SDValue InsVal =
Op.getOperand(1);
9710 SDValue Idx =
Op.getOperand(2);
9720 if (NumElts == 4 && EltSize == 16 && KIdx) {
9731 unsigned Idx = KIdx->getZExtValue();
9732 bool InsertLo = Idx < 2;
9733 SDValue InsHalf = DAG.
getNode(
9736 DAG.
getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9742 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9755 assert(VecSize <= 64 &&
"Expected target vector size to be <= 64 bits");
9763 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9790 EVT ResultVT =
Op.getValueType();
9791 SDValue Vec =
Op.getOperand(0);
9792 SDValue Idx =
Op.getOperand(1);
9803 if (SDValue Combined = performExtractVectorEltCombine(
Op.getNode(), DCI))
9806 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9810 if (VecSize == 128) {
9811 SDValue V2 = DAG.
getBitcast(MVT::v2i64, Vec);
9818 }
else if (VecSize == 256) {
9819 SDValue V2 = DAG.
getBitcast(MVT::v4i64, Vec);
9821 for (
unsigned P = 0;
P < 4; ++
P) {
9827 Parts[0], Parts[1]));
9829 Parts[2], Parts[3]));
9833 SDValue V2 = DAG.
getBitcast(MVT::v8i64, Vec);
9835 for (
unsigned P = 0;
P < 8; ++
P) {
9842 Parts[0], Parts[1], Parts[2], Parts[3]));
9845 Parts[4], Parts[5], Parts[6], Parts[7]));
9851 SDValue IdxMask = DAG.
getConstant(NElem / 2 - 1, SL, IdxVT);
9865 Src = DAG.
getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9875 SDValue ScaledIdx = DAG.
getNode(
ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9880 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9890 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9895 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9896 !(Mask[Elt + 1] & 1);
9902 EVT ResultVT =
Op.getValueType();
9905 const int NewSrcNumElts = 2;
9907 int SrcNumElts =
Op.getOperand(0).getValueType().getVectorNumElements();
9923 const bool ShouldUseConsecutiveExtract = EltVT.
getSizeInBits() == 16;
9945 if (ShouldUseConsecutiveExtract &&
9948 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9949 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9960 SDValue SrcOp1 = SrcOp0;
9961 if (Idx0 >= SrcNumElts) {
9966 if (Idx1 >= SrcNumElts) {
9971 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9972 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9980 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9981 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9983 SDValue Result0 = SubVec0;
9984 SDValue Result1 = SubVec0;
9986 if (SubVec0 != SubVec1) {
9987 NewMaskIdx1 += NewSrcNumElts;
9994 {NewMaskIdx0, NewMaskIdx1});
9999 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10000 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10001 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10002 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10020 SDValue SVal =
Op.getOperand(0);
10021 EVT ResultVT =
Op.getValueType();
10023 SDValue UndefVal = DAG.
getPOISON(SValVT);
10037 EVT VT =
Op.getValueType();
10039 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10040 assert(!Subtarget->hasVOP3PInsts() &&
"this should be legal");
10042 SDValue
Lo =
Op.getOperand(0);
10043 SDValue
Hi =
Op.getOperand(1);
10046 if (
Hi.isUndef()) {
10074 for (
unsigned P = 0;
P < NumParts; ++
P) {
10076 PartVT, SL, {
Op.getOperand(
P * 2),
Op.getOperand(
P * 2 + 1)});
10102 if (!Subtarget->isAmdHsaOS())
10145 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET64,
DL, PtrVT, Ptr);
10154 return DAG.
getNode(AMDGPUISD::PC_ADD_REL_OFFSET,
DL, PtrVT, PtrLo, PtrHi);
10162 EVT PtrVT =
Op.getValueType();
10164 const GlobalValue *GV = GSD->
getGlobal();
10177 assert(PtrVT == MVT::i32 &&
"32-bit pointer is expected.");
10192 return SDValue(DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, GA), 0);
10198 return DAG.
getNode(AMDGPUISD::LDS,
DL, MVT::i32, GA);
10201 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10202 if (Subtarget->has64BitLiterals()) {
10211 AddrLo = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrLo), 0};
10215 AddrHi = {DAG.
getMachineNode(AMDGPU::S_MOV_B32,
DL, MVT::i32, AddrHi), 0};
10233 MachinePointerInfo PtrInfo =
10246 Fn,
"unsupported external symbol",
Op.getDebugLoc()));
10268 unsigned Offset)
const {
10270 SDValue Param = lowerKernargMemParameter(
10281 "non-hsa intrinsic with hsa target",
DL.getDebugLoc()));
10289 "intrinsic not supported on subtarget",
DL.getDebugLoc()));
10297 unsigned NumElts = Elts.
size();
10299 if (NumElts <= 12) {
10303 Type = MVT::v16f32;
10308 for (
unsigned i = 0; i < Elts.
size(); ++i) {
10314 for (
unsigned i = Elts.
size(); i < NumElts; ++i)
10323 SDValue Src,
int ExtraElts) {
10324 EVT SrcVT = Src.getValueType();
10334 while (ExtraElts--)
10345 bool Unpacked,
bool IsD16,
int DMaskPop,
10346 int NumVDataDwords,
bool IsAtomicPacked16Bit,
10350 EVT ReqRetVT = ResultTypes[0];
10352 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10353 ? (ReqRetNumElts + 1) / 2
10356 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10359 NumDataDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, NumDataDwords);
10362 MaskPopDwords == 1 ? MVT::i32 :
MVT::getVectorVT(MVT::i32, MaskPopDwords);
10367 if (DMaskPop > 0 &&
Data.getValueType() != MaskPopVT) {
10371 SDValue(Result, 0), ZeroIdx);
10374 SDValue(Result, 0), ZeroIdx);
10378 if (DataDwordVT.
isVector() && !IsAtomicPacked16Bit)
10380 NumDataDwords - MaskPopDwords);
10385 EVT LegalReqRetVT = ReqRetVT;
10387 if (!
Data.getValueType().isInteger())
10389 Data.getValueType().changeTypeToInteger(),
Data);
10410 if (Result->getNumValues() == 1)
10417 SDValue *LWE,
bool &IsTexFail) {
10437 unsigned DimIdx,
unsigned EndIdx,
10438 unsigned NumGradients) {
10440 for (
unsigned I = DimIdx;
I < EndIdx;
I++) {
10448 if (((
I + 1) >= EndIdx) ||
10449 ((NumGradients / 2) % 2 == 1 && (
I == DimIdx + (NumGradients / 2) - 1 ||
10450 I == DimIdx + NumGradients - 1))) {
10482 !
Op.getNode()->hasAnyUseOfValue(0))
10484 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10495 ResultTypes.erase(&ResultTypes[0]);
10497 bool IsD16 =
false;
10498 bool IsG16 =
false;
10499 bool IsA16 =
false;
10501 int NumVDataDwords = 0;
10502 bool AdjustRetType =
false;
10503 bool IsAtomicPacked16Bit =
false;
10506 const unsigned ArgOffset = WithChain ? 2 : 1;
10509 unsigned DMaskLanes = 0;
10511 if (BaseOpcode->
Atomic) {
10512 VData =
Op.getOperand(2);
10514 IsAtomicPacked16Bit =
10515 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10516 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10517 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10518 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10523 "unsupported image atomic data type");
10528 SDValue VData2 =
Op.getOperand(3);
10535 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10537 DMask = Is64Bit ? 0xf : 0x3;
10538 NumVDataDwords = Is64Bit ? 4 : 2;
10540 DMask = Is64Bit ? 0x3 : 0x1;
10541 NumVDataDwords = Is64Bit ? 2 : 1;
10544 DMask =
Op->getConstantOperandVal(ArgOffset + Intr->
DMaskIndex);
10547 if (BaseOpcode->
Store) {
10548 VData =
Op.getOperand(2);
10552 if (StoreScalarVT != MVT::f16 && StoreScalarVT.
getSizeInBits() != 32 &&
10555 "unsupported image store data type");
10557 if (StoreScalarVT == MVT::f16) {
10558 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10562 VData = handleD16VData(VData, DAG,
true);
10565 NumVDataDwords = (VData.
getValueType().getSizeInBits() + 31) / 32;
10566 }
else if (!BaseOpcode->
NoReturn) {
10571 if (LoadScalarVT != MVT::f16 && LoadScalarVT.
getSizeInBits() != 32 &&
10574 "unsupported image load data type");
10576 if (LoadScalarVT == MVT::f16) {
10577 if (!Subtarget->hasD16Images() || !BaseOpcode->
HasD16)
10585 (!LoadVT.
isVector() && DMaskLanes > 1))
10591 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10592 !(BaseOpcode->
Gather4 && Subtarget->hasImageGather4D16Bug()))
10593 NumVDataDwords = (DMaskLanes + 1) / 2;
10595 NumVDataDwords = DMaskLanes;
10597 AdjustRetType =
true;
10601 unsigned VAddrEnd = ArgOffset + Intr->
VAddrEnd;
10608 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10609 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10611 VAddrVT =
Op.getOperand(ArgOffset + Intr->
CoordStart).getSimpleValueType();
10613 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10614 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10618 if (IsA16 && (
Op.getOperand(ArgOffset +
I).getValueType() == MVT::f16)) {
10624 {
Op.getOperand(ArgOffset +
I), DAG.
getPOISON(MVT::f16)});
10628 "Bias needs to be converted to 16 bit in A16 mode");
10633 if (BaseOpcode->
Gradients && !
ST->hasG16() && (IsA16 != IsG16)) {
10637 dbgs() <<
"Failed to lower image intrinsic: 16 bit addresses "
10638 "require 16 bit args for both gradients and addresses");
10643 if (!
ST->hasA16()) {
10644 LLVM_DEBUG(
dbgs() <<
"Failed to lower image intrinsic: Target does not "
10645 "support 16 bit addresses\n");
10655 if (BaseOpcode->
Gradients && IsG16 &&
ST->hasG16()) {
10657 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10659 IntrOpcode = G16MappingInfo->
G16;
10682 for (
unsigned I = ArgOffset + Intr->
CoordStart;
I < VAddrEnd;
I++)
10700 const unsigned NSAMaxSize =
ST->getNSAMaxSize(BaseOpcode->
Sampler);
10701 const bool HasPartialNSAEncoding =
ST->hasPartialNSAEncoding();
10702 const bool UseNSA =
ST->hasNSAEncoding() &&
10703 VAddrs.
size() >=
ST->getNSAThreshold(MF) &&
10704 (VAddrs.
size() <= NSAMaxSize || HasPartialNSAEncoding);
10705 const bool UsePartialNSA =
10706 UseNSA && HasPartialNSAEncoding && VAddrs.
size() > NSAMaxSize;
10709 if (UsePartialNSA) {
10711 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10712 }
else if (!UseNSA) {
10723 Op.getConstantOperandVal(ArgOffset + Intr->
UnormIndex);
10725 Unorm = UnormConst ? True : False;
10731 bool IsTexFail =
false;
10732 if (!
parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10741 NumVDataDwords = 1;
10743 NumVDataDwords += 1;
10744 AdjustRetType =
true;
10749 if (AdjustRetType) {
10752 if (DMaskLanes == 0 && !BaseOpcode->
Store) {
10761 MVT::i32, NumVDataDwords)
10764 ResultTypes[0] = NewVT;
10765 if (ResultTypes.size() == 3) {
10769 ResultTypes.erase(&ResultTypes[1]);
10783 Ops.push_back(VData);
10784 if (UsePartialNSA) {
10786 Ops.push_back(VAddr);
10790 Ops.push_back(VAddr);
10791 SDValue Rsrc =
Op.getOperand(ArgOffset + Intr->
RsrcIndex);
10793 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10795 Ops.push_back(Rsrc);
10797 SDValue Samp =
Op.getOperand(ArgOffset + Intr->
SampIndex);
10800 Ops.push_back(Samp);
10805 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10806 Ops.push_back(Unorm);
10808 Ops.push_back(IsA16 &&
10809 ST->hasFeature(AMDGPU::FeatureR128A16)
10813 Ops.push_back(IsA16 ? True : False);
10815 if (!Subtarget->hasGFX90AInsts())
10816 Ops.push_back(TFE);
10820 "TFE is not supported on this GPU",
DL.getDebugLoc()));
10823 if (!IsGFX12Plus || BaseOpcode->
Sampler || BaseOpcode->
MSAA)
10824 Ops.push_back(LWE);
10826 Ops.push_back(DimInfo->
DA ? True : False);
10828 Ops.push_back(IsD16 ? True : False);
10830 Ops.push_back(
Op.getOperand(0));
10832 int NumVAddrDwords =
10838 NumVDataDwords, NumVAddrDwords);
10839 }
else if (IsGFX12Plus) {
10841 NumVDataDwords, NumVAddrDwords);
10842 }
else if (IsGFX11Plus) {
10844 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10845 : AMDGPU::MIMGEncGfx11Default,
10846 NumVDataDwords, NumVAddrDwords);
10847 }
else if (IsGFX10Plus) {
10849 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10850 : AMDGPU::MIMGEncGfx10Default,
10851 NumVDataDwords, NumVAddrDwords);
10853 if (Subtarget->hasGFX90AInsts()) {
10855 NumVDataDwords, NumVAddrDwords);
10856 if (Opcode == -1) {
10858 DAG,
Op, OrigResultTypes,
DL,
10859 "requested image instruction is not supported on this GPU");
10862 if (Opcode == -1 &&
10865 NumVDataDwords, NumVAddrDwords);
10868 NumVDataDwords, NumVAddrDwords);
10875 MachineMemOperand *MemRef = MemOp->getMemOperand();
10882 {DAG.
getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)},
DL);
10884 return SDValue(NewNode, 0);
10894 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10895 NumVDataDwords, IsAtomicPacked16Bit,
DL);
10904 bool HasChainResult = MMO !=
nullptr;
10908 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10909 Subtarget->hasScalarSubwordLoads();
10912 MF.
getFunction(),
"unsupported s_buffer_load result type",
10913 DL.getDebugLoc()));
10914 EVT ResultTypes[] = {VT, MVT::Other};
10916 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain,
DL);
10919 if (!HasChainResult) {
10931 if (!
Offset->isDivergent()) {
10932 SDValue
Ops[] = {Chain, Rsrc,
Offset, CachePolicy};
10939 auto HandleScalarSubwordLoads = [&](
unsigned Opcode) -> SDValue {
10941 Opcode,
DL, DAG.
getVTList(MVT::i32, MVT::Other),
Ops, MemVT, MMO);
10944 if (HasChainResult)
10948 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10949 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10951 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10952 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10957 !Subtarget->hasScalarDwordx3Loads()) {
10961 AMDGPUISD::SBUFFER_LOAD,
DL, DAG.
getVTList(WidenedVT, MVT::Other),
10966 if (HasChainResult)
10988 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10989 Subtarget->hasScalarSubwordLoads()) {
10991 SDValue
Load = handleByteShortBufferLoads(DAG, MemVT,
DL,
Ops, MMO);
10993 if (HasChainResult)
10999 unsigned NumLoads = 1;
11005 if (NumElts == 8 || NumElts == 16) {
11006 NumLoads = NumElts / 4;
11010 SDVTList VTList = DAG.
getVTList({LoadVT, MVT::Other});
11015 NumLoads > 1 ?
Align(16 * NumLoads) :
Align(4));
11019 for (
unsigned i = 0; i < NumLoads; ++i) {
11022 Loads.
push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD,
DL, VTList,
Ops,
11023 LoadVT, LoadMMO, DAG));
11026 if (NumElts == 8 || NumElts == 16) {
11028 if (HasChainResult) {
11030 for (SDValue
Load : Loads)
11043 if (!Subtarget->hasArchitectedSGPRs())
11048 return DAG.
getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11055 unsigned Width)
const {
11057 using namespace AMDGPU::Hwreg;
11059 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11079 SDValue Val =
loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11098 SDValue Src =
Op.getOperand(0);
11099 EVT DstVT =
Op.getValueType();
11101 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11102 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11106 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11108 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11121SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(
SDValue Op,
11130 const bool HasE5M3ConversionInsts =
11131 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11132 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11136 EVT DstVT =
Op.getValueType();
11140 !Subtarget->hasFP8F16ConversionInsts())
11148 SDValue Src =
Op.getOperand(0);
11150 "only the v2f32 vector result is custom lowered");
11156 auto ConvertByte = [&](
unsigned ByteSel) {
11157 return DAG.
getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11162 return ConvertByte(0);
11163 return DAG.
getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11167 SDValue Src =
Op.getOperand(0);
11168 if (Src.getValueType() != MVT::i32) {
11178 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11179 return lowerFromFP8(
Op, IsBF8, DAG);
11186 SDValue Src =
Op.getOperand(0);
11187 EVT ResVT =
Op.getValueType();
11188 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11189 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11190 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11192 "only the v2i8 vector result is custom lowered");
11196 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11197 SDValue Bytes = DAG.
getNode(
Opc, SL, MVT::i16, Src);
11201 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11202 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11203 : AMDGPUISD::CVT_PK_FP8_F32;
11204 SDValue PoisonI32 = DAG.
getPOISON(MVT::i32);
11211 DAG.
getNode(
Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11223SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(
SDValue Op,
11232 const bool HasE5M3ConversionInsts =
11233 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11234 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11244 if (!IsE5M3 &&
Op.getConstantOperandVal(3) != 0)
11247 EVT SrcEltVT =
Op.getOperand(0).getValueType().getScalarType();
11250 if (SrcEltVT == MVT::f32)
11251 return lowerToFP8(
Op, IsBF8, IsE5M3, DAG);
11252 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11253 Subtarget->hasF16FP8ConversionInsts()) {
11256 if (!
Op.getValueType().isVector())
11258 return lowerToFP8(
Op, IsBF8,
false, DAG);
11266 auto *MFI = MF.
getInfo<SIMachineFunctionInfo>();
11268 EVT VT =
Op.getValueType();
11270 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
11274 switch (IntrinsicID) {
11275 case Intrinsic::amdgcn_wave_reduce_min:
11276 case Intrinsic::amdgcn_wave_reduce_umin:
11277 case Intrinsic::amdgcn_wave_reduce_fmin:
11278 case Intrinsic::amdgcn_wave_reduce_max:
11279 case Intrinsic::amdgcn_wave_reduce_umax:
11280 case Intrinsic::amdgcn_wave_reduce_fmax:
11281 case Intrinsic::amdgcn_wave_reduce_add:
11282 case Intrinsic::amdgcn_wave_reduce_fadd:
11283 case Intrinsic::amdgcn_wave_reduce_sub:
11284 case Intrinsic::amdgcn_wave_reduce_fsub:
11285 case Intrinsic::amdgcn_wave_reduce_and:
11286 case Intrinsic::amdgcn_wave_reduce_or:
11287 case Intrinsic::amdgcn_wave_reduce_xor: {
11288 EVT SrcVT =
Op.getOperand(1).getValueType();
11291 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11292 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11293 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11294 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11298 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11299 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11300 SDValue ExtendedSrc = DAG.
getNode(ExtOpc,
DL, ExtType,
Op.getOperand(1));
11301 SDValue Strategy =
Op.getOperand(2);
11303 Op.getOperand(0), ExtendedSrc, Strategy);
11312 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11315 return getPreloadedValue(DAG, *MFI, VT,
11318 case Intrinsic::amdgcn_dispatch_ptr:
11319 case Intrinsic::amdgcn_queue_ptr: {
11320 if (!Subtarget->isAmdHsaOrMesa(MF.
getFunction())) {
11322 MF.
getFunction(),
"unsupported hsa intrinsic without hsa target",
11323 DL.getDebugLoc()));
11327 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11330 return getPreloadedValue(DAG, *MFI, VT, RegID);
11332 case Intrinsic::amdgcn_implicitarg_ptr: {
11334 return getImplicitArgPtr(DAG,
DL);
11335 return getPreloadedValue(DAG, *MFI, VT,
11338 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11344 return getPreloadedValue(DAG, *MFI, VT,
11347 case Intrinsic::amdgcn_dispatch_id: {
11350 case Intrinsic::amdgcn_rcp:
11351 return DAG.
getNode(AMDGPUISD::RCP,
DL, VT,
Op.getOperand(1));
11352 case Intrinsic::amdgcn_rsq:
11353 return DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11354 case Intrinsic::amdgcn_rsq_legacy:
11358 case Intrinsic::amdgcn_rcp_legacy:
11361 return DAG.
getNode(AMDGPUISD::RCP_LEGACY,
DL, VT,
Op.getOperand(1));
11362 case Intrinsic::amdgcn_fma_legacy:
11363 case Intrinsic::amdgcn_sudot4:
11364 case Intrinsic::amdgcn_sudot8:
11365 case Intrinsic::amdgcn_tanh:
11367 case Intrinsic::amdgcn_rsq_clamp: {
11369 return DAG.
getNode(AMDGPUISD::RSQ_CLAMP,
DL, VT,
Op.getOperand(1));
11375 SDValue Rsq = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT,
Op.getOperand(1));
11381 case Intrinsic::r600_read_ngroups_x:
11382 if (Subtarget->isAmdHsaOS())
11385 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11388 case Intrinsic::r600_read_ngroups_y:
11389 if (Subtarget->isAmdHsaOS())
11392 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11395 case Intrinsic::r600_read_ngroups_z:
11396 if (Subtarget->isAmdHsaOS())
11399 return lowerKernargMemParameter(DAG, VT, VT,
DL, DAG.
getEntryNode(),
11402 case Intrinsic::r600_read_local_size_x:
11403 if (Subtarget->isAmdHsaOS())
11406 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11408 case Intrinsic::r600_read_local_size_y:
11409 if (Subtarget->isAmdHsaOS())
11412 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11414 case Intrinsic::r600_read_local_size_z:
11415 if (Subtarget->isAmdHsaOS())
11418 return lowerImplicitZextParam(DAG,
Op, MVT::i16,
11420 case Intrinsic::amdgcn_workgroup_id_x:
11421 return lowerWorkGroupId(DAG, *MFI, VT,
11425 case Intrinsic::amdgcn_workgroup_id_y:
11426 return lowerWorkGroupId(DAG, *MFI, VT,
11430 case Intrinsic::amdgcn_workgroup_id_z:
11431 return lowerWorkGroupId(DAG, *MFI, VT,
11435 case Intrinsic::amdgcn_cluster_id_x:
11436 return Subtarget->hasClusters()
11437 ? getPreloadedValue(DAG, *MFI, VT,
11439 : DAG.getPOISON(VT);
11440 case Intrinsic::amdgcn_cluster_id_y:
11441 return Subtarget->hasClusters()
11442 ? getPreloadedValue(DAG, *MFI, VT,
11445 case Intrinsic::amdgcn_cluster_id_z:
11446 return Subtarget->hasClusters()
11447 ? getPreloadedValue(DAG, *MFI, VT,
11450 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11451 return Subtarget->hasClusters()
11452 ? getPreloadedValue(
11456 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11457 return Subtarget->hasClusters()
11458 ? getPreloadedValue(
11462 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11463 return Subtarget->hasClusters()
11464 ? getPreloadedValue(
11468 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11469 return Subtarget->hasClusters()
11472 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11473 return Subtarget->hasClusters()
11474 ? getPreloadedValue(
11478 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11479 return Subtarget->hasClusters()
11480 ? getPreloadedValue(
11484 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11485 return Subtarget->hasClusters()
11486 ? getPreloadedValue(
11490 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11491 return Subtarget->hasClusters()
11492 ? getPreloadedValue(
11496 case Intrinsic::amdgcn_wave_id:
11497 return lowerWaveID(DAG,
Op);
11498 case Intrinsic::amdgcn_lds_kernel_id: {
11500 return getLDSKernelId(DAG,
DL);
11501 return getPreloadedValue(DAG, *MFI, VT,
11504 case Intrinsic::amdgcn_workitem_id_x:
11505 return lowerWorkitemID(DAG,
Op, 0, MFI->getArgInfo().WorkItemIDX);
11506 case Intrinsic::amdgcn_workitem_id_y:
11507 return lowerWorkitemID(DAG,
Op, 1, MFI->getArgInfo().WorkItemIDY);
11508 case Intrinsic::amdgcn_workitem_id_z:
11509 return lowerWorkitemID(DAG,
Op, 2, MFI->getArgInfo().WorkItemIDZ);
11510 case Intrinsic::amdgcn_wavefrontsize:
11512 SDLoc(
Op), MVT::i32);
11513 case Intrinsic::amdgcn_s_buffer_load: {
11514 unsigned CPol =
Op.getConstantOperandVal(3);
11522 Op.getOperand(2),
Op.getOperand(3), DAG);
11524 case Intrinsic::amdgcn_fdiv_fast:
11525 return lowerFDIV_FAST(
Op, DAG);
11526 case Intrinsic::amdgcn_sin:
11527 return DAG.
getNode(AMDGPUISD::SIN_HW,
DL, VT,
Op.getOperand(1));
11529 case Intrinsic::amdgcn_cos:
11530 return DAG.
getNode(AMDGPUISD::COS_HW,
DL, VT,
Op.getOperand(1));
11532 case Intrinsic::amdgcn_mul_u24:
11533 return DAG.
getNode(AMDGPUISD::MUL_U24,
DL, VT,
Op.getOperand(1),
11535 case Intrinsic::amdgcn_mul_i24:
11536 return DAG.
getNode(AMDGPUISD::MUL_I24,
DL, VT,
Op.getOperand(1),
11539 case Intrinsic::amdgcn_log_clamp: {
11545 case Intrinsic::amdgcn_fract:
11546 return DAG.
getNode(AMDGPUISD::FRACT,
DL, VT,
Op.getOperand(1));
11548 case Intrinsic::amdgcn_class: {
11549 SDValue Src =
Op.getOperand(1);
11550 EVT SrcVT = Src.getValueType();
11551 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11552 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11556 "llvm.amdgcn.class only supports f16, f32, and f64",
11557 DL.getDebugLoc()));
11560 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, VT, Src,
Op.getOperand(2));
11562 case Intrinsic::amdgcn_div_fmas:
11563 return DAG.
getNode(AMDGPUISD::DIV_FMAS,
DL, VT,
Op.getOperand(1),
11564 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11566 case Intrinsic::amdgcn_div_fixup:
11567 return DAG.
getNode(AMDGPUISD::DIV_FIXUP,
DL, VT,
Op.getOperand(1),
11568 Op.getOperand(2),
Op.getOperand(3));
11570 case Intrinsic::amdgcn_div_scale: {
11575 SDValue Numerator =
Op.getOperand(1);
11576 SDValue Denominator =
Op.getOperand(2);
11583 SDValue Src0 =
Param->isAllOnes() ? Numerator : Denominator;
11585 return DAG.
getNode(AMDGPUISD::DIV_SCALE,
DL,
Op->getVTList(), Src0,
11586 Denominator, Numerator);
11588 case Intrinsic::amdgcn_ballot:
11590 case Intrinsic::amdgcn_fmed3:
11591 return DAG.
getNode(AMDGPUISD::FMED3,
DL, VT,
Op.getOperand(1),
11592 Op.getOperand(2),
Op.getOperand(3),
Op->getFlags());
11593 case Intrinsic::amdgcn_fdot2:
11594 return DAG.
getNode(AMDGPUISD::FDOT2,
DL, VT,
Op.getOperand(1),
11595 Op.getOperand(2),
Op.getOperand(3),
Op.getOperand(4));
11596 case Intrinsic::amdgcn_fmul_legacy:
11597 return DAG.
getNode(AMDGPUISD::FMUL_LEGACY,
DL, VT,
Op.getOperand(1),
11599 case Intrinsic::amdgcn_sbfe:
11600 case Intrinsic::amdgcn_ubfe:
11602 case Intrinsic::amdgcn_cvt_pkrtz:
11603 case Intrinsic::amdgcn_cvt_pknorm_i16:
11604 case Intrinsic::amdgcn_cvt_pknorm_u16:
11605 case Intrinsic::amdgcn_cvt_pk_i16:
11606 case Intrinsic::amdgcn_cvt_pk_u16: {
11608 EVT VT =
Op.getValueType();
11611 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11612 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11613 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11614 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11615 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11616 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11617 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11618 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11620 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11623 return DAG.
getNode(Opcode,
DL, VT,
Op.getOperand(1),
Op.getOperand(2));
11626 DAG.
getNode(Opcode,
DL, MVT::i32,
Op.getOperand(1),
Op.getOperand(2));
11629 case Intrinsic::amdgcn_fmad_ftz:
11630 return DAG.
getNode(AMDGPUISD::FMAD_FTZ,
DL, VT,
Op.getOperand(1),
11631 Op.getOperand(2),
Op.getOperand(3));
11633 case Intrinsic::amdgcn_if_break:
11635 Op->getOperand(1),
Op->getOperand(2)),
11638 case Intrinsic::amdgcn_groupstaticsize: {
11644 const GlobalValue *GV =
11650 case Intrinsic::amdgcn_is_shared:
11651 case Intrinsic::amdgcn_is_private: {
11658 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11662 Subtarget->hasGloballyAddressableScratch()) {
11663 SDValue FlatScratchBaseHi(
11665 AMDGPU::S_MOV_B32,
DL, MVT::i32,
11666 DAG.
getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11675 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11678 case Intrinsic::amdgcn_perm:
11679 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op.getOperand(1),
11680 Op.getOperand(2),
Op.getOperand(3));
11681 case Intrinsic::amdgcn_reloc_constant: {
11691 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11692 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11693 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11694 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11695 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11696 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11697 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11698 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11699 if (
Op.getOperand(4).getValueType() == MVT::i32)
11705 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11706 Op.getOperand(3), IndexKeyi32);
11708 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11709 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11710 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11711 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11712 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11713 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11714 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11715 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11716 if (
Op.getOperand(4).getValueType() == MVT::i64)
11721 Op.getOperand(4).getValueType() == MVT::v2i32
11725 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11726 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11727 Op.getOperand(6)});
11729 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11730 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11731 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11732 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11733 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11734 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11735 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11738 if (
Op.getOperand(6).getValueType() == IndexKeyTy)
11743 Op.getOperand(6).getValueType().isVector()
11747 Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
11748 Op.getOperand(3),
Op.getOperand(4),
Op.getOperand(5),
11749 IndexKey,
Op.getOperand(7),
Op.getOperand(8)};
11750 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11751 Args.push_back(
Op.getOperand(9));
11754 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11755 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11756 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11757 if (
Op.getOperand(6).getValueType() == MVT::i32)
11763 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11764 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11765 IndexKeyi32, Op.getOperand(7)});
11767 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11768 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11769 unsigned AFmt = (unsigned)
Op.getConstantOperandVal(1);
11770 unsigned BFmt = (unsigned)
Op.getConstantOperandVal(3);
11771 unsigned AScaleFmt = (unsigned)
Op.getConstantOperandVal(8);
11772 unsigned BScaleFmt = (unsigned)
Op.getConstantOperandVal(11);
11776 "invalid matrix and scale format combination in wmma call");
11782 case Intrinsic::amdgcn_readlane:
11783 case Intrinsic::amdgcn_readfirstlane:
11784 case Intrinsic::amdgcn_writelane:
11785 case Intrinsic::amdgcn_permlane16:
11786 case Intrinsic::amdgcn_permlanex16:
11787 case Intrinsic::amdgcn_permlane64:
11788 case Intrinsic::amdgcn_set_inactive:
11789 case Intrinsic::amdgcn_set_inactive_chain_arg:
11790 case Intrinsic::amdgcn_mov_dpp8:
11791 case Intrinsic::amdgcn_update_dpp:
11792 case Intrinsic::amdgcn_permlane_bcast:
11793 case Intrinsic::amdgcn_permlane_up:
11794 case Intrinsic::amdgcn_permlane_down:
11795 case Intrinsic::amdgcn_permlane_xor:
11797 case Intrinsic::amdgcn_dead: {
11799 for (
const EVT ValTy :
Op.getNode()->values())
11803 case Intrinsic::amdgcn_wave_shuffle:
11806 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11808 return lowerImage(
Op, ImageDimIntr, DAG,
false);
11818 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(SOffset))
11819 return DAG.
getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11825 unsigned NewOpcode)
const {
11828 SDValue VData =
Op.getOperand(2);
11832 "unsupported buffer atomic data type");
11834 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11835 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
11853 M->getMemOperand());
11858 unsigned NewOpcode)
const {
11861 SDValue VData =
Op.getOperand(2);
11865 "unsupported buffer atomic data type");
11867 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
11868 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
11886 M->getMemOperand());
11893 unsigned NumOperands =
N->getNumOperands();
11894 if (
N->getOperand(NumOperands - 1) == Zero)
11897 Ops[NumOperands - 1] = Zero;
11903 unsigned IntrID =
Op.getConstantOperandVal(1);
11907 case Intrinsic::amdgcn_cluster_load_b32:
11908 case Intrinsic::amdgcn_cluster_load_b64:
11909 case Intrinsic::amdgcn_cluster_load_b128: {
11910 if (Subtarget->hasGFX1250_STRICT())
11914 case Intrinsic::amdgcn_ds_ordered_add:
11915 case Intrinsic::amdgcn_ds_ordered_swap: {
11917 SDValue Chain =
M->getOperand(0);
11918 SDValue
M0 =
M->getOperand(2);
11919 SDValue
Value =
M->getOperand(3);
11920 unsigned IndexOperand =
M->getConstantOperandVal(7);
11921 unsigned WaveRelease =
M->getConstantOperandVal(8);
11922 unsigned WaveDone =
M->getConstantOperandVal(9);
11924 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11925 IndexOperand &= ~0x3f;
11926 unsigned CountDw = 0;
11929 CountDw = (IndexOperand >> 24) & 0xf;
11930 IndexOperand &= ~(0xf << 24);
11932 if (CountDw < 1 || CountDw > 4) {
11935 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
11936 DL.getDebugLoc()));
11941 if (IndexOperand) {
11944 Fn,
"ds_ordered_count: bad index operand",
DL.getDebugLoc()));
11947 if (WaveDone && !WaveRelease) {
11951 Fn,
"ds_ordered_count: wave_done requires wave_release",
11952 DL.getDebugLoc()));
11955 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11956 unsigned ShaderType =
11958 unsigned Offset0 = OrderedCountIndex << 2;
11959 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11962 Offset1 |= (CountDw - 1) << 6;
11965 Offset1 |= ShaderType << 2;
11967 unsigned Offset = Offset0 | (Offset1 << 8);
11974 M->getVTList(),
Ops,
M->getMemoryVT(),
11975 M->getMemOperand());
11977 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11978 unsigned CPol =
Op.getConstantOperandVal(4);
11985 return lowerSBuffer(
11986 Op.getValueType(),
M->getMemoryVT(),
DL,
Op.getOperand(0),
11987 bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
Op.getOperand(3),
11988 Op.getOperand(4), DAG,
M->getMemOperand());
11990 case Intrinsic::amdgcn_raw_buffer_load:
11991 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11992 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11993 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11994 case Intrinsic::amdgcn_raw_buffer_load_format:
11995 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11996 const bool IsFormat =
11997 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11998 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12000 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12001 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12015 return lowerIntrinsicLoad(M, IsFormat, DAG,
Ops);
12017 case Intrinsic::amdgcn_struct_buffer_load:
12018 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12019 case Intrinsic::amdgcn_struct_buffer_load_format:
12020 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12021 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12022 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12023 const bool IsFormat =
12024 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12025 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12027 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12028 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12043 case Intrinsic::amdgcn_raw_tbuffer_load:
12044 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12046 EVT LoadVT =
Op.getValueType();
12047 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12048 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(3), DAG);
12064 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12066 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12067 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12070 case Intrinsic::amdgcn_struct_tbuffer_load:
12071 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12073 EVT LoadVT =
Op.getValueType();
12074 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12075 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12091 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12093 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT,
DL,
12094 Op->getVTList(),
Ops, LoadVT,
M->getMemOperand(),
12097 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12098 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12099 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12100 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12101 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12102 return lowerStructBufferAtomicIntrin(
Op, DAG,
12103 AMDGPUISD::BUFFER_ATOMIC_FADD);
12104 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12105 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12106 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12107 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12108 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12109 return lowerStructBufferAtomicIntrin(
Op, DAG,
12110 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12111 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12112 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12113 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12114 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12115 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12116 return lowerStructBufferAtomicIntrin(
Op, DAG,
12117 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12118 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12119 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12120 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12121 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12122 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12123 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12124 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12125 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12126 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12127 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12129 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12132 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12133 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12135 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12136 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12137 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12138 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12139 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12140 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12141 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12142 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12144 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12147 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12148 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12150 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12151 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12152 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12153 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12154 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12155 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12156 return lowerStructBufferAtomicIntrin(
Op, DAG,
12157 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12158 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12159 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12160 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12161 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12162 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12163 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12164 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12166 return lowerStructBufferAtomicIntrin(
Op, DAG,
12167 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12168 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12169 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12170 return lowerStructBufferAtomicIntrin(
Op, DAG,
12171 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12172 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12173 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12174 return lowerStructBufferAtomicIntrin(
Op, DAG,
12175 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12176 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12177 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12178 return lowerStructBufferAtomicIntrin(
Op, DAG,
12179 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12180 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12181 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12182 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12183 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12184 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12185 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12186 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12187 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12188 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12189 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12190 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12191 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12192 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12194 return lowerStructBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12195 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12197 return lowerRawBufferAtomicIntrin(
Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12198 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12199 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12200 return lowerStructBufferAtomicIntrin(
Op, DAG,
12201 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12202 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12203 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12204 return lowerRawBufferAtomicIntrin(
Op, DAG,
12205 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12206 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12207 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12208 return lowerStructBufferAtomicIntrin(
Op, DAG,
12209 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12210 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12211 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12212 SDValue Src =
Op.getOperand(2);
12213 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12216 "unsupported buffer atomic data type");
12218 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(4), DAG);
12219 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12233 EVT VT =
Op.getValueType();
12237 Op->getVTList(),
Ops, VT,
12238 M->getMemOperand());
12240 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12241 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12242 SDValue Src =
Op.getOperand(2);
12243 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12246 "unsupported buffer atomic data type");
12248 SDValue Rsrc = bufferRsrcPtrToVector(
Op->getOperand(4), DAG);
12249 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(6), DAG);
12263 EVT VT =
Op.getValueType();
12267 Op->getVTList(),
Ops, VT,
12268 M->getMemOperand());
12270 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12271 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12273 SDValue NodePtr =
M->getOperand(2);
12274 SDValue RayExtent =
M->getOperand(3);
12275 SDValue InstanceMask =
M->getOperand(4);
12276 SDValue RayOrigin =
M->getOperand(5);
12277 SDValue RayDir =
M->getOperand(6);
12278 SDValue
Offsets =
M->getOperand(7);
12279 SDValue TDescr =
M->getOperand(8);
12284 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12285 const unsigned NumVDataDwords = 10;
12286 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12288 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12289 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12290 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12294 Ops.push_back(NodePtr);
12297 {DAG.getBitcast(MVT::i32, RayExtent),
12298 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12299 Ops.push_back(RayOrigin);
12300 Ops.push_back(RayDir);
12301 Ops.push_back(Offsets);
12302 Ops.push_back(TDescr);
12303 Ops.push_back(
M->getChain());
12306 MachineMemOperand *MemRef =
M->getMemOperand();
12308 return SDValue(NewNode, 0);
12310 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12312 SDValue NodePtr =
M->getOperand(2);
12313 SDValue RayExtent =
M->getOperand(3);
12314 SDValue RayOrigin =
M->getOperand(4);
12315 SDValue RayDir =
M->getOperand(5);
12316 SDValue RayInvDir =
M->getOperand(6);
12317 SDValue TDescr =
M->getOperand(7);
12329 const unsigned NumVDataDwords = 4;
12330 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12331 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12332 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12335 const unsigned BaseOpcodes[2][2] = {
12336 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12337 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12338 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12342 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12343 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12344 : AMDGPU::MIMGEncGfx10NSA,
12345 NumVDataDwords, NumVAddrDwords);
12349 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12350 : AMDGPU::MIMGEncGfx10Default,
12351 NumVDataDwords, NumVAddrDwords);
12357 auto packLanes = [&DAG, &
Ops, &
DL](SDValue
Op,
bool IsAligned) {
12360 if (Lanes[0].getValueSizeInBits() == 32) {
12361 for (
unsigned I = 0;
I < 3; ++
I)
12368 Ops.push_back(Lanes[2]);
12370 SDValue Elt0 =
Ops.pop_back_val();
12380 if (UseNSA && IsGFX11Plus) {
12381 Ops.push_back(NodePtr);
12383 Ops.push_back(RayOrigin);
12388 for (
unsigned I = 0;
I < 3; ++
I) {
12391 {DirLanes[I], InvDirLanes[I]})));
12395 Ops.push_back(RayDir);
12396 Ops.push_back(RayInvDir);
12403 Ops.push_back(NodePtr);
12406 packLanes(RayOrigin,
true);
12407 packLanes(RayDir,
true);
12408 packLanes(RayInvDir,
false);
12413 if (NumVAddrDwords > 12) {
12418 SDValue MergedOps =
12421 Ops.push_back(MergedOps);
12424 Ops.push_back(TDescr);
12426 Ops.push_back(
M->getChain());
12429 MachineMemOperand *MemRef =
M->getMemOperand();
12431 return SDValue(NewNode, 0);
12433 case Intrinsic::amdgcn_global_atomic_fmin_num:
12434 case Intrinsic::amdgcn_global_atomic_fmax_num:
12435 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12436 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12443 unsigned Opcode = 0;
12445 case Intrinsic::amdgcn_global_atomic_fmin_num:
12446 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12450 case Intrinsic::amdgcn_global_atomic_fmax_num:
12451 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12458 return DAG.
getAtomic(Opcode, SDLoc(
Op),
M->getMemoryVT(),
M->getVTList(),
12459 Ops,
M->getMemOperand());
12461 case Intrinsic::amdgcn_s_alloc_vgpr: {
12466 SDValue ReadFirstLaneID =
12469 ReadFirstLaneID, NumVGPRs);
12472 Op.getOperand(0),
Op.getOperand(1), NumVGPRs);
12474 case Intrinsic::amdgcn_s_get_barrier_state:
12475 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12476 SDValue Chain =
Op->getOperand(0);
12482 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12483 BarID = BarID & 0x3F;
12484 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12487 Ops.push_back(Chain);
12489 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12490 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12499 return SDValue(NewMI, 0);
12501 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12502 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12503 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12505 SDValue Chain =
Op->getOperand(0);
12506 SDValue Ptr =
Op->getOperand(2);
12507 EVT VT =
Op->getValueType(0);
12511 case Intrinsic::amdgcn_av_load_b128: {
12513 SDValue Chain =
Op->getOperand(0);
12514 SDValue Ptr =
Op->getOperand(2);
12515 EVT VT =
Op->getValueType(0);
12522 case Intrinsic::amdgcn_flat_load_monitor_b32:
12523 case Intrinsic::amdgcn_flat_load_monitor_b64:
12524 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12526 SDValue Chain =
Op->getOperand(0);
12527 SDValue Ptr =
Op->getOperand(2);
12529 Op->getVTList(), {Chain, Ptr},
12532 case Intrinsic::amdgcn_global_load_monitor_b32:
12533 case Intrinsic::amdgcn_global_load_monitor_b64:
12534 case Intrinsic::amdgcn_global_load_monitor_b128: {
12536 SDValue Chain =
Op->getOperand(0);
12537 SDValue Ptr =
Op->getOperand(2);
12539 Op->getVTList(), {Chain, Ptr},
12544 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12546 return lowerImage(
Op, ImageDimIntr, DAG,
true);
12554SDValue SITargetLowering::getMemIntrinsicNode(
unsigned Opcode,
const SDLoc &
DL,
12561 EVT VT = VTList.
VTs[0];
12564 bool IsTFE = VTList.
NumVTs == 3;
12567 unsigned NumOpDWords = NumValueDWords + 1;
12569 SDVTList OpDWordsVTList = DAG.
getVTList(OpDWordsVT, VTList.
VTs[2]);
12570 MachineMemOperand *OpDWordsMMO =
12572 SDValue
Op = getMemIntrinsicNode(Opcode,
DL, OpDWordsVTList,
Ops,
12573 OpDWordsVT, OpDWordsMMO, DAG);
12578 if (!Subtarget->hasDwordx3LoadStores() &&
12579 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12583 SDVTList WidenedVTList = DAG.
getVTList(WidenedVT, VTList.
VTs[1]);
12585 WidenedMemVT, WidenedMMO);
12595 bool ImageStore)
const {
12605 if (Subtarget->hasUnpackedD16VMem()) {
12619 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12630 for (
unsigned I = 0;
I < Elts.
size() / 2;
I += 1) {
12636 if ((NumElements % 2) == 1) {
12638 unsigned I = Elts.
size() / 2;
12654 if (NumElements == 3) {
12673 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12674 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12675 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12676 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12677 case Intrinsic::amdgcn_load_async_to_lds:
12678 case Intrinsic::amdgcn_global_load_async_lds:
12687 SDValue Chain =
Op.getOperand(0);
12688 unsigned IntrinsicID =
Op.getConstantOperandVal(1);
12690 switch (IntrinsicID) {
12691 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12692 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12693 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12694 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12695 if (Subtarget->hasGFX1250_STRICT())
12699 case Intrinsic::amdgcn_exp_compr: {
12700 SDValue Src0 =
Op.getOperand(4);
12701 SDValue Src1 =
Op.getOperand(5);
12708 const SDValue
Ops[] = {
12720 unsigned Opc =
Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12724 case Intrinsic::amdgcn_struct_tbuffer_store:
12725 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12726 SDValue VData =
Op.getOperand(2);
12729 VData = handleD16VData(VData, DAG);
12730 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12731 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12745 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12746 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12749 M->getMemoryVT(),
M->getMemOperand());
12752 case Intrinsic::amdgcn_raw_tbuffer_store:
12753 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12754 SDValue VData =
Op.getOperand(2);
12757 VData = handleD16VData(VData, DAG);
12758 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12759 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12773 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12774 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12777 M->getMemoryVT(),
M->getMemOperand());
12780 case Intrinsic::amdgcn_raw_buffer_store:
12781 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12782 case Intrinsic::amdgcn_raw_buffer_store_format:
12783 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12784 const bool IsFormat =
12785 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12786 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12788 SDValue VData =
Op.getOperand(2);
12796 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12801 VData = handleD16VData(VData, DAG);
12811 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12812 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(4), DAG);
12826 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12827 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12832 return handleByteShortBufferStores(DAG, VDataVT,
DL,
Ops, M);
12835 M->getMemoryVT(),
M->getMemOperand());
12838 case Intrinsic::amdgcn_struct_buffer_store:
12839 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12840 case Intrinsic::amdgcn_struct_buffer_store_format:
12841 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12842 const bool IsFormat =
12843 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12844 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12846 SDValue VData =
Op.getOperand(2);
12854 "unsupported sub-dword format buffer store",
DL.getDebugLoc()));
12859 VData = handleD16VData(VData, DAG);
12869 auto Rsrc = bufferRsrcPtrToVector(
Op.getOperand(3), DAG);
12870 auto [VOffset,
Offset] = splitBufferOffsets(
Op.getOperand(5), DAG);
12884 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12885 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 :
Opc;
12889 EVT VDataType = VData.getValueType().getScalarType();
12891 return handleByteShortBufferStores(DAG, VDataType,
DL,
Ops, M);
12894 M->getMemoryVT(),
M->getMemOperand());
12896 case Intrinsic::amdgcn_raw_buffer_load_lds:
12897 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12898 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12899 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12900 case Intrinsic::amdgcn_struct_buffer_load_lds:
12901 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12902 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12903 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12906 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12907 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12908 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12909 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12910 unsigned OpOffset = HasVIndex ? 1 : 0;
12911 SDValue VOffset =
Op.getOperand(5 + OpOffset);
12913 unsigned Size =
Op->getConstantOperandVal(4);
12919 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12920 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12921 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12922 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12925 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12926 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12927 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12928 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12931 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12932 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12933 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12934 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12937 if (!Subtarget->hasLDSLoadB96_B128())
12939 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12940 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12941 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12942 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12945 if (!Subtarget->hasLDSLoadB96_B128())
12947 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12948 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12949 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12950 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12954 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
12958 if (HasVIndex && HasVOffset)
12962 else if (HasVIndex)
12963 Ops.push_back(
Op.getOperand(5));
12964 else if (HasVOffset)
12965 Ops.push_back(VOffset);
12967 SDValue Rsrc = bufferRsrcPtrToVector(
Op.getOperand(2), DAG);
12968 Ops.push_back(Rsrc);
12969 Ops.push_back(
Op.getOperand(6 + OpOffset));
12970 Ops.push_back(
Op.getOperand(7 + OpOffset));
12972 unsigned Aux =
Op.getConstantOperandVal(8 + OpOffset);
12990 return SDValue(
Load, 0);
12995 case Intrinsic::amdgcn_load_to_lds:
12996 case Intrinsic::amdgcn_load_async_to_lds:
12997 case Intrinsic::amdgcn_global_load_lds:
12998 case Intrinsic::amdgcn_global_load_async_lds: {
12999 if (!Subtarget->hasVMemToLDSLoad())
13003 unsigned Size =
Op->getConstantOperandVal(4);
13008 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13011 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13014 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13017 if (!Subtarget->hasLDSLoadB96_B128())
13019 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13022 if (!Subtarget->hasLDSLoadB96_B128())
13024 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13028 SDValue M0Val =
copyToM0(DAG, Chain,
DL,
Op.getOperand(3));
13032 SDValue Addr =
Op.getOperand(2);
13040 if (
LHS->isDivergent())
13044 RHS.getOperand(0).getValueType() == MVT::i32) {
13047 VOffset =
RHS.getOperand(0);
13051 Ops.push_back(Addr);
13059 Ops.push_back(VOffset);
13062 Ops.push_back(
Op.getOperand(5));
13064 unsigned Aux =
Op.getConstantOperandVal(6);
13077 return SDValue(
Load, 0);
13079 case Intrinsic::amdgcn_end_cf:
13081 Op->getOperand(2), Chain),
13083 case Intrinsic::amdgcn_s_barrier_signal_var: {
13088 SDValue CntOp =
Op->getOperand(3);
13090 if (CntC && CntC->isZero()) {
13091 SDValue Chain =
Op->getOperand(0);
13092 SDValue BarOp =
Op->getOperand(2);
13095 std::optional<uint64_t> BarVal;
13097 BarVal =
C->getZExtValue();
13101 BarVal = *Addr + GA->getOffset();
13104 unsigned BarID = *BarVal & 0x3F;
13106 Ops.push_back(Chain);
13108 Op->getVTList(),
Ops);
13109 return SDValue(NewMI, 0);
13114 case Intrinsic::amdgcn_s_barrier_init: {
13116 SDValue Chain =
Op->getOperand(0);
13118 SDValue BarOp =
Op->getOperand(2);
13119 SDValue CntOp =
Op->getOperand(3);
13121 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13122 ? AMDGPU::S_BARRIER_INIT_M0
13123 : AMDGPU::S_BARRIER_SIGNAL_M0;
13131 constexpr unsigned ShAmt = 16;
13140 return SDValue(NewMI, 0);
13142 case Intrinsic::amdgcn_s_wakeup_barrier: {
13143 if (!Subtarget->hasSWakeupBarrier())
13147 case Intrinsic::amdgcn_s_barrier_join: {
13149 SDValue Chain =
Op->getOperand(0);
13151 SDValue BarOp =
Op->getOperand(2);
13156 switch (IntrinsicID) {
13159 case Intrinsic::amdgcn_s_barrier_join:
13160 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13162 case Intrinsic::amdgcn_s_wakeup_barrier:
13163 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13167 unsigned BarID = BarVal & 0x3F;
13170 Ops.push_back(Chain);
13172 switch (IntrinsicID) {
13175 case Intrinsic::amdgcn_s_barrier_join:
13176 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13178 case Intrinsic::amdgcn_s_wakeup_barrier:
13179 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13189 return SDValue(NewMI, 0);
13191 case Intrinsic::amdgcn_s_prefetch_data:
13192 case Intrinsic::amdgcn_s_prefetch_inst: {
13195 return Op.getOperand(0);
13198 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13200 Chain, bufferRsrcPtrToVector(
Op.getOperand(2), DAG),
13207 Op->getVTList(),
Ops,
M->getMemoryVT(),
13208 M->getMemOperand());
13210 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13211 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13212 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13214 SDValue Chain =
Op->getOperand(0);
13215 SDValue Ptr =
Op->getOperand(2);
13216 SDValue Val =
Op->getOperand(3);
13220 case Intrinsic::amdgcn_av_store_b128: {
13222 SDValue Chain =
Op->getOperand(0);
13223 SDValue Ptr =
Op->getOperand(2);
13224 SDValue Val =
Op->getOperand(3);
13228 if (
const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13230 return lowerImage(
Op, ImageDimIntr, DAG,
true);
13246 return PtrVT == MVT::i64;
13260std::pair<SDValue, SDValue>
13273 bool CheckNUW = Subtarget->hasGFX1250Insts();
13290 unsigned Overflow = ImmOffset & ~MaxImm;
13291 ImmOffset -= Overflow;
13292 if ((int32_t)Overflow < 0) {
13293 Overflow += ImmOffset;
13298 auto OverflowVal = DAG.
getConstant(Overflow,
DL, MVT::i32);
13302 SDValue
Ops[] = {N0, OverflowVal};
13311 return {N0, SDValue(C1, 0)};
13317void SITargetLowering::setBufferOffsets(
SDValue CombinedOffset,
13319 Align Alignment)
const {
13321 SDLoc
DL(CombinedOffset);
13323 uint32_t
Imm =
C->getZExtValue();
13324 uint32_t SOffset, ImmOffset;
13325 if (
TII->splitMUBUFOffset(
Imm, SOffset, ImmOffset, Alignment)) {
13336 bool CheckNUW = Subtarget->hasGFX1250Insts();
13339 uint32_t SOffset, ImmOffset;
13342 TII->splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
13350 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13359SDValue SITargetLowering::bufferRsrcPtrToVector(
SDValue MaybePointer,
13362 return MaybePointer;
13364 SDValue Rsrc = DAG.
getBitcast(MVT::v4i32, MaybePointer);
13375 SDValue Stride =
Op->getOperand(2);
13376 SDValue NumRecords =
Op->getOperand(3);
13377 SDValue
Flags =
Op->getOperand(4);
13382 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13385 DAG.
getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13390 SDValue NumRecordsLHS =
13398 SDValue NumRecordsRHS =
13401 SDValue ShiftedStride =
13404 SDValue ExtShiftedStrideVec =
13406 SDValue ExtShiftedStride =
13408 SDValue ShiftedFlags =
13411 SDValue ExtShiftedFlagsVec =
13413 SDValue ExtShiftedFlags =
13415 SDValue CombinedFields =
13416 DAG.
getNode(
ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13418 DAG.
getNode(
ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13423 auto [LowHalf, HighHalf] =
13424 DAG.
SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13427 SDValue ShiftedStride =
13430 SDValue NewHighHalf =
13434 NumRecords, Flags);
13446 bool IsTFE)
const {
13451 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13452 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13455 SDVTList VTs = DAG.
getVTList(MVT::v2i32, MVT::Other);
13456 SDValue
Op = getMemIntrinsicNode(
Opc,
DL, VTs,
Ops, MVT::v2i32, OpMMO, DAG);
13467 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13468 : AMDGPUISD::BUFFER_LOAD_USHORT;
13470 SDVTList ResList = DAG.
getVTList(MVT::i32, MVT::Other);
13471 SDValue BufferLoad =
13484 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13488 Ops[1] = BufferStoreExt;
13489 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13490 : AMDGPUISD::BUFFER_STORE_SHORT;
13493 M->getMemOperand());
13518 DAGCombinerInfo &DCI)
const {
13519 SelectionDAG &DAG = DCI.DAG;
13520 if (Ld->getAlign() <
Align(4) || Ld->isDivergent())
13524 unsigned AS = Ld->getAddressSpace();
13533 EVT MemVT = Ld->getMemoryVT();
13534 if ((MemVT.
isSimple() && !DCI.isAfterLegalizeDAG()) ||
13541 "unexpected vector extload");
13544 SDValue Ptr = Ld->getBasePtr();
13545 SDValue NewLoad = DAG.
getLoad(
13547 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13548 Ld->getMemOperand()->getFlags(), Ld->getAAInfo());
13553 "unexpected fp extload");
13557 SDValue Cvt = NewLoad;
13568 EVT VT = Ld->getValueType(0);
13571 DCI.AddToWorklist(Cvt.
getNode());
13576 DCI.AddToWorklist(Cvt.
getNode());
13587 if (Info.isEntryFunction())
13588 return Info.getUserSGPRInfo().hasFlatScratchInit();
13596 EVT MemVT =
Load->getMemoryVT();
13597 MachineMemOperand *MMO =
Load->getMemOperand();
13606 SDValue Chain =
Load->getChain();
13609 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13637 assert(
Op.getValueType().getVectorElementType() == MVT::i32 &&
13638 "Custom lowering for non-i32 vectors hasn't been implemented.");
13641 unsigned AS =
Load->getAddressSpace();
13642 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13649 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
13653 !Subtarget->hasMultiDwordFlatScratchAddressing())
13663 Subtarget->getScalarizeGlobalBehavior() &&
Load->isSimple() &&
13666 Alignment >=
Align(4) && NumElements < 32) {
13668 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13680 if (NumElements > 4)
13683 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13693 switch (Subtarget->getMaxPrivateElementSize()) {
13699 if (NumElements > 2)
13704 if (NumElements > 4)
13707 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13716 auto Flags =
Load->getMemOperand()->getFlags();
13718 Load->getAlign(), Flags, &
Fast) &&
13727 MemVT, *
Load->getMemOperand())) {
13736 EVT VT =
Op.getValueType();
13771 SDValue
LHS =
Op.getOperand(0);
13772 SDValue
RHS =
Op.getOperand(1);
13773 EVT VT =
Op.getValueType();
13774 const SDNodeFlags
Flags =
Op->getFlags();
13776 bool AllowInaccurateRcp =
Flags.hasApproximateFuncs();
13782 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13785 if (CLHS->isOne()) {
13798 return DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13802 if (CLHS->isMinusOne()) {
13805 return DAG.
getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13811 if (!AllowInaccurateRcp &&
13812 ((VT != MVT::f16 && VT != MVT::bf16) || !
Flags.hasAllowReciprocal()))
13817 SDValue Recip = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
RHS);
13824 SDValue
X =
Op.getOperand(0);
13825 SDValue
Y =
Op.getOperand(1);
13826 EVT VT =
Op.getValueType();
13827 const SDNodeFlags
Flags =
Op->getFlags();
13829 bool AllowInaccurateDiv =
Flags.hasApproximateFuncs();
13830 if (!AllowInaccurateDiv)
13843 SDValue
R = DAG.
getNode(AMDGPUISD::RCP, SL, VT,
Y);
13854 if (IsNegRcp || (CLHS && CLHS->
isOne()))
13866 return DAG.
getNode(Opcode, SL, VT,
A,
B, Flags);
13876 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13880 return DAG.
getNode(Opcode, SL, VTList,
13889 return DAG.
getNode(Opcode, SL, VT, {
A,
B,
C}, Flags);
13899 Opcode = AMDGPUISD::FMA_W_CHAIN;
13903 return DAG.
getNode(Opcode, SL, VTList,
13909 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
13910 return FastLowered;
13913 EVT VT =
Op.getValueType();
13914 SDValue
LHS =
Op.getOperand(0);
13915 SDValue
RHS =
Op.getOperand(1);
13920 if (VT == MVT::bf16) {
13943 unsigned FMADOpCode =
13947 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt,
Op->getFlags());
13950 SDValue Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13952 Quot = DAG.
getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot,
Op->getFlags());
13953 Err = DAG.
getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13963 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst,
RHS,
LHS,
13969 SDNodeFlags
Flags =
Op->getFlags();
13971 SDValue
LHS =
Op.getOperand(1);
13972 SDValue
RHS =
Op.getOperand(2);
13979 const APFloat K0Val(0x1p+96f);
13982 const APFloat K1Val(0x1p-32f);
13997 SDValue
r0 = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32,
r1, Flags);
14009 assert(ST->hasDenormModeInst() &&
"Requires S_DENORM_MODE");
14010 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14011 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14016 if (SDValue FastLowered = lowerFastUnsafeFDIV(
Op, DAG))
14017 return FastLowered;
14023 SDNodeFlags
Flags =
Op->getFlags();
14024 Flags.setNoFPExcept(
true);
14027 SDValue
LHS =
Op.getOperand(0);
14028 SDValue
RHS =
Op.getOperand(1);
14032 SDVTList ScaleVT = DAG.
getVTList(MVT::f32, MVT::i1);
14034 SDValue DenominatorScaled =
14036 SDValue NumeratorScaled =
14040 SDValue ApproxRcp =
14041 DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14042 SDValue NegDivScale0 =
14045 using namespace AMDGPU::Hwreg;
14046 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14050 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
14051 const DenormalMode DenormMode =
Info->getMode().FP32Denormals;
14054 const bool HasDynamicDenormals =
14058 SDValue SavedDenormMode;
14060 if (!PreservesDenormals) {
14065 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14068 if (HasDynamicDenormals) {
14072 SavedDenormMode = SDValue(GetReg, 0);
14075 {DAG.
getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14078 SDNode *EnableDenorm;
14079 if (Subtarget->hasDenormModeInst()) {
14080 const SDValue EnableDenormValue =
14083 EnableDenorm = DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14087 const SDValue EnableDenormValue =
14089 EnableDenorm = DAG.
getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14090 {EnableDenormValue,
BitField, Glue});
14093 SDValue
Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14094 SDValue(EnableDenorm, 1)};
14100 ApproxRcp, One, NegDivScale0, Flags);
14103 ApproxRcp, Fma0, Flags);
14109 NumeratorScaled,
Mul, Flags);
14115 NumeratorScaled, Fma3, Flags);
14117 if (!PreservesDenormals) {
14118 SDNode *DisableDenorm;
14119 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14123 SDVTList BindParamVTs = DAG.
getVTList(MVT::Other, MVT::Glue);
14125 DAG.
getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14129 assert(HasDynamicDenormals == (
bool)SavedDenormMode);
14130 const SDValue DisableDenormValue =
14131 HasDynamicDenormals
14136 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14141 SDValue(DisableDenorm, 0), DAG.
getRoot());
14145 SDValue Scale = NumeratorScaled.
getValue(1);
14146 SDValue Fmas = DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14147 {Fma4, Fma1, Fma3, Scale},
Flags);
14149 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas,
RHS,
LHS, Flags);
14153 if (SDValue FastLowered = lowerFastUnsafeFDIV64(
Op, DAG))
14154 return FastLowered;
14157 SDValue
X =
Op.getOperand(0);
14158 SDValue
Y =
Op.getOperand(1);
14162 SDVTList ScaleVT = DAG.
getVTList(MVT::f64, MVT::i1);
14164 SDValue DivScale0 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
Y,
Y,
X);
14168 SDValue Rcp = DAG.
getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14170 SDValue Fma0 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14174 SDValue Fma2 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14176 SDValue DivScale1 = DAG.
getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT,
X,
Y,
X);
14178 SDValue Fma3 = DAG.
getNode(
ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14186 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14216 DAG.
getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3,
Mul, Scale);
14218 return DAG.
getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas,
Y,
X);
14222 EVT VT =
Op.getValueType();
14224 if (VT == MVT::f32)
14225 return LowerFDIV32(
Op, DAG);
14227 if (VT == MVT::f64)
14228 return LowerFDIV64(
Op, DAG);
14230 if (VT == MVT::f16 || VT == MVT::bf16)
14231 return LowerFDIV16(
Op, DAG);
14238 SDValue Val =
Op.getOperand(0);
14240 EVT ResultExpVT =
Op->getValueType(1);
14241 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14251 if (Subtarget->hasFractBug()) {
14269 EVT VT =
Store->getMemoryVT();
14271 if (VT == MVT::i1) {
14275 Store->getBasePtr(), MVT::i1,
Store->getMemOperand());
14279 Store->getValue().getValueType().getScalarType() == MVT::i32);
14281 unsigned AS =
Store->getAddressSpace();
14282 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14290 SIMachineFunctionInfo *MFI = MF.
getInfo<SIMachineFunctionInfo>();
14294 !Subtarget->hasMultiDwordFlatScratchAddressing())
14301 if (NumElements > 4)
14304 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14308 VT, *
Store->getMemOperand()))
14314 switch (Subtarget->getMaxPrivateElementSize()) {
14318 if (NumElements > 2)
14322 if (NumElements > 4 ||
14323 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14331 auto Flags =
Store->getMemOperand()->getFlags();
14350 assert(!Subtarget->has16BitInsts());
14351 SDNodeFlags
Flags =
Op->getFlags();
14365 SDNodeFlags
Flags =
Op->getFlags();
14366 MVT VT =
Op.getValueType().getSimpleVT();
14367 const SDValue
X =
Op.getOperand(0);
14393 SDValue SqrtSNextDownInt =
14398 SDValue NegSqrtSNextDown =
14422 SDValue SqrtR = DAG.
getNode(AMDGPUISD::RSQ,
DL, VT, SqrtX, Flags);
14442 SDValue ScaledDown =
14446 SDValue IsZeroOrInf =
14474 SDNodeFlags
Flags =
Op->getFlags();
14478 SDValue
X =
Op.getOperand(0);
14483 if (!
Flags.hasApproximateFuncs()) {
14488 SDValue ScaleUpFactor = DAG.
getConstant(256,
DL, MVT::i32);
14494 SDValue SqrtY = DAG.
getNode(AMDGPUISD::RSQ,
DL, MVT::f64, SqrtX);
14514 SDValue SqrtRet = SqrtS2;
14515 if (!
Flags.hasApproximateFuncs()) {
14524 ScaleDownFactor, ZeroInt);
14530 SDValue IsZeroOrInf;
14531 if (
Flags.hasNoInfs()) {
14547 EVT VT =
Op.getValueType();
14548 SDValue Arg =
Op.getOperand(0);
14557 auto UnrollIfVec = [&DAG](SDValue
V) -> SDValue {
14558 if (!
V.getValueType().isVector())
14566 if (Subtarget->hasTrigReducedRange()) {
14568 TrigVal = UnrollIfVec(DAG.
getNode(AMDGPUISD::FRACT,
DL, VT, MulVal, Flags));
14573 switch (
Op.getOpcode()) {
14575 TrigVal = DAG.
getNode(AMDGPUISD::COS_HW, SDLoc(
Op), VT, TrigVal, Flags);
14578 TrigVal = DAG.
getNode(AMDGPUISD::SIN_HW, SDLoc(
Op), VT, TrigVal, Flags);
14584 return UnrollIfVec(TrigVal);
14600 SDValue ChainIn =
Op.getOperand(0);
14601 SDValue Addr =
Op.getOperand(1);
14602 SDValue Old =
Op.getOperand(2);
14603 SDValue
New =
Op.getOperand(3);
14604 EVT VT =
Op.getValueType();
14609 SDValue
Ops[] = {ChainIn, Addr, NewOld};
14612 Op->getVTList(),
Ops, VT,
14621SITargetLowering::performUCharToFloatCombine(
SDNode *
N,
14622 DAGCombinerInfo &DCI)
const {
14623 EVT VT =
N->getValueType(0);
14625 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14628 SelectionDAG &DAG = DCI.DAG;
14631 SDValue Src =
N->getOperand(0);
14632 EVT SrcVT = Src.getValueType();
14638 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14640 SDValue Cvt = DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0,
DL, MVT::f32, Src);
14641 DCI.AddToWorklist(Cvt.
getNode());
14644 if (ScalarVT != MVT::f32) {
14656 DAGCombinerInfo &DCI)
const {
14667 SelectionDAG &DAG = DCI.DAG;
14686 for (
unsigned I = 0;
I != NumElts; ++
I) {
14694 SDValue SignOpElt =
14710 if (NewElts.
size() == 1)
14732 for (
unsigned I = 0;
I != NumElts; ++
I) {
14734 SDValue SignAsF32 =
14767SDValue SITargetLowering::performSHLPtrCombine(
SDNode *
N,
unsigned AddrSpace,
14769 DAGCombinerInfo &DCI)
const {
14786 SelectionDAG &DAG = DCI.DAG;
14799 AM.BaseOffs =
Offset.getSExtValue();
14804 EVT VT =
N->getValueType(0);
14810 Flags.setNoUnsignedWrap(
14811 N->getFlags().hasNoUnsignedWrap() &&
14823 switch (
N->getOpcode()) {
14834 DAGCombinerInfo &DCI)
const {
14835 SelectionDAG &DAG = DCI.DAG;
14842 SDValue NewPtr = performSHLPtrCombine(Ptr.
getNode(),
N->getAddressSpace(),
14843 N->getMemoryVT(), DCI);
14847 NewOps[PtrIdx] = NewPtr;
14856 return (
Opc ==
ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14857 (
Opc ==
ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14866SDValue SITargetLowering::splitBinaryBitConstantOp(
14870 uint32_t ValLo =
Lo_32(Val);
14871 uint32_t ValHi =
Hi_32(Val);
14878 if (Subtarget->has64BitLiterals() && CRHS->
hasOneUse() &&
14892 if (V.getValueType() != MVT::i1)
14894 switch (V.getOpcode()) {
14899 case AMDGPUISD::FP_CLASS:
14911 return V.getResNo() == 1;
14913 unsigned IntrinsicID = V.getConstantOperandVal(0);
14914 switch (IntrinsicID) {
14915 case Intrinsic::amdgcn_is_shared:
14916 case Intrinsic::amdgcn_is_private:
14933 if (!(
C & 0x000000ff))
14934 ZeroByteMask |= 0x000000ff;
14935 if (!(
C & 0x0000ff00))
14936 ZeroByteMask |= 0x0000ff00;
14937 if (!(
C & 0x00ff0000))
14938 ZeroByteMask |= 0x00ff0000;
14939 if (!(
C & 0xff000000))
14940 ZeroByteMask |= 0xff000000;
14941 uint32_t NonZeroByteMask = ~ZeroByteMask;
14942 if ((NonZeroByteMask &
C) != NonZeroByteMask)
14955 assert(V.getValueSizeInBits() == 32);
14957 if (V.getNumOperands() != 2)
14966 switch (V.getOpcode()) {
14971 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14976 return (0x03020100 & ~ConstMask) | ConstMask;
14983 return uint32_t((0x030201000c0c0c0cull <<
C) >> 32);
14989 return uint32_t(0x0c0c0c0c03020100ull >>
C);
14996 DAGCombinerInfo &DCI)
const {
14997 if (DCI.isBeforeLegalize())
15000 SelectionDAG &DAG = DCI.DAG;
15001 EVT VT =
N->getValueType(0);
15002 SDValue
LHS =
N->getOperand(0);
15003 SDValue
RHS =
N->getOperand(1);
15006 if (VT == MVT::i64 && CRHS) {
15007 if (SDValue Split =
15008 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::AND,
LHS, CRHS))
15012 if (CRHS && VT == MVT::i32) {
15022 unsigned Shift = CShift->getZExtValue();
15024 unsigned Offset = NB + Shift;
15025 if ((
Offset & (Bits - 1)) == 0) {
15028 DAG.
getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
LHS->getOperand(0),
15049 Sel = (
LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15051 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15062 SDValue
X =
LHS.getOperand(0);
15063 SDValue
Y =
RHS.getOperand(0);
15064 if (
Y.getOpcode() !=
ISD::FABS ||
Y.getOperand(0) !=
X ||
15069 if (
X !=
LHS.getOperand(1))
15073 const ConstantFPSDNode *C1 =
15090 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
X,
15096 if (
RHS.getOpcode() ==
ISD::SETCC &&
LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15099 if (
LHS.getOpcode() ==
ISD::SETCC &&
RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15107 (
RHS.getOperand(0) ==
LHS.getOperand(0) &&
15108 LHS.getOperand(0) ==
LHS.getOperand(1))) {
15110 unsigned NewMask = LCC ==
ISD::SETO ?
Mask->getZExtValue() & ~OrdMask
15111 :
Mask->getZExtValue() & OrdMask;
15114 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1,
RHS.getOperand(0),
15132 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15135 if (LHSMask != ~0u && RHSMask != ~0u) {
15138 if (LHSMask > RHSMask) {
15145 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15146 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15149 if (!(LHSUsedLanes & RHSUsedLanes) &&
15152 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15158 uint32_t
Mask = LHSMask & RHSMask;
15159 for (
unsigned I = 0;
I < 32;
I += 8) {
15160 uint32_t ByteSel = 0xff <<
I;
15161 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15162 Mask &= (0x0c <<
I) & 0xffffffff;
15167 uint32_t Sel =
Mask | (LHSUsedLanes & 0x04040404);
15170 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15220static const std::optional<ByteProvider<SDValue>>
15222 unsigned Depth = 0) {
15225 return std::nullopt;
15227 if (
Op.getValueSizeInBits() < 8)
15228 return std::nullopt;
15230 if (
Op.getValueType().isVector())
15233 switch (
Op->getOpcode()) {
15246 NarrowVT = VTSign->getVT();
15249 return std::nullopt;
15252 if (SrcIndex >= NarrowByteWidth)
15253 return std::nullopt;
15261 return std::nullopt;
15263 uint64_t BitShift = ShiftOp->getZExtValue();
15265 if (BitShift % 8 != 0)
15266 return std::nullopt;
15268 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15269 if (NewSrcIndex >=
Op.getScalarValueSizeInBits() / 8)
15270 return std::nullopt;
15289static const std::optional<ByteProvider<SDValue>>
15291 unsigned StartingIndex = 0) {
15295 return std::nullopt;
15297 unsigned BitWidth =
Op.getScalarValueSizeInBits();
15299 return std::nullopt;
15301 return std::nullopt;
15303 bool IsVec =
Op.getValueType().isVector();
15304 switch (
Op.getOpcode()) {
15307 return std::nullopt;
15312 return std::nullopt;
15316 return std::nullopt;
15319 if (!
LHS->isConstantZero() && !
RHS->isConstantZero())
15320 return std::nullopt;
15321 if (!
LHS ||
LHS->isConstantZero())
15323 if (!
RHS ||
RHS->isConstantZero())
15325 return std::nullopt;
15330 return std::nullopt;
15334 return std::nullopt;
15336 uint32_t BitMask = BitMaskOp->getZExtValue();
15338 uint32_t IndexMask = 0xFF << (Index * 8);
15340 if ((IndexMask & BitMask) != IndexMask) {
15343 if (IndexMask & BitMask)
15344 return std::nullopt;
15353 return std::nullopt;
15357 if (!ShiftOp ||
Op.getValueType().isVector())
15358 return std::nullopt;
15360 uint64_t BitsProvided =
Op.getValueSizeInBits();
15361 if (BitsProvided % 8 != 0)
15362 return std::nullopt;
15364 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15366 return std::nullopt;
15368 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15369 uint64_t ByteShift = BitShift / 8;
15371 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15372 uint64_t BytesProvided = BitsProvided / 8;
15373 SDValue NextOp =
Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15374 NewIndex %= BytesProvided;
15381 return std::nullopt;
15385 return std::nullopt;
15387 uint64_t BitShift = ShiftOp->getZExtValue();
15389 return std::nullopt;
15391 auto BitsProvided =
Op.getScalarValueSizeInBits();
15392 if (BitsProvided % 8 != 0)
15393 return std::nullopt;
15395 uint64_t BytesProvided = BitsProvided / 8;
15396 uint64_t ByteShift = BitShift / 8;
15397 if (Index + ByteShift < BytesProvided)
15399 Index + ByteShift);
15402 return std::nullopt;
15408 return std::nullopt;
15412 return std::nullopt;
15414 uint64_t BitShift = ShiftOp->getZExtValue();
15415 if (BitShift % 8 != 0)
15416 return std::nullopt;
15417 uint64_t ByteShift = BitShift / 8;
15423 return Index < ByteShift
15426 Depth + 1, StartingIndex);
15435 return std::nullopt;
15443 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15445 if (NarrowBitWidth % 8 != 0)
15446 return std::nullopt;
15447 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15449 if (Index >= NarrowByteWidth)
15451 ? std::optional<ByteProvider<SDValue>>(
15459 return std::nullopt;
15463 if (NarrowByteWidth >= Index) {
15468 return std::nullopt;
15475 return std::nullopt;
15481 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15482 if (NarrowBitWidth % 8 != 0)
15483 return std::nullopt;
15484 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15489 if (Index >= NarrowByteWidth) {
15491 ? std::optional<ByteProvider<SDValue>>(
15496 if (NarrowByteWidth > Index) {
15500 return std::nullopt;
15505 return std::nullopt;
15508 Depth + 1, StartingIndex);
15514 return std::nullopt;
15515 auto VecIdx = IdxOp->getZExtValue();
15516 auto ScalarSize =
Op.getScalarValueSizeInBits();
15517 if (ScalarSize < 32)
15518 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15520 StartingIndex, Index);
15523 case AMDGPUISD::PERM: {
15525 return std::nullopt;
15529 return std::nullopt;
15532 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15533 if (IdxMask > 0x07 && IdxMask != 0x0c)
15534 return std::nullopt;
15536 auto NextOp =
Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15537 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15539 return IdxMask != 0x0c ?
calculateSrcByte(NextOp, StartingIndex, NextIndex)
15545 return std::nullopt;
15560 return !OpVT.
isVector() && OpVT.getSizeInBits() == 16;
15567 auto MemVT = L->getMemoryVT();
15570 return L->getMemoryVT().getSizeInBits() == 16;
15580 int Low8 = Mask & 0xff;
15581 int Hi8 = (Mask & 0xff00) >> 8;
15583 assert(Low8 < 8 && Hi8 < 8);
15585 bool IsConsecutive = (Hi8 - Low8 == 1);
15590 bool Is16Aligned = !(Low8 % 2);
15592 return IsConsecutive && Is16Aligned;
15600 int Low16 = PermMask & 0xffff;
15601 int Hi16 = (PermMask & 0xffff0000) >> 16;
15611 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15613 if (!OtherOpIs16Bit)
15621 unsigned DWordOffset) {
15626 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15631 if (Src.getValueType().isVector()) {
15632 auto ScalarTySize = Src.getScalarValueSizeInBits();
15633 auto ScalarTy = Src.getValueType().getScalarType();
15634 if (ScalarTySize == 32) {
15638 if (ScalarTySize > 32) {
15641 DAG.
getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15642 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15649 assert(ScalarTySize < 32);
15658 auto NumElements =
TypeSize / ScalarTySize;
15659 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15660 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15661 auto NumElementsIn32 = 32 / ScalarTySize;
15662 auto NumAvailElements = DWordOffset < Trunc32Elements
15664 : NumElements - NormalizedTrunc;
15677 auto ShiftVal = 32 * DWordOffset;
15685 [[maybe_unused]]
EVT VT =
N->getValueType(0);
15690 for (
int i = 0; i < 4; i++) {
15692 std::optional<ByteProvider<SDValue>>
P =
15695 if (!
P ||
P->isConstantZero())
15700 if (PermNodes.
size() != 4)
15703 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15704 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15706 for (
size_t i = 0; i < PermNodes.
size(); i++) {
15707 auto PermOp = PermNodes[i];
15710 int SrcByteAdjust = 4;
15714 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15715 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15717 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15718 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15722 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15723 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15726 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15728 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15731 SDValue Op = *PermNodes[FirstSrc.first].Src;
15733 assert(
Op.getValueSizeInBits() == 32);
15737 int Low16 = PermMask & 0xffff;
15738 int Hi16 = (PermMask & 0xffff0000) >> 16;
15740 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15741 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15744 if (WellFormedLow && WellFormedHi)
15748 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src :
Op;
15757 (
N->getOperand(0) ==
Op ||
N->getOperand(0) == OtherOp) &&
15758 (
N->getOperand(1) ==
Op ||
N->getOperand(1) == OtherOp))
15763 assert(
Op.getValueType().isByteSized() &&
15774 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
Op, OtherOp,
15781 DAGCombinerInfo &DCI)
const {
15782 SelectionDAG &DAG = DCI.DAG;
15783 SDValue
LHS =
N->getOperand(0);
15784 SDValue
RHS =
N->getOperand(1);
15786 EVT VT =
N->getValueType(0);
15787 if (VT == MVT::i1) {
15789 if (
LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15790 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15791 SDValue Src =
LHS.getOperand(0);
15792 if (Src !=
RHS.getOperand(0))
15797 if (!CLHS || !CRHS)
15801 static const uint32_t MaxMask = 0x3ff;
15806 return DAG.
getNode(AMDGPUISD::FP_CLASS,
DL, MVT::i1, Src,
15815 LHS.getOpcode() == AMDGPUISD::PERM &&
15821 Sel |=
LHS.getConstantOperandVal(2);
15823 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15830 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15834 auto usesCombinedOperand = [](SDNode *OrUse) {
15837 !OrUse->getValueType(0).isVector())
15841 for (
auto *VUser : OrUse->users()) {
15842 if (!VUser->getValueType(0).isVector())
15849 if (VUser->getOpcode() == VectorwiseOp)
15855 if (!
any_of(
N->users(), usesCombinedOperand))
15861 if (LHSMask != ~0u && RHSMask != ~0u) {
15864 if (LHSMask > RHSMask) {
15871 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15872 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15875 if (!(LHSUsedLanes & RHSUsedLanes) &&
15878 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15880 LHSMask &= ~RHSUsedLanes;
15881 RHSMask &= ~LHSUsedLanes;
15883 LHSMask |= LHSUsedLanes & 0x04040404;
15885 uint32_t Sel = LHSMask | RHSMask;
15888 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32,
LHS.getOperand(0),
15893 if (LHSMask == ~0u || RHSMask == ~0u) {
15924 SDValue LEVE =
LHS->getOperand(0);
15925 SDValue REVE =
RHS->getOperand(1);
15934 return IdentitySrc;
15940 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15953 SDValue ExtSrc =
RHS.getOperand(0);
15955 if (SrcVT == MVT::i32) {
15958 SDValue LowOr = DAG.
getNode(
ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
15960 DCI.AddToWorklist(LowOr.
getNode());
15961 DCI.AddToWorklist(HiBits.getNode());
15971 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::OR,
15972 N->getOperand(0), CRHS))
15980 DAGCombinerInfo &DCI)
const {
15981 if (SDValue RV = reassociateScalarOps(
N, DCI.DAG))
15984 SDValue
LHS =
N->getOperand(0);
15985 SDValue
RHS =
N->getOperand(1);
15988 SelectionDAG &DAG = DCI.DAG;
15990 EVT VT =
N->getValueType(0);
15991 if (CRHS && VT == MVT::i64) {
15992 if (SDValue Split =
15993 splitBinaryBitConstantOp(DCI, SDLoc(
N),
ISD::XOR,
LHS, CRHS))
16000 unsigned Opc =
LHS.getOpcode();
16004 SDValue CC =
LHS->getOperand(0);
16005 SDValue TRUE =
LHS->getOperand(1);
16006 SDValue FALSE =
LHS->getOperand(2);
16030 LHS->getOperand(0), FNegLHS, FNegRHS);
16039SITargetLowering::performZeroOrAnyExtendCombine(
SDNode *
N,
16040 DAGCombinerInfo &DCI)
const {
16041 if (!Subtarget->has16BitInsts() ||
16045 EVT VT =
N->getValueType(0);
16046 if (VT != MVT::i32)
16049 SDValue Src =
N->getOperand(0);
16050 if (Src.getValueType() != MVT::i16)
16053 if (!Src->hasOneUse())
16060 std::optional<ByteProvider<SDValue>> BP0 =
16062 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16064 SDValue
V0 = *BP0->Src;
16066 std::optional<ByteProvider<SDValue>> BP1 =
16068 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16071 SDValue
V1 = *BP1->Src;
16076 SelectionDAG &DAG = DCI.DAG;
16078 uint32_t PermMask = 0x0c0c0c0c;
16081 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16086 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16089 return DAG.
getNode(AMDGPUISD::PERM,
DL, MVT::i32, V0,
V1,
16094SITargetLowering::performSignExtendInRegCombine(
SDNode *
N,
16095 DAGCombinerInfo &DCI)
const {
16096 SDValue Src =
N->getOperand(0);
16101 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16102 VTSign->getVT() == MVT::i8) ||
16103 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16104 VTSign->getVT() == MVT::i16))) {
16105 assert(Subtarget->hasScalarSubwordLoads() &&
16106 "s_buffer_load_{u8, i8} are supported "
16107 "in GFX12 (or newer) architectures.");
16108 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16109 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16110 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16113 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16121 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16122 Opc,
DL, ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16123 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.
getValue(1)},
DL);
16125 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16126 VTSign->getVT() == MVT::i8) ||
16127 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16128 VTSign->getVT() == MVT::i16)) &&
16131 SDValue
Ops[] = {Src.getOperand(0),
16137 Src.getOperand(6), Src.getOperand(7)};
16140 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16141 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16142 ? AMDGPUISD::BUFFER_LOAD_BYTE
16143 : AMDGPUISD::BUFFER_LOAD_SHORT;
16144 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16145 Opc, SDLoc(
N), ResList,
Ops,
M->getMemoryVT(),
M->getMemOperand());
16146 return DCI.DAG.getMergeValues(
16147 {BufferLoadSignExt, BufferLoadSignExt.
getValue(1)}, SDLoc(
N));
16153 DAGCombinerInfo &DCI)
const {
16154 SelectionDAG &DAG = DCI.DAG;
16155 SDValue
Mask =
N->getOperand(1);
16161 if (
N->getOperand(0).isUndef())
16168 DAGCombinerInfo &DCI)
const {
16169 EVT VT =
N->getValueType(0);
16180 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(
N), VT, N0.
getOperand(0),
16189 unsigned MaxDepth)
const {
16190 EVT VT =
Op.getValueType();
16192 "expected a floating-point value to query canonicality of");
16198 unsigned MaxDepth)
const {
16200 "QueryVT must be a floating-point scalar type");
16201 EVT VT =
Op.getValueType();
16205 unsigned Opcode =
Op.getOpcode();
16210 const auto &
F = CFP->getValueAPF();
16211 if (
F.isNaN() &&
F.isSignaling())
16213 if (!
F.isDenormal())
16245 case AMDGPUISD::FMUL_LEGACY:
16246 case AMDGPUISD::FMAD_FTZ:
16247 case AMDGPUISD::RCP:
16248 case AMDGPUISD::RSQ:
16249 case AMDGPUISD::RSQ_CLAMP:
16250 case AMDGPUISD::RCP_LEGACY:
16251 case AMDGPUISD::RCP_IFLAG:
16252 case AMDGPUISD::LOG:
16253 case AMDGPUISD::EXP:
16254 case AMDGPUISD::DIV_SCALE:
16255 case AMDGPUISD::DIV_FMAS:
16256 case AMDGPUISD::DIV_FIXUP:
16257 case AMDGPUISD::FRACT:
16258 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16259 case AMDGPUISD::CVT_F32_UBYTE0:
16260 case AMDGPUISD::CVT_F32_UBYTE1:
16261 case AMDGPUISD::CVT_F32_UBYTE2:
16262 case AMDGPUISD::CVT_F32_UBYTE3:
16263 case AMDGPUISD::FP_TO_FP16:
16264 case AMDGPUISD::SIN_HW:
16265 case AMDGPUISD::COS_HW:
16277 if (
Op.getValueType() == MVT::i32) {
16283 if (RHS->getZExtValue() == 0xffff0000) {
16294 return Op.getValueType().getScalarType() != MVT::f16;
16304 case AMDGPUISD::CLAMP:
16305 case AMDGPUISD::FMED3:
16306 case AMDGPUISD::FMAX3:
16307 case AMDGPUISD::FMIN3:
16308 case AMDGPUISD::FMAXIMUM3:
16309 case AMDGPUISD::FMINIMUM3: {
16315 if (Subtarget->supportsMinMaxDenormModes() ||
16325 for (
unsigned I = 0, E =
Op.getNumOperands();
I != E; ++
I) {
16340 for (
unsigned i = 0, e =
Op.getNumOperands(); i != e; ++i) {
16374 if (
Op.getValueType() == MVT::i16) {
16386 unsigned IntrinsicID =
Op.getConstantOperandVal(0);
16388 switch (IntrinsicID) {
16389 case Intrinsic::amdgcn_cvt_pkrtz:
16390 case Intrinsic::amdgcn_cubeid:
16391 case Intrinsic::amdgcn_frexp_mant:
16392 case Intrinsic::amdgcn_fdot2:
16393 case Intrinsic::amdgcn_rcp:
16394 case Intrinsic::amdgcn_rsq:
16395 case Intrinsic::amdgcn_rsq_clamp:
16396 case Intrinsic::amdgcn_rcp_legacy:
16397 case Intrinsic::amdgcn_rsq_legacy:
16398 case Intrinsic::amdgcn_trig_preop:
16399 case Intrinsic::amdgcn_tanh:
16400 case Intrinsic::amdgcn_log:
16401 case Intrinsic::amdgcn_exp2:
16402 case Intrinsic::amdgcn_sqrt:
16420 unsigned MaxDepth)
const {
16423 unsigned Opcode =
MI->getOpcode();
16425 if (Opcode == AMDGPU::G_FCANONICALIZE)
16428 std::optional<FPValueAndVReg> FCR;
16431 if (FCR->Value.isSignaling())
16433 if (!FCR->Value.isDenormal())
16444 case AMDGPU::G_FADD:
16445 case AMDGPU::G_FSUB:
16446 case AMDGPU::G_FMUL:
16447 case AMDGPU::G_FCEIL:
16448 case AMDGPU::G_FFLOOR:
16449 case AMDGPU::G_FRINT:
16450 case AMDGPU::G_FNEARBYINT:
16451 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16452 case AMDGPU::G_INTRINSIC_TRUNC:
16453 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16454 case AMDGPU::G_FMA:
16455 case AMDGPU::G_FMAD:
16456 case AMDGPU::G_FSQRT:
16457 case AMDGPU::G_FDIV:
16458 case AMDGPU::G_FREM:
16459 case AMDGPU::G_FPOW:
16460 case AMDGPU::G_FPEXT:
16461 case AMDGPU::G_FLOG:
16462 case AMDGPU::G_FLOG2:
16463 case AMDGPU::G_FLOG10:
16464 case AMDGPU::G_FPTRUNC:
16465 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16466 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16467 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16468 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16469 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16471 case AMDGPU::G_FNEG:
16472 case AMDGPU::G_FABS:
16473 case AMDGPU::G_FCOPYSIGN:
16475 case AMDGPU::G_FMINNUM:
16476 case AMDGPU::G_FMAXNUM:
16477 case AMDGPU::G_FMINNUM_IEEE:
16478 case AMDGPU::G_FMAXNUM_IEEE:
16479 case AMDGPU::G_FMINIMUM:
16480 case AMDGPU::G_FMAXIMUM:
16481 case AMDGPU::G_FMINIMUMNUM:
16482 case AMDGPU::G_FMAXIMUMNUM: {
16483 if (Subtarget->supportsMinMaxDenormModes() ||
16490 case AMDGPU::G_BUILD_VECTOR:
16495 case AMDGPU::G_INTRINSIC:
16496 case AMDGPU::G_INTRINSIC_CONVERGENT:
16498 case Intrinsic::amdgcn_fmul_legacy:
16499 case Intrinsic::amdgcn_fmad_ftz:
16500 case Intrinsic::amdgcn_sqrt:
16501 case Intrinsic::amdgcn_fmed3:
16502 case Intrinsic::amdgcn_sin:
16503 case Intrinsic::amdgcn_cos:
16504 case Intrinsic::amdgcn_log:
16505 case Intrinsic::amdgcn_exp2:
16506 case Intrinsic::amdgcn_log_clamp:
16507 case Intrinsic::amdgcn_rcp:
16508 case Intrinsic::amdgcn_rcp_legacy:
16509 case Intrinsic::amdgcn_rsq:
16510 case Intrinsic::amdgcn_rsq_clamp:
16511 case Intrinsic::amdgcn_rsq_legacy:
16512 case Intrinsic::amdgcn_div_scale:
16513 case Intrinsic::amdgcn_div_fmas:
16514 case Intrinsic::amdgcn_div_fixup:
16515 case Intrinsic::amdgcn_fract:
16516 case Intrinsic::amdgcn_cvt_pkrtz:
16517 case Intrinsic::amdgcn_cubeid:
16518 case Intrinsic::amdgcn_cubema:
16519 case Intrinsic::amdgcn_cubesc:
16520 case Intrinsic::amdgcn_cubetc:
16521 case Intrinsic::amdgcn_frexp_mant:
16522 case Intrinsic::amdgcn_fdot2:
16523 case Intrinsic::amdgcn_trig_preop:
16524 case Intrinsic::amdgcn_tanh:
16543 if (
C.isDenormal()) {
16556 if (
C.isSignaling()) {
16571SITargetLowering::performFCanonicalizeCombine(
SDNode *
N,
16572 DAGCombinerInfo &DCI)
const {
16573 SelectionDAG &DAG = DCI.DAG;
16575 EVT VT =
N->getValueType(0);
16584 return getCanonicalConstantFP(DAG, SDLoc(
N), VT, CFP->getValueAPF());
16596 SDValue NewElts[2];
16599 EVT EltVT =
Lo.getValueType();
16608 for (
unsigned I = 0;
I != 2; ++
I) {
16612 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16613 }
else if (
Op.isUndef()) {
16648 return AMDGPUISD::FMAX3;
16650 return AMDGPUISD::FMAXIMUM3;
16652 return AMDGPUISD::SMAX3;
16654 return AMDGPUISD::UMAX3;
16658 return AMDGPUISD::FMIN3;
16660 return AMDGPUISD::FMINIMUM3;
16662 return AMDGPUISD::SMIN3;
16664 return AMDGPUISD::UMIN3;
16685 if (!MinK || !MaxK)
16697 unsigned Med3Opc =
Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16698 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16699 return DAG.
getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16723 bool IsKnownNoNaNs)
const {
16759 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
16765 if (
Info->getMode().DX10Clamp) {
16774 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16788 SDValue(K0, 0), SDValue(K1, 0));
16806 case AMDGPUISD::FMIN_LEGACY:
16807 case AMDGPUISD::FMAX_LEGACY:
16808 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.
hasMin3Max3_16()) ||
16809 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16812 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16813 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16814 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16819 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.
hasMin3Max3_16());
16828 DAGCombinerInfo &DCI)
const {
16829 SelectionDAG &DAG = DCI.DAG;
16840 auto IsTreeWithCombinableChildren = [
Opc](SDValue
Op) {
16841 return (
Op.getOperand(0).getOpcode() ==
Opc &&
16842 Op.getOperand(0).hasOneUse()) ||
16844 Op.getOperand(1).hasOneUse());
16849 bool HasCombinableTreeChild =
16850 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16851 IsTreeWithCombinableChildren(Op1));
16860 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16898 if (
Known.isNonZero() &&
Known.Zero.getBoolValue())
16906 if (SDValue Med3 = performIntMed3ImmCombine(
16911 if (SDValue Med3 = performIntMed3ImmCombine(
16917 if (SDValue Med3 = performIntMed3ImmCombine(
16922 if (SDValue Med3 = performIntMed3ImmCombine(
16935 (
Opc == AMDGPUISD::FMIN_LEGACY &&
16936 Op0.
getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16937 (VT == MVT::f32 || VT == MVT::f64 ||
16938 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16939 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16940 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16941 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16943 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(
N), Op0, Op1,
16944 N->getFlags().hasNoNaNs()))
16951 const SDNodeFlags
Flags =
N->getFlags();
16953 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16957 return DAG.
getNode(NewOpc, SDLoc(
N), VT, Op0, Op1, Flags);
16967 return (CA->isPosZero() && CB->isOne()) ||
16968 (CA->isOne() && CB->isPosZero());
16977 DAGCombinerInfo &DCI)
const {
16978 EVT VT =
N->getValueType(0);
16982 SelectionDAG &DAG = DCI.DAG;
16993 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16997 const SIMachineFunctionInfo *
Info = MF.
getInfo<SIMachineFunctionInfo>();
17001 if (
Info->getMode().DX10Clamp) {
17014 return DAG.
getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17021 DAGCombinerInfo &DCI)
const {
17025 return DCI.DAG.getUNDEF(
N->getValueType(0));
17033 bool IsDivergentIdx,
17038 unsigned VecSize = EltSize * NumElem;
17041 if (VecSize <= 64 && EltSize < 32)
17050 if (IsDivergentIdx)
17054 unsigned NumInsts = NumElem +
17055 ((EltSize + 31) / 32) * NumElem ;
17059 if (Subtarget->useVGPRIndexMode())
17060 return NumInsts <= 16;
17064 if (Subtarget->hasMovrel())
17065 return NumInsts <= 15;
17071 SDValue Idx =
N->getOperand(
N->getNumOperands() - 1);
17086SITargetLowering::performExtractVectorEltCombine(
SDNode *
N,
17087 DAGCombinerInfo &DCI)
const {
17093 EVT ResVT =
N->getValueType(0);
17117 if (!
C ||
C->getZExtValue() != 0x1f)
17133 if (Vec.
hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17161 DCI.AddToWorklist(Elt0.
getNode());
17162 DCI.AddToWorklist(Elt1.
getNode());
17193 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17194 uint64_t KImmValue = KImm->getZExtValue();
17196 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17199 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17201 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17202 return DAG.
getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17208 if (!DCI.isBeforeLegalize())
17215 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17218 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17219 unsigned EltIdx = BitIndex / 32;
17220 unsigned LeftoverBitIdx = BitIndex % 32;
17224 DCI.AddToWorklist(Cast.
getNode());
17228 DCI.AddToWorklist(Elt.
getNode());
17231 DCI.AddToWorklist(Srl.
getNode());
17235 DCI.AddToWorklist(Trunc.
getNode());
17237 if (VecEltVT == ResVT) {
17249SITargetLowering::performInsertVectorEltCombine(
SDNode *
N,
17250 DAGCombinerInfo &DCI)
const {
17261 SelectionDAG &DAG = DCI.DAG;
17281 Src.getOperand(0).getValueType() == MVT::f16) {
17282 return Src.getOperand(0);
17286 APFloat Val = CFP->getValueAPF();
17287 bool LosesInfo =
true;
17297 DAGCombinerInfo &DCI)
const {
17298 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17299 "combine only useful on gfx8");
17301 SDValue TruncSrc =
N->getOperand(0);
17302 EVT VT =
N->getValueType(0);
17303 if (VT != MVT::f16)
17306 if (TruncSrc.
getOpcode() != AMDGPUISD::FMED3 ||
17310 SelectionDAG &DAG = DCI.DAG;
17341unsigned SITargetLowering::getFusedOpcode(
const SelectionDAG &DAG,
17343 const SDNode *N1)
const {
17348 if (((VT == MVT::f32 &&
17350 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17367 EVT VT =
N->getValueType(0);
17368 if (VT != MVT::i32 && VT != MVT::i64)
17374 unsigned Opc =
N->getOpcode();
17396 SDValue Add1 = DAG.
getNode(
Opc, SL, VT, Op0, Op1);
17429 if (!Const ||
Hi_32(Const->getZExtValue()) !=
uint32_t(-1))
17448 DAGCombinerInfo &DCI)
const {
17451 SelectionDAG &DAG = DCI.DAG;
17452 EVT VT =
N->getValueType(0);
17454 SDValue
LHS =
N->getOperand(0);
17455 SDValue
RHS =
N->getOperand(1);
17462 if (!
N->isDivergent() && Subtarget->hasSMulHi())
17466 if (NumBits <= 32 || NumBits > 64)
17477 if (!Subtarget->hasFullRate64Ops()) {
17478 unsigned NumUsers = 0;
17479 for (SDNode *User :
LHS->
users()) {
17482 if (!
User->isAnyAdd())
17493 SDValue MulLHS =
LHS.getOperand(0);
17494 SDValue MulRHS =
LHS.getOperand(1);
17495 SDValue AddRHS =
RHS;
17506 bool MulSignedLo =
false;
17507 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17516 if (VT != MVT::i64) {
17539 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17541 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17542 auto [AccumLo, AccumHi] = DAG.
SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17544 if (!MulLHSUnsigned32) {
17547 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17551 if (!MulRHSUnsigned32) {
17554 SDValue MulHi = DAG.
getNode(
ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17562 if (VT != MVT::i64)
17568SITargetLowering::foldAddSub64WithZeroLowBitsTo32(
SDNode *
N,
17569 DAGCombinerInfo &DCI)
const {
17570 SDValue
RHS =
N->getOperand(1);
17579 SelectionDAG &DAG = DCI.DAG;
17581 SDValue
LHS =
N->getOperand(0);
17594 unsigned Opcode =
N->getOpcode();
17598 DAG.
getNode(Opcode, SL, MVT::i32,
Hi, ConstHi32,
N->getFlags());
17609static std::optional<ByteProvider<SDValue>>
17612 if (!Byte0 || Byte0->isConstantZero()) {
17613 return std::nullopt;
17616 if (Byte1 && !Byte1->isConstantZero()) {
17617 return std::nullopt;
17623 unsigned FirstCs =
First & 0x0c0c0c0c;
17624 unsigned SecondCs = Second & 0x0c0c0c0c;
17625 unsigned FirstNoCs =
First & ~0x0c0c0c0c;
17626 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17628 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17629 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17630 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17631 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17633 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17657 for (
int BPI = 0; BPI < 2; BPI++) {
17660 BPP = {Src1, Src0};
17662 unsigned ZeroMask = 0x0c0c0c0c;
17663 unsigned FMask = 0xFF << (8 * (3 - Step));
17665 unsigned FirstMask =
17666 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17667 unsigned SecondMask =
17668 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17672 int FirstGroup = -1;
17673 for (
int I = 0;
I < 2;
I++) {
17675 auto MatchesFirst = [&BPP](
DotSrc &IterElt) {
17676 return IterElt.SrcOp == *BPP.first.Src &&
17677 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17681 if (Match != Srcs.
end()) {
17682 Match->PermMask =
addPermMasks(FirstMask, Match->PermMask);
17687 if (FirstGroup != -1) {
17689 auto MatchesSecond = [&BPP](
DotSrc &IterElt) {
17690 return IterElt.SrcOp == *BPP.second.Src &&
17691 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17694 if (Match != Srcs.
end()) {
17695 Match->PermMask =
addPermMasks(SecondMask, Match->PermMask);
17697 Srcs.
push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17705 unsigned ZeroMask = 0x0c0c0c0c;
17706 unsigned FMask = 0xFF << (8 * (3 - Step));
17710 ((Src0.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17714 ((Src1.
SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17723 if (Srcs.
size() == 1) {
17724 auto *Elt = Srcs.
begin();
17728 if (Elt->PermMask == 0x3020100)
17731 return DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17735 auto *FirstElt = Srcs.
begin();
17736 auto *SecondElt = std::next(FirstElt);
17743 auto FirstMask = FirstElt->PermMask;
17744 auto SecondMask = SecondElt->PermMask;
17746 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17747 unsigned FirstPlusFour = FirstMask | 0x04040404;
17750 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17762 FirstElt = std::next(SecondElt);
17763 if (FirstElt == Srcs.
end())
17766 SecondElt = std::next(FirstElt);
17769 if (SecondElt == Srcs.
end()) {
17774 DAG.
getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17775 DAG.
getConstant(FirstElt->PermMask, SL, MVT::i32)));
17781 return Perms.
size() == 2
17787 for (
auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17788 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17789 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17790 EntryMask += ZeroMask;
17795 auto Opcode =
Op.getOpcode();
17797 return (Opcode ==
ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17798 Opcode == AMDGPUISD::MUL_I24);
17801static std::optional<bool>
17812 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17815 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17817 assert(!(S0IsUnsigned && S0IsSigned));
17818 assert(!(S1IsUnsigned && S1IsSigned));
17826 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17832 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17833 return std::nullopt;
17845 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17846 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17851 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17857 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17858 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17859 return std::nullopt;
17865 DAGCombinerInfo &DCI)
const {
17866 SelectionDAG &DAG = DCI.DAG;
17867 EVT VT =
N->getValueType(0);
17869 SDValue
LHS =
N->getOperand(0);
17870 SDValue
RHS =
N->getOperand(1);
17873 if (Subtarget->hasMad64_32()) {
17874 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
17879 if (SDValue V = reassociateScalarOps(
N, DAG)) {
17883 if (VT == MVT::i64) {
17884 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
17891 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17892 SDValue TempNode(
N, 0);
17893 std::optional<bool> IsSigned;
17899 int ChainLength = 0;
17900 for (
int I = 0;
I < 4;
I++) {
17904 auto Src0 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17907 auto Src1 =
handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17912 TempNode->getOperand(MulIdx), *Src0, *Src1,
17913 TempNode->getOperand(MulIdx)->getOperand(0),
17914 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17918 IsSigned = *IterIsSigned;
17919 if (*IterIsSigned != *IsSigned)
17922 auto AddIdx = 1 - MulIdx;
17925 if (
I == 2 &&
isMul(TempNode->getOperand(AddIdx))) {
17926 Src2s.
push_back(TempNode->getOperand(AddIdx));
17936 TempNode->getOperand(AddIdx), *Src0, *Src1,
17937 TempNode->getOperand(AddIdx)->getOperand(0),
17938 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17942 if (*IterIsSigned != *IsSigned)
17946 ChainLength =
I + 2;
17950 TempNode = TempNode->getOperand(AddIdx);
17952 ChainLength =
I + 1;
17954 if (TempNode.getOpcode() !=
ISD::ADD)
17956 LHS = TempNode->getOperand(0);
17957 RHS = TempNode->getOperand(1);
17960 if (ChainLength < 2)
17966 if (ChainLength < 4) {
17971 SDValue Src0, Src1;
17976 bool UseOriginalSrc =
false;
17977 if (ChainLength == 4 && Src0s.
size() == 1 && Src1s.
size() == 1 &&
17978 Src0s.
begin()->PermMask == Src1s.
begin()->PermMask &&
17979 Src0s.
begin()->SrcOp.getValueSizeInBits() >= 32 &&
17980 Src1s.
begin()->SrcOp.getValueSizeInBits() >= 32) {
17981 SmallVector<unsigned, 4> SrcBytes;
17982 auto Src0Mask = Src0s.
begin()->PermMask;
17983 SrcBytes.
push_back(Src0Mask & 0xFF000000);
17984 bool UniqueEntries =
true;
17985 for (
auto I = 1;
I < 4;
I++) {
17986 auto NextByte = Src0Mask & (0xFF << ((3 -
I) * 8));
17989 UniqueEntries =
false;
17995 if (UniqueEntries) {
17996 UseOriginalSrc =
true;
17998 auto *FirstElt = Src0s.
begin();
18002 auto *SecondElt = Src1s.
begin();
18004 SecondElt->DWordOffset);
18013 if (!UseOriginalSrc) {
18020 DAG.
getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18023 : Intrinsic::amdgcn_udot4,
18033 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18038 unsigned Opc =
LHS.getOpcode();
18050 auto Cond =
RHS.getOperand(0);
18055 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18064 SDValue
Args[] = {
LHS,
RHS.getOperand(0),
RHS.getOperand(2)};
18072 DAGCombinerInfo &DCI)
const {
18073 SelectionDAG &DAG = DCI.DAG;
18075 EVT VT =
N->getValueType(0);
18088 SDNodeFlags ShlFlags = N1->
getFlags();
18092 SDNodeFlags NewShlFlags =
18097 DCI.AddToWorklist(Inner.
getNode());
18104 if (Subtarget->hasMad64_32()) {
18105 if (SDValue Folded = tryFoldToMad64_32(
N, DCI))
18114 if (VT == MVT::i64) {
18115 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18128 if (!YIsConstant && !ZIsConstant && !
X->isDivergent() &&
18129 Y->isDivergent() !=
Z->isDivergent()) {
18138 if (
Y->isDivergent())
18141 SDNodeFlags ReassocFlags =
18144 DCI.AddToWorklist(UniformInner.
getNode());
18156 DAGCombinerInfo &DCI)
const {
18157 SelectionDAG &DAG = DCI.DAG;
18158 EVT VT =
N->getValueType(0);
18160 if (VT == MVT::i64) {
18161 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(
N, DCI))
18165 if (VT != MVT::i32)
18169 SDValue
LHS =
N->getOperand(0);
18170 SDValue
RHS =
N->getOperand(1);
18174 unsigned Opc =
RHS.getOpcode();
18181 auto Cond =
RHS.getOperand(0);
18186 SDVTList VTList = DAG.
getVTList(MVT::i32, MVT::i1);
18197 SDValue
Args[] = {
LHS.getOperand(0),
RHS,
LHS.getOperand(2)};
18203 SDValue CtlzSrc =
LHS.getOperand(0);
18212 ConstantSDNode *ShiftAmt =
18214 unsigned BitWidth =
X.getValueType().getScalarSizeInBits();
18225 DAGCombinerInfo &DCI)
const {
18229 SelectionDAG &DAG = DCI.DAG;
18230 EVT VT =
N->getValueType(0);
18233 SDValue
LHS =
N->getOperand(0);
18234 SDValue
RHS =
N->getOperand(1);
18241 SDValue
A =
LHS.getOperand(0);
18242 if (
A ==
LHS.getOperand(1)) {
18243 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18244 if (FusedOp != 0) {
18246 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
RHS);
18253 SDValue
A =
RHS.getOperand(0);
18254 if (
A ==
RHS.getOperand(1)) {
18255 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18256 if (FusedOp != 0) {
18258 return DAG.
getNode(FusedOp, SL, VT,
A, Two,
LHS);
18267 DAGCombinerInfo &DCI)
const {
18271 SelectionDAG &DAG = DCI.DAG;
18273 EVT VT =
N->getValueType(0);
18281 SDValue
LHS =
N->getOperand(0);
18282 SDValue
RHS =
N->getOperand(1);
18285 SDValue
A =
LHS.getOperand(0);
18286 if (
A ==
LHS.getOperand(1)) {
18287 unsigned FusedOp = getFusedOpcode(DAG,
N,
LHS.getNode());
18288 if (FusedOp != 0) {
18292 return DAG.
getNode(FusedOp, SL, VT,
A, Two, NegRHS);
18300 SDValue
A =
RHS.getOperand(0);
18301 if (
A ==
RHS.getOperand(1)) {
18302 unsigned FusedOp = getFusedOpcode(DAG,
N,
RHS.getNode());
18303 if (FusedOp != 0) {
18305 return DAG.
getNode(FusedOp, SL, VT,
A, NegTwo,
LHS);
18314 DAGCombinerInfo &DCI)
const {
18315 SelectionDAG &DAG = DCI.DAG;
18317 EVT VT =
N->getValueType(0);
18319 if (VT != MVT::f16 && VT != MVT::bf16)
18322 SDValue
LHS =
N->getOperand(0);
18323 SDValue
RHS =
N->getOperand(1);
18325 SDNodeFlags
Flags =
N->getFlags();
18326 SDNodeFlags RHSFlags =
RHS->getFlags();
18332 bool IsNegative =
false;
18333 if (CLHS->
isOne() || (IsNegative = CLHS->isMinusOne())) {
18338 SDValue SqrtOp =
RHS.getOperand(0);
18342 Rsq = DAG.
getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18343 }
else if (VT == MVT::f16) {
18352 DAG.
getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18369 DAGCombinerInfo &DCI)
const {
18370 SelectionDAG &DAG = DCI.DAG;
18371 EVT VT =
N->getValueType(0);
18375 if (!
N->isDivergent() &&
getSubtarget()->hasSALUFloatInsts() &&
18376 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18381 SDValue
LHS =
N->getOperand(0);
18382 SDValue
RHS =
N->getOperand(1);
18391 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18396 const ConstantFPSDNode *FalseNode =
18406 if (ScalarVT == MVT::f32 &&
18412 if (TrueNodeExpVal == INT_MIN)
18415 if (FalseNodeExpVal == INT_MIN)
18419 SDValue SelectNode =
18435 DAGCombinerInfo &DCI)
const {
18436 SelectionDAG &DAG = DCI.DAG;
18437 EVT VT =
N->getValueType(0);
18440 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18447 SDValue
FMA =
N->getOperand(2);
18468 bool AllowInaccuracy =
N->getFlags().hasApproximateFuncs() &&
18469 FMA->getFlags().hasApproximateFuncs();
18470 if (!AllowInaccuracy) {
18473 if (Subtarget->dot2UnconditionalFlush()) {
18485 if (
N->getFlags().hasAllowContract() &&
FMA->getFlags().hasAllowContract()) {
18496 SDValue FMAOp1 =
FMA.getOperand(0);
18497 SDValue FMAOp2 =
FMA.getOperand(1);
18498 SDValue FMAAcc =
FMA.getOperand(2);
18521 if (Vec1 == Vec2 || Vec3 == Vec4)
18527 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18528 return DAG.
getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18571 EVT VT =
LHS.getValueType();
18572 assert(VT == MVT::f64 &&
"Incorrect operand type!");
18604 if (CC ==
ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18608 if (CC ==
ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18612 if (CC ==
ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18616 if (CC ==
ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18619 const std::optional<bool> KnownEq =
18648 if (CC ==
ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18652 if (CC ==
ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18660 const std::optional<bool> KnownUge =
18685 if (CC ==
ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18699 if (CC ==
ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18702 const std::optional<bool> KnownUle =
18725 DAGCombinerInfo &DCI)
const {
18726 SelectionDAG &DAG = DCI.DAG;
18729 SDValue
LHS =
N->getOperand(0);
18730 SDValue
RHS =
N->getOperand(1);
18731 EVT VT =
LHS.getValueType();
18760 return LHS.getOperand(0);
18774 const APInt &CT =
LHS.getConstantOperandAPInt(1);
18775 const APInt &CF =
LHS.getConstantOperandAPInt(2);
18780 return DAG.
getNOT(SL,
LHS.getOperand(0), MVT::i1);
18783 return LHS.getOperand(0);
18804 if (VT == MVT::i64) {
18816 const std::optional<bool> KnownEq =
18824 const std::optional<bool> KnownEq =
18835 const std::optional<bool> KnownUge =
18855 const std::optional<bool> KnownUle =
18895 SDValue Op0 =
LHS.getOperand(0);
18896 SDValue Op1 =
LHS.getOperand(1);
18906 DAG.
getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18908 SDValue CarryInHi = NodeLo.
getValue(1);
18911 {Op0Hi, Op1Hi, CarryInHi});
18913 SDValue ResultLo = NodeLo.
getValue(0);
18914 SDValue ResultHi = NodeHi.
getValue(0);
18916 SDValue JoinedResult =
18920 SDValue Overflow = NodeHi.
getValue(1);
18921 DCI.CombineTo(
LHS.getNode(), Result);
18925 if (VT != MVT::f32 && VT != MVT::f64 &&
18926 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18941 const unsigned IsInfMask =
18943 const unsigned IsFiniteMask =
18948 return DAG.
getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1,
LHS.getOperand(0),
18953 if (VT == MVT::f64) {
18964SITargetLowering::performCvtF32UByteNCombine(
SDNode *
N,
18965 DAGCombinerInfo &DCI)
const {
18966 SelectionDAG &DAG = DCI.DAG;
18968 unsigned Offset =
N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18970 SDValue Src =
N->getOperand(0);
18971 SDValue Shift =
N->getOperand(0);
18987 unsigned ShiftOffset = 8 *
Offset;
18989 ShiftOffset -=
C->getZExtValue();
18991 ShiftOffset +=
C->getZExtValue();
18993 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18994 return DAG.
getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18995 MVT::f32, Shifted);
19006 DCI.AddToWorklist(
N);
19007 return SDValue(
N, 0);
19011 if (SDValue DemandedSrc =
19013 return DAG.
getNode(
N->getOpcode(), SL, MVT::f32, DemandedSrc);
19019 DAGCombinerInfo &DCI)
const {
19028 (
F.isNaN() && MF.
getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19029 return DCI.DAG.getConstantFP(Zero, SDLoc(
N),
N->getValueType(0));
19034 return DCI.DAG.getConstantFP(One, SDLoc(
N),
N->getValueType(0));
19036 return getCanonicalConstantFP(DCI.DAG, SDLoc(
N),
N->getValueType(0),
F);
19045 if (V.getOpcode() ==
ISD::FFREXP && V.getResNo() == 1) {
19056SITargetLowering::performFrexpSelectCombine(
SDNode *
N,
19057 DAGCombinerInfo &DCI)
const {
19059 if (Subtarget->hasFractBug())
19062 SDValue
Cond =
N->getOperand(0);
19063 SDValue
TrueVal =
N->getOperand(1);
19071 bool CondSelectsZero;
19075 SDValue FrexpInput;
19079 CondSelectsZero =
true;
19080 }
else if (
isFrexpExp(TrueVal, FrexpInput)) {
19083 CondSelectsZero =
false;
19095 bool IsNonFiniteTest =
false;
19101 SDValue CondLHS =
Cond.getOperand(0);
19102 SDValue CondRHS =
Cond.getOperand(1);
19107 bool LHSMatchesFrexp =
19108 (CondLHS == FrexpInput) ||
19109 (LHSIsFabs &&
peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19111 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19119 SelectionDAG &DAG = DCI.DAG;
19120 if (LHSMatchesFrexp &&
19122 IsNonFiniteTest = CondSelectsZero;
19124 IsNonFiniteTest = CondSelectsZero;
19131 IsNonFiniteTest = CondSelectsZero;
19138 IsNonFiniteTest = !CondSelectsZero;
19144 SelectionDAG &DAG = DCI.DAG;
19145 if (LHSMatchesFrexp &&
19147 IsNonFiniteTest = !CondSelectsZero;
19149 IsNonFiniteTest = !CondSelectsZero;
19153 if (!IsNonFiniteTest)
19161 DAGCombinerInfo &DCI)
const {
19170 SDValue
Cond =
N->getOperand(0);
19171 SDValue
TrueVal =
N->getOperand(1);
19178 SDValue
LHS =
Cond.getOperand(0);
19179 SDValue
RHS =
Cond.getOperand(1);
19182 bool isFloatingPoint =
LHS.getValueType().isFloatingPoint();
19183 bool isInteger =
LHS.getValueType().isInteger();
19186 if (!isFloatingPoint && !isInteger)
19191 bool isNonEquality =
19193 if (!isEquality && !isNonEquality)
19196 SDValue ArgVal, ConstVal;
19210 if (isFloatingPoint) {
19212 if (!Val.
isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19215 const std::optional<int64_t> Val =
19224 if (!(isEquality && TrueVal == ConstVal) &&
19225 !(isNonEquality && FalseVal == ConstVal))
19229 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19230 !
Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19233 SDValue SelectLHS = (isEquality &&
TrueVal == ConstVal) ? ArgVal :
TrueVal;
19234 SDValue SelectRHS =
19237 SelectLHS, SelectRHS);
19242 switch (
N->getOpcode()) {
19264 if (
auto Res = promoteUniformOpToI32(
SDValue(
N, 0), DCI))
19274 switch (
N->getOpcode()) {
19276 return performAddCombine(
N, DCI);
19278 return performPtrAddCombine(
N, DCI);
19280 return performSubCombine(
N, DCI);
19282 return performFAddCombine(
N, DCI);
19284 return performFSubCombine(
N, DCI);
19286 return performFDivCombine(
N, DCI);
19288 return performFMulCombine(
N, DCI);
19290 return performSetCCCombine(
N, DCI);
19292 if (
auto Res = performFrexpSelectCombine(
N, DCI))
19294 if (
auto Res = performSelectCombine(
N, DCI))
19309 case AMDGPUISD::FMIN_LEGACY:
19310 case AMDGPUISD::FMAX_LEGACY:
19311 return performMinMaxCombine(
N, DCI);
19313 return performFMACombine(
N, DCI);
19315 return performAndCombine(
N, DCI);
19317 return performOrCombine(
N, DCI);
19320 if (
N->getValueType(0) == MVT::i32 &&
N->isDivergent() &&
19321 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19327 return performXorCombine(
N, DCI);
19330 return performZeroOrAnyExtendCombine(
N, DCI);
19332 return performSignExtendInRegCombine(
N, DCI);
19333 case AMDGPUISD::FP_CLASS:
19334 return performClassCombine(
N, DCI);
19336 return performFCanonicalizeCombine(
N, DCI);
19337 case AMDGPUISD::RCP:
19338 return performRcpCombine(
N, DCI);
19340 case AMDGPUISD::FRACT:
19341 case AMDGPUISD::RSQ:
19342 case AMDGPUISD::RCP_LEGACY:
19343 case AMDGPUISD::RCP_IFLAG:
19344 case AMDGPUISD::RSQ_CLAMP: {
19353 return performUCharToFloatCombine(
N, DCI);
19355 return performFCopySignCombine(
N, DCI);
19356 case AMDGPUISD::CVT_F32_UBYTE0:
19357 case AMDGPUISD::CVT_F32_UBYTE1:
19358 case AMDGPUISD::CVT_F32_UBYTE2:
19359 case AMDGPUISD::CVT_F32_UBYTE3:
19360 return performCvtF32UByteNCombine(
N, DCI);
19361 case AMDGPUISD::FMED3:
19362 return performFMed3Combine(
N, DCI);
19363 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19364 return performCvtPkRTZCombine(
N, DCI);
19365 case AMDGPUISD::CLAMP:
19366 return performClampCombine(
N, DCI);
19369 EVT VT =
N->getValueType(0);
19372 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19375 EVT EltVT = Src.getValueType();
19376 if (EltVT != MVT::i16)
19386 return performExtractVectorEltCombine(
N, DCI);
19388 return performInsertVectorEltCombine(
N, DCI);
19390 return performFPRoundCombine(
N, DCI);
19399 return performMemSDNodeCombine(MemNode, DCI);
19430 unsigned Opcode =
Node->getMachineOpcode();
19433 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19434 if (D16Idx >= 0 &&
Node->getConstantOperandVal(D16Idx))
19437 SDNode *
Users[5] = {
nullptr};
19439 unsigned DmaskIdx =
19440 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19441 unsigned OldDmask =
Node->getConstantOperandVal(DmaskIdx);
19442 unsigned NewDmask = 0;
19443 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19444 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19445 bool UsesTFC = (int(TFEIdx) >= 0 &&
Node->getConstantOperandVal(TFEIdx)) ||
19446 (
int(LWEIdx) >= 0 &&
Node->getConstantOperandVal(LWEIdx));
19447 unsigned TFCLane = 0;
19448 bool HasChain =
Node->getNumValues() > 1;
19450 if (OldDmask == 0) {
19458 TFCLane = OldBitsSet;
19462 for (SDUse &Use :
Node->uses()) {
19465 if (
Use.getResNo() != 0)
19468 SDNode *
User =
Use.getUser();
19471 if (!
User->isMachineOpcode() ||
19472 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19484 if (UsesTFC && Lane == TFCLane) {
19489 for (
unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19491 Dmask &= ~(1 << Comp);
19499 NewDmask |= 1 << Comp;
19504 bool NoChannels = !NewDmask;
19511 if (OldBitsSet == 1)
19517 if (NewDmask == OldDmask)
19526 unsigned NewChannels = BitsSet + UsesTFC;
19530 assert(NewOpcode != -1 &&
19531 NewOpcode !=
static_cast<int>(
Node->getMachineOpcode()) &&
19532 "failed to find equivalent MIMG op");
19540 MVT SVT =
Node->getValueType(0).getVectorElementType().getSimpleVT();
19542 MVT ResultVT = NewChannels == 1
19545 : NewChannels == 5 ? 8
19547 SDVTList NewVTList =
19550 MachineSDNode *NewNode =
19559 if (NewChannels == 1) {
19569 for (
unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19574 if (i || !NoChannels)
19579 if (NewUser != User) {
19589 Idx = AMDGPU::sub1;
19592 Idx = AMDGPU::sub2;
19595 Idx = AMDGPU::sub3;
19598 Idx = AMDGPU::sub4;
19609 Op =
Op.getOperand(0);
19634 Node->getOperand(0), SL, VReg, SrcVal,
19640 return ToResultReg.
getNode();
19645 for (
unsigned i = 0; i <
Node->getNumOperands(); ++i) {
19647 Ops.push_back(
Node->getOperand(i));
19653 Node->getOperand(i).getValueType(),
19654 Node->getOperand(i)),
19666 unsigned Opcode =
Node->getMachineOpcode();
19668 if (
TII->isImage(Opcode) && !
TII->get(Opcode).mayStore() &&
19669 !
TII->isGather4(Opcode) &&
19671 return adjustWritemask(
Node, DAG);
19674 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19680 case AMDGPU::V_DIV_SCALE_F32_e64:
19681 case AMDGPU::V_DIV_SCALE_F64_e64: {
19691 (Src0 == Src1 || Src0 == Src2))
19747 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
19748 unsigned InitIdx = 0;
19750 if (
TII->isImage(
MI)) {
19758 unsigned TFEVal = TFE ? TFE->
getImm() : 0;
19759 unsigned LWEVal = LWE ? LWE->
getImm() : 0;
19760 unsigned D16Val = D16 ? D16->getImm() : 0;
19762 if (!TFEVal && !LWEVal)
19773 assert(MO_Dmask &&
"Expected dmask operand in instruction");
19775 unsigned dmask = MO_Dmask->
getImm();
19780 bool Packed = !Subtarget->hasUnpackedD16VMem();
19782 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19789 uint32_t DstSize =
TRI.getRegSizeInBits(*DstRC) / 32;
19790 if (DstSize < InitIdx)
19794 InitIdx =
TRI.getRegSizeInBits(*DstRC) / 32;
19803 unsigned NewDst = 0;
19808 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19809 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19812 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19833 MI.tieOperands(DstIdx,
MI.getNumOperands() - 1);
19845 if (
TII->isVOP3(
MI.getOpcode())) {
19847 TII->legalizeOperandsVOP3(MRI,
MI);
19849 if (
TII->isMAI(
MI)) {
19854 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19855 AMDGPU::OpName::scale_src0);
19856 if (Src0Idx != -1) {
19857 int Src1Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
19858 AMDGPU::OpName::scale_src1);
19859 if (
TII->usesConstantBus(MRI,
MI, Src0Idx) &&
19860 TII->usesConstantBus(MRI,
MI, Src1Idx))
19861 TII->legalizeOpWithMove(
MI, Src1Idx);
19868 if (
TII->isImage(
MI))
19869 TII->enforceOperandRCAlignment(
MI, AMDGPU::OpName::vaddr);
19911 uint64_t RsrcDword2And3)
const {
19941std::pair<unsigned, const TargetRegisterClass *>
19948 if (Constraint.
size() == 1) {
19952 if (VT == MVT::Other)
19955 switch (Constraint[0]) {
19962 RC = &AMDGPU::SReg_32RegClass;
19965 RC = &AMDGPU::SGPR_64RegClass;
19970 return std::pair(0U,
nullptr);
19977 return std::pair(0U,
nullptr);
19979 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19980 : &AMDGPU::VGPR_32_Lo256RegClass;
19983 RC = Subtarget->has1024AddressableVGPRs()
19984 ?
TRI->getAlignedLo256VGPRClassForBitWidth(
BitWidth)
19987 return std::pair(0U,
nullptr);
19992 if (!Subtarget->hasMAIInsts())
19996 return std::pair(0U,
nullptr);
19998 RC = &AMDGPU::AGPR_32RegClass;
20003 return std::pair(0U,
nullptr);
20008 }
else if (Constraint ==
"VA" && Subtarget->hasGFX90AInsts()) {
20012 RC = &AMDGPU::AV_32RegClass;
20015 RC =
TRI->getVectorSuperClassForBitWidth(
BitWidth);
20017 return std::pair(0U,
nullptr);
20026 return std::pair(0U, RC);
20029 if (Kind !=
'\0') {
20031 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20032 }
else if (Kind ==
's') {
20033 RC = &AMDGPU::SGPR_32RegClass;
20034 }
else if (Kind ==
'a') {
20035 RC = &AMDGPU::AGPR_32RegClass;
20041 return std::pair(0U,
nullptr);
20047 return std::pair(0U,
nullptr);
20051 RC =
TRI->getVGPRClassForBitWidth(Width);
20053 RC =
TRI->getSGPRClassForBitWidth(Width);
20055 RC =
TRI->getAGPRClassForBitWidth(Width);
20057 Reg =
TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20062 return std::pair(0U,
nullptr);
20064 return std::pair(Reg, RC);
20073 return std::pair(0U,
nullptr);
20074 if (RC && Idx < RC->getNumRegs())
20076 return std::pair(0U,
nullptr);
20082 Ret.second =
TRI->getPhysRegBaseClass(Ret.first);
20088 if (Constraint.
size() == 1) {
20089 switch (Constraint[0]) {
20099 }
else if (Constraint ==
"DA" || Constraint ==
"DB") {
20107 if (Constraint.
size() == 1) {
20108 switch (Constraint[0]) {
20116 }
else if (Constraint.
size() == 2) {
20117 if (Constraint ==
"VA")
20135 std::vector<SDValue> &
Ops,
20150 unsigned Size =
Op.getScalarValueSizeInBits();
20154 if (
Size == 16 && !Subtarget->has16BitInsts())
20158 Val =
C->getSExtValue();
20162 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20166 if (
Size != 16 ||
Op.getNumOperands() != 2)
20168 if (
Op.getOperand(0).isUndef() ||
Op.getOperand(1).isUndef())
20171 Val =
C->getSExtValue();
20175 Val =
C->getValueAPF().bitcastToAPInt().getSExtValue();
20184 uint64_t Val)
const {
20185 if (Constraint.
size() == 1) {
20186 switch (Constraint[0]) {
20201 }
else if (Constraint.
size() == 2) {
20202 if (Constraint ==
"DA") {
20203 int64_t HiBits =
static_cast<int32_t
>(Val >> 32);
20204 int64_t LoBits =
static_cast<int32_t
>(Val);
20208 if (Constraint ==
"DB") {
20216 unsigned MaxSize)
const {
20217 unsigned Size = std::min<unsigned>(
Op.getScalarValueSizeInBits(), MaxSize);
20218 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20220 MVT VT =
Op.getSimpleValueType();
20245 switch (UnalignedClassID) {
20246 case AMDGPU::VReg_64RegClassID:
20247 return AMDGPU::VReg_64_Align2RegClassID;
20248 case AMDGPU::VReg_96RegClassID:
20249 return AMDGPU::VReg_96_Align2RegClassID;
20250 case AMDGPU::VReg_128RegClassID:
20251 return AMDGPU::VReg_128_Align2RegClassID;
20252 case AMDGPU::VReg_160RegClassID:
20253 return AMDGPU::VReg_160_Align2RegClassID;
20254 case AMDGPU::VReg_192RegClassID:
20255 return AMDGPU::VReg_192_Align2RegClassID;
20256 case AMDGPU::VReg_224RegClassID:
20257 return AMDGPU::VReg_224_Align2RegClassID;
20258 case AMDGPU::VReg_256RegClassID:
20259 return AMDGPU::VReg_256_Align2RegClassID;
20260 case AMDGPU::VReg_288RegClassID:
20261 return AMDGPU::VReg_288_Align2RegClassID;
20262 case AMDGPU::VReg_320RegClassID:
20263 return AMDGPU::VReg_320_Align2RegClassID;
20264 case AMDGPU::VReg_352RegClassID:
20265 return AMDGPU::VReg_352_Align2RegClassID;
20266 case AMDGPU::VReg_384RegClassID:
20267 return AMDGPU::VReg_384_Align2RegClassID;
20268 case AMDGPU::VReg_512RegClassID:
20269 return AMDGPU::VReg_512_Align2RegClassID;
20270 case AMDGPU::VReg_1024RegClassID:
20271 return AMDGPU::VReg_1024_Align2RegClassID;
20272 case AMDGPU::AReg_64RegClassID:
20273 return AMDGPU::AReg_64_Align2RegClassID;
20274 case AMDGPU::AReg_96RegClassID:
20275 return AMDGPU::AReg_96_Align2RegClassID;
20276 case AMDGPU::AReg_128RegClassID:
20277 return AMDGPU::AReg_128_Align2RegClassID;
20278 case AMDGPU::AReg_160RegClassID:
20279 return AMDGPU::AReg_160_Align2RegClassID;
20280 case AMDGPU::AReg_192RegClassID:
20281 return AMDGPU::AReg_192_Align2RegClassID;
20282 case AMDGPU::AReg_256RegClassID:
20283 return AMDGPU::AReg_256_Align2RegClassID;
20284 case AMDGPU::AReg_512RegClassID:
20285 return AMDGPU::AReg_512_Align2RegClassID;
20286 case AMDGPU::AReg_1024RegClassID:
20287 return AMDGPU::AReg_1024_Align2RegClassID;
20303 if (Info->isEntryFunction()) {
20310 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20312 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20313 :
TRI->getAlignedHighSGPRForRC(MF, 2,
20314 &AMDGPU::SGPR_64RegClass);
20315 Info->setSGPRForEXECCopy(SReg);
20317 assert(!
TRI->isSubRegister(Info->getScratchRSrcReg(),
20318 Info->getStackPtrOffsetReg()));
20319 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20320 MRI.
replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20324 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20325 MRI.
replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20327 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20330 Info->limitOccupancy(MF);
20332 if (ST.isWave32() && !MF.
empty()) {
20333 for (
auto &
MBB : MF) {
20334 for (
auto &
MI :
MBB) {
20335 TII->fixImplicitOperands(
MI);
20345 if (ST.needsAlignedVGPRs()) {
20352 if (NewClassID != -1)
20362 const APInt &DemandedElts,
20364 unsigned Depth)
const {
20366 unsigned Opc =
Op.getOpcode();
20369 unsigned IID =
Op.getConstantOperandVal(0);
20371 case Intrinsic::amdgcn_mbcnt_lo:
20372 case Intrinsic::amdgcn_mbcnt_hi: {
20377 Known.Zero.setBitsFrom(
20378 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20404 unsigned MaxValue =
20411 unsigned BFEWidth,
bool SExt,
unsigned Depth) {
20415 unsigned Src1Cst = 0;
20416 if (Src1.
isImm()) {
20417 Src1Cst = Src1.
getImm();
20418 }
else if (Src1.
isReg()) {
20422 Src1Cst = Cst->Value.getZExtValue();
20433 if (Width >= BFEWidth)
20450 unsigned Depth)
const {
20453 switch (
MI->getOpcode()) {
20454 case AMDGPU::S_BFE_I32:
20457 case AMDGPU::S_BFE_U32:
20460 case AMDGPU::S_BFE_I64:
20463 case AMDGPU::S_BFE_U64:
20466 case AMDGPU::G_INTRINSIC:
20467 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20470 case Intrinsic::amdgcn_workitem_id_x:
20473 case Intrinsic::amdgcn_workitem_id_y:
20476 case Intrinsic::amdgcn_workitem_id_z:
20479 case Intrinsic::amdgcn_mbcnt_lo:
20480 case Intrinsic::amdgcn_mbcnt_hi: {
20483 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20492 case Intrinsic::amdgcn_groupstaticsize: {
20496 Known.Zero.setHighBits(
20500 case Intrinsic::amdgcn_readfirstlane:
20501 case Intrinsic::amdgcn_readlane: {
20510 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20511 Known.Zero.setHighBits(24);
20513 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20514 Known.Zero.setHighBits(16);
20516 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20519 Known.Zero.setHighBits(
Known.getBitWidth() - 1);
20521 case AMDGPU::G_AMDGPU_SMED3:
20522 case AMDGPU::G_AMDGPU_UMED3: {
20523 auto [Dst, Src0, Src1, Src2] =
MI->getFirst4Regs();
20550 unsigned Depth)
const {
20559 if (
MaybeAlign RetAlign = Attrs.getRetAlignment())
20577 if (Header->getAlignment() != PrefAlign)
20578 return Header->getAlignment();
20579 if (needsFetchWindowAlignment(*Header))
20600 if (Header->getAlignment() != PrefAlign)
20601 return Header->getAlignment();
20603 unsigned LoopSize = 0;
20608 LoopSize +=
MBB->getAlignment().value() / 2;
20611 LoopSize +=
TII->getInstSizeInBytes(
MI);
20612 if (LoopSize > 192)
20617 if (LoopSize <= 64)
20620 if (LoopSize <= 128)
20621 return CacheLineAlign;
20627 auto I = Exit->getFirstNonDebugInstr();
20628 if (
I != Exit->end() &&
I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20629 return CacheLineAlign;
20638 if (PreTerm == Pre->
begin() ||
20639 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20643 auto ExitHead = Exit->getFirstNonDebugInstr();
20644 if (ExitHead == Exit->end() ||
20645 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20650 return CacheLineAlign;
20658 if (needsFetchWindowAlignment(*
MBB))
20663bool SITargetLowering::needsFetchWindowAlignment(
20665 if (!
getSubtarget()->hasLoopHeadInstSplitSensitivity())
20669 if (
MI.isMetaInstruction())
20672 return TII->getInstSizeInBytes(
MI) > 4;
20682 N =
N->getOperand(0).getNode();
20692 switch (
N->getOpcode()) {
20700 if (Reg.isPhysical() || MRI.
isLiveIn(Reg))
20701 return !
TRI->isSGPRReg(MRI, Reg);
20707 return !
TRI->isSGPRReg(MRI, Reg);
20711 unsigned AS = L->getAddressSpace();
20721 case AMDGPUISD::ATOMIC_CMP_SWAP:
20722 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20723 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20724 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20725 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20726 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20727 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20728 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20729 case AMDGPUISD::BUFFER_ATOMIC_AND:
20730 case AMDGPUISD::BUFFER_ATOMIC_OR:
20731 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20732 case AMDGPUISD::BUFFER_ATOMIC_INC:
20733 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20734 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20735 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20736 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20737 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20743 return A->readMem() &&
A->writeMem();
20764 switch (Ty.getScalarSizeInBits()) {
20776 const APInt &DemandedElts,
20779 unsigned Depth)
const {
20780 if (
Op.getOpcode() == AMDGPUISD::CLAMP) {
20784 if (Info->getMode().DX10Clamp)
20796 if (RMW->
hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
20816 <<
"Hardware instruction generated for atomic "
20818 <<
" operation at memory scope " << MemScope;
20823 Type *EltTy = VT->getElementType();
20824 return VT->getNumElements() == 2 &&
20844 unsigned BW =
IT->getBitWidth();
20845 return BW == 32 || BW == 64;
20859 unsigned BW =
DL.getPointerSizeInBits(PT->getAddressSpace());
20860 return BW == 32 || BW == 64;
20863 if (Ty->isFloatTy() || Ty->isDoubleTy())
20867 return VT->getNumElements() == 2 &&
20868 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20878 bool HasSystemScope) {
20885 if (HasSystemScope) {
20886 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20889 if (Subtarget.hasEmulatedSystemScopeAtomics())
20891 }
else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20894 return RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory");
20907 const MDNode *MD =
I->getMetadata(LLVMContext::MD_noalias_addrspace);
20915 return STI.hasGloballyAddressableScratch()
20933 DL.getTypeSizeInBits(RMW->
getType()) == 64 &&
20946 bool HasSystemScope =
20980 if (!
IT ||
IT->getBitWidth() != 32)
20986 if (Subtarget->hasEmulatedSystemScopeAtomics())
21002 if (!HasSystemScope &&
21003 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21015 if (RMW->
hasMetadata(
"amdgpu.no.fine.grained.memory"))
21024 ConstVal && ConstVal->isNullValue() &&
21063 if (Ty->isFloatTy()) {
21068 if (Ty->isDoubleTy()) {
21089 if (Ty->isFloatTy() &&
21090 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
21103 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21107 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() &&
isV2BF16(Ty))
21111 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() &&
isV2F16(Ty))
21116 if (Subtarget->hasAtomicBufferPkAddBF16Inst() &&
isV2BF16(Ty))
21121 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21125 if (Ty->isFloatTy()) {
21128 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21131 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21136 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21144 if (Subtarget->hasFlatAtomicFaddF32Inst())
21153 if (Subtarget->hasLDSFPAtomicAddF32()) {
21154 if (RMW->
use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21156 if (!RMW->
use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21184 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21186 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21190 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21192 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21246 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21247 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21248 : &AMDGPU::SReg_32RegClass;
21249 if (!
TRI->isSGPRClass(RC) && !isDivergent)
21250 return TRI->getEquivalentSGPRClass(RC);
21251 if (
TRI->isSGPRClass(RC) && isDivergent) {
21252 if (Subtarget->hasGFX90AInsts())
21253 return TRI->getEquivalentAVClass(RC);
21254 return TRI->getEquivalentVGPRClass(RC);
21267 unsigned WaveSize) {
21272 if (!
IT ||
IT->getBitWidth() != WaveSize)
21277 if (!Visited.
insert(V).second)
21279 bool Result =
false;
21280 for (
const auto *U : V->users()) {
21282 if (V == U->getOperand(1)) {
21287 case Intrinsic::amdgcn_if_break:
21288 case Intrinsic::amdgcn_if:
21289 case Intrinsic::amdgcn_else:
21294 if (V == U->getOperand(0)) {
21299 case Intrinsic::amdgcn_end_cf:
21300 case Intrinsic::amdgcn_loop:
21306 Result =
hasCFUser(U, Visited, WaveSize);
21315 const Value *V)
const {
21317 if (CI->isInlineAsm()) {
21326 for (
auto &TC : TargetConstraints) {
21340 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21375 if (
I.getMetadata(
"amdgpu.noclobber"))
21377 if (
I.getMetadata(
"amdgpu.last.use"))
21441 Alignment = RMW->getAlign();
21454 bool FullFlatEmulation =
21456 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21457 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21458 RMW->getType()->isDoubleTy()));
21461 bool ReturnValueIsUsed = !AI->
use_empty();
21470 if (FullFlatEmulation) {
21481 std::prev(BB->
end())->eraseFromParent();
21482 Builder.SetInsertPoint(BB);
21484 Value *LoadedShared =
nullptr;
21485 if (FullFlatEmulation) {
21486 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21487 {Addr},
nullptr,
"is.shared");
21488 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21489 Builder.SetInsertPoint(SharedBB);
21490 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21496 LoadedShared = Clone;
21498 Builder.CreateBr(PhiBB);
21499 Builder.SetInsertPoint(CheckPrivateBB);
21502 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21503 {Addr},
nullptr,
"is.private");
21504 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21506 Builder.SetInsertPoint(PrivateBB);
21508 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21511 Value *LoadedPrivate;
21513 LoadedPrivate = Builder.CreateAlignedLoad(
21514 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21518 LoadedPrivate, RMW->getValOperand());
21520 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21521 RMW->isVolatile());
21529 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21532 Builder.CreateBr(PhiBB);
21534 Builder.SetInsertPoint(GlobalBB);
21538 if (FullFlatEmulation) {
21539 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21548 if (!FullFlatEmulation) {
21553 MDNode *RangeNotPrivate =
21556 LoadedGlobal->
setMetadata(LLVMContext::MD_noalias_addrspace,
21560 Builder.CreateBr(PhiBB);
21562 Builder.SetInsertPoint(PhiBB);
21564 if (ReturnValueIsUsed) {
21567 if (FullFlatEmulation)
21568 Loaded->addIncoming(LoadedShared, SharedBB);
21569 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21570 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21571 Loaded->takeName(AI);
21574 Builder.CreateBr(ExitBB);
21578 unsigned PtrOpIdx) {
21579 Value *PtrOp =
I->getOperand(PtrOpIdx);
21586 I->setOperand(PtrOpIdx, ASCast);
21598 ConstVal && ConstVal->isNullValue() &&
21629 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21637 "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::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static 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
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned AndSaveExecOpc
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmNearestTiesToEven
static const fltSemantics & IEEEhalf()
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
LLVM_READONLY int getExactLog2Abs() const
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents an incoming formal argument to a Function.
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
const Function * getParent() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getCompareOperand()
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
std::optional< ISelOp > Src
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Argument * getArg(unsigned i) const
const SIInstrInfo * getInstrInfo() const override
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool hasKernargSegmentPtr() const
bool hasDispatchID() const
bool hasPrivateSegmentBuffer() const
unsigned getNumFreeUserSGPRs()
bool hasImplicitBufferPtr() const
bool hasPrivateSegmentSize() const
bool hasDispatchPtr() const
bool hasFlatScratchInit() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
int64_t getOffset() const
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
const MDOperand & getOperand(unsigned I) const
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool isWholeWaveFunction() const
bool hasWorkGroupIDZ() const
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
unsigned getBytesInStackArgArea() const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void allocateSpecialInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments at the end of allocated user arguments.
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
OSType getOS() const
Get the parsed operating system type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isFunctionTy() const
True if this is an instance of FunctionType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI const fltSemantics & getFltSemantics() const
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM_ABI void set(Value *Val)
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
@ TowardZeroF32_TowardNegativeF64
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ CLUSTER_WORKGROUP_MAX_ID_X
@ CLUSTER_WORKGROUP_MAX_ID_Z
@ CLUSTER_WORKGROUP_MAX_FLAT_ID
@ CLUSTER_WORKGROUP_MAX_ID_Y
ArgDescriptor WorkItemIDZ
ArgDescriptor WorkItemIDY
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
ArgDescriptor WorkItemIDX
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
unsigned AtomicNoRetBaseOpcode
This struct is a compact representation of a valid (non-zero power of two) alignment.
static ArgDescriptor createStack(unsigned Offset, unsigned Mask=~0u)
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SDValue ConvergenceControlToken
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalize() const